Browse Source

Add delayed actions

v2
Nathaniel Walizer 6 months ago
parent
commit
df0f2a4835
1 changed files with 103 additions and 13 deletions
  1. +103
    -13
      src/linux/port.c

+ 103
- 13
src/linux/port.c View File

@@ -83,6 +83,68 @@ void* nese_alloc(int size) {
* Platform-specific features and controls
*/

#define ACTION_DELAY (60U * 1U)
#define ACTION_NOTIFY (60U * 3U)

typedef struct {
int timer;
int msg_id;
nese_Action action;
} Action_State;

static void action_immediate(Action_State* state, nese_Action action) {
state->action = action;
state->timer = 0;
}

static void action_start(Action_State* state, nese_Action action,
Overlay* overlay) {
if (state->action != Action_OK) {
// We can't do two things at once - cancel the current action
overlay_clear_message(overlay, state->msg_id);
state->action = Action_OK;

} else {
state->action = action;

const char* op = NULL;
if (Action_Load == action) op = "Restoring ...";
else if (Action_Save == action) op = "Saving ...";
else if (Action_Reset == action) op = "Resetting ...";
if (NULL != op) {
state->timer = ACTION_DELAY;
state->msg_id = overlay_add_message(overlay, op, state->timer);
} else {
state->timer = 0;
}
}
}

static nese_Action action_tick(Action_State* state, Overlay* overlay) {
nese_Action action = Action_OK;

if (state->action != Action_OK && --state->timer <= 0) {
action = state->action;
state->action = Action_OK;
overlay_clear_message(overlay, state->msg_id);
}

return action;
}

static int action_notify(nese_Action action, int status, Overlay* overlay) {
int msg_id = 0;
const char* op = NULL;
if (Action_Load == action) op = (status < 0 ? "Restore failed" : "Restored");
else if (Action_Save == action) op = (status < 0 ? "Save failed" : "Saved");
else if (Action_Reset == action) op = "Reset";
if (NULL != op) {
msg_id = overlay_add_message(overlay, op, ACTION_NOTIFY);
}
return msg_id;
}


#define PLAT_FILENAME_SIZE (1024U)

typedef enum {
@@ -98,6 +160,7 @@ typedef struct {
int fps_msg_id;
Platform_Flags flags;
char filename[PLAT_FILENAME_SIZE];
Action_State delayed_action;
} platform_data;


@@ -221,12 +284,21 @@ static nese_Action process_events(nes* sys) {
input->gamepads[0].buttons &= ~mask;
}

} else if (SDL_KEYDOWN == event.type) {
} else {
index = keycode_index(
event.key.keysym.sym,
sdl_action_keycodes, Action_Max
);
if (index >= 0) action = index;
if (index >= 0) {
if (SDL_KEYDOWN == event.type) {
action = index;
} else if ( Action_Load == index ||
Action_Save == index ||
Action_Reset == index) {
// On key release, cancel certain pending delayed actions
action = Action_Cancel;
}
}
}
}
// TODO: Controller inputs
@@ -314,6 +386,8 @@ int nese_frame_ready(void* plat_data) {
status = render_frame_end(&plat->renderer);
}

overlay_step(&plat->overlay);


// TODO: Check status first?

@@ -324,11 +398,10 @@ int nese_frame_ready(void* plat_data) {
break;

case Action_Save:
status = save_state(plat->sys, plat->cart.filename);
break;

case Action_Load:
status = load_state(plat->sys, plat->cart.filename);
case Action_Reset:
case Action_Cancel:
action_start(&plat->delayed_action, action, &plat->overlay);
break;

case Action_FPS:
@@ -346,14 +419,17 @@ int nese_frame_ready(void* plat_data) {

case Action_Menu:
action = game_menu(plat);
if (Action_Reset == action) {
nes_reset(plat->sys);
} else if (Action_Save == action) {
status = save_state(plat->sys, plat->cart.filename);
} else if (Action_Load == action) {
status = load_state(plat->sys, plat->cart.filename);
} else if (Action_Quit == action || NULL == plat->sys->cart_header) {
switch (action) {
case Action_Reset:
case Action_Load:
case Action_Save:
action_immediate(&plat->delayed_action, action);
break;
default:
if (NULL != plat->sys->cart_header) break;
case Action_Quit:
status = -1;
break;
}
// TODO: Other Actions?
break;
@@ -362,6 +438,20 @@ int nese_frame_ready(void* plat_data) {
}

// TODO: Perform more actions?
int action_status = 1;
action = action_tick(&plat->delayed_action, &plat->overlay);
if (Action_Reset == action) {
nes_reset(plat->sys);
action_status = 0;
} else if (Action_Save == action) {
action_status = save_state(plat->sys, plat->cart.filename);
} else if (Action_Load == action) {
action_status = load_state(plat->sys, plat->cart.filename);
}

if (action_status <= 0) {
action_notify(action, action_status, &plat->overlay);
}

if (0 == status) {
plat->t_target += FRAME_TIME_NS;


Loading…
Cancel
Save