X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=02861925e981cb2510b22c683f206a60cdef1afa;hb=686d4883428879e2e882222a6579e376d9e4ac4c;hp=ba066ed9bd6f740064244ccbbbf6d1f775ceded0;hpb=3ff2e8a0b5c27b99a9920bdf5ed82bc41bf40181;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index ba066ed9..02861925 100644 --- a/src/game.c +++ b/src/game.c @@ -15,6 +15,7 @@ #include "init.h" #include "tools.h" #include "screens.h" +#include "events.h" #include "files.h" #include "tape.h" #include "network.h" @@ -970,13 +971,15 @@ static struct GamePanelControlInfo game_panel_controls[] = #define GAME_CTRL_ID_STOP 0 #define GAME_CTRL_ID_PAUSE 1 #define GAME_CTRL_ID_PLAY 2 -#define SOUND_CTRL_ID_MUSIC 3 -#define SOUND_CTRL_ID_LOOPS 4 -#define SOUND_CTRL_ID_SIMPLE 5 -#define GAME_CTRL_ID_SAVE 6 -#define GAME_CTRL_ID_LOAD 7 +#define GAME_CTRL_ID_UNDO 3 +#define GAME_CTRL_ID_REDO 4 +#define GAME_CTRL_ID_SAVE 5 +#define GAME_CTRL_ID_LOAD 6 +#define SOUND_CTRL_ID_MUSIC 7 +#define SOUND_CTRL_ID_LOOPS 8 +#define SOUND_CTRL_ID_SIMPLE 9 -#define NUM_GAME_BUTTONS 8 +#define NUM_GAME_BUTTONS 10 /* forward declaration for internal use */ @@ -2519,17 +2522,11 @@ void DisplayGameControlValues() height = graphic_info[graphic].height * size / TILESIZE; if (draw_masked) - { - SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc, - dst_x - src_x, dst_y - src_y); BlitBitmapMasked(src_bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y); - } else - { BlitBitmap(src_bitmap, drawto, src_x, src_y, width, height, dst_x, dst_y); - } } } else if (type == TYPE_STRING) @@ -2581,7 +2578,7 @@ void DisplayGameControlValues() void UpdateAndDisplayGameControlValues() { - if (tape.warp_forward) + if (tape.deactivate_display) return; UpdateGameControlValues(); @@ -3037,6 +3034,14 @@ static void InitGameEngine() setup.scroll_delay ? setup.scroll_delay_value : 0); game.scroll_delay_value = MIN(MAX(MIN_SCROLL_DELAY, game.scroll_delay_value), MAX_SCROLL_DELAY); + + /* ---------- initialize game engine snapshots ---------------------------- */ + for (i = 0; i < MAX_PLAYERS; i++) + game.snapshot.last_action[i] = 0; + game.snapshot.changed_action = FALSE; + game.snapshot.mode = SNAPSHOT_MODE_MOVE; + + FreeEngineSnapshotList(); } int get_num_special_action(int element, int action_first, int action_last) @@ -3915,6 +3920,14 @@ void InitGame() FadeIn(REDRAW_FIELD); +#if 1 + // full screen redraw is required at this point in the following cases: + // - special editor door undrawn when game was started from level editor + // - drawing area (playfield) was changed and has to be removed completely + redraw_mask = REDRAW_ALL; + BackToFront(); +#endif + if (!game.restart_level) { /* copy default game door content to main double buffer */ @@ -3989,6 +4002,8 @@ void InitGame() } game.restart_level = FALSE; + + SaveEngineSnapshotToList(); } void UpdateEngineValues(int actual_scroll_x, int actual_scroll_y) @@ -5007,7 +5022,6 @@ void DrawRelocateScreen(int old_x, int old_y, int x, int y, int move_dir, /* scroll in two steps of half tile size to make things smoother */ BlitBitmap(drawto_field, window, fx, fy, SXSIZE, SYSIZE, SX, SY); - FlushDisplay(); Delay(wait_delay_value); /* scroll second step to align at full tile size */ @@ -10667,6 +10681,37 @@ static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting) } } +static void CheckSaveEngineSnapshot(struct PlayerInfo *player) +{ + static boolean player_was_moving = FALSE; + static boolean player_was_snapping = FALSE; + static boolean player_was_dropping = FALSE; + + if ((!player->is_moving && player_was_moving) || + (player->MovPos == 0 && player_was_moving) || + (player->is_snapping && !player_was_snapping) || + (player->is_dropping && !player_was_dropping)) + { + if (!SaveEngineSnapshotToList()) + return; + + player_was_moving = FALSE; + player_was_snapping = TRUE; + player_was_dropping = TRUE; + } + else + { + if (player->is_moving) + player_was_moving = TRUE; + + if (!player->is_snapping) + player_was_snapping = FALSE; + + if (!player->is_dropping) + player_was_dropping = FALSE; + } +} + static void CheckSingleStepMode(struct PlayerInfo *player) { if (tape.single_step && tape.recording && !tape.pausing) @@ -10679,6 +10724,8 @@ static void CheckSingleStepMode(struct PlayerInfo *player) SnapField(player, 0, 0); /* stop snapping */ } } + + CheckSaveEngineSnapshot(player); } static byte PlayerActions(struct PlayerInfo *player, byte player_action) @@ -10831,6 +10878,9 @@ static void CheckLevelTime() DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime); } + if (tape.recording || tape.playing) + DrawVideoDisplay(VIDEO_STATE_FRAME_ON, FrameCounter); + UpdateAndDisplayGameControlValues(); } @@ -10912,6 +10962,23 @@ void GameActions() byte tape_action[MAX_PLAYERS]; int i; + for (i = 0; i < MAX_PLAYERS; i++) + { + struct PlayerInfo *player = &stored_player[i]; + + // allow engine snapshot if movement attempt was stopped + if ((game.snapshot.last_action[i] & KEY_MOTION) != 0 && + (player->action & KEY_MOTION) == 0) + game.snapshot.changed_action = TRUE; + + // allow engine snapshot in case of snapping/dropping attempt + if ((game.snapshot.last_action[i] & KEY_BUTTON) == 0 && + (player->action & KEY_BUTTON) != 0) + game.snapshot.changed_action = TRUE; + + game.snapshot.last_action[i] = player->action; + } + /* detect endless loops, caused by custom element programming */ if (recursion_loop_detected && recursion_loop_depth == 0) { @@ -11074,7 +11141,8 @@ void GameActions() TapeRecordAction(tape_action); #if USE_NEW_PLAYER_ASSIGNMENTS - if (game.team_mode) + // !!! also map player actions in single player mode !!! + // if (game.team_mode) { byte mapped_action[MAX_PLAYERS]; @@ -12303,6 +12371,9 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) if (tape.single_step && tape.recording && !tape.pausing && !player->programmed_action) TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + + if (!player->programmed_action) + CheckSaveEngineSnapshot(player); } } @@ -14546,22 +14617,22 @@ static void LoadEngineSnapshotValues_RND() } } -void FreeEngineSnapshot() +void FreeEngineSnapshotSingle() { - FreeEngineSnapshotBuffers(); + FreeSnapshotSingle(); setString(&snapshot_level_identifier, NULL); snapshot_level_nr = -1; } -void SaveEngineSnapshot() +void FreeEngineSnapshotList() { - /* do not save snapshots from editor */ - if (level_editor_test_game) - return; + FreeSnapshotList(); +} - /* free previous snapshot buffers, if needed */ - FreeEngineSnapshotBuffers(); +ListNode *SaveEngineSnapshotBuffers() +{ + ListNode *buffers = NULL; /* copy some special values to a structure better suited for the snapshot */ @@ -14570,82 +14641,82 @@ void SaveEngineSnapshot() if (level.game_engine_type == GAME_ENGINE_TYPE_EM) SaveEngineSnapshotValues_EM(); if (level.game_engine_type == GAME_ENGINE_TYPE_SP) - SaveEngineSnapshotValues_SP(); + SaveEngineSnapshotValues_SP(&buffers); /* save values stored in special snapshot structure */ if (level.game_engine_type == GAME_ENGINE_TYPE_RND) - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd)); if (level.game_engine_type == GAME_ENGINE_TYPE_EM) - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em)); if (level.game_engine_type == GAME_ENGINE_TYPE_SP) - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp)); /* save further RND engine values */ - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(stored_player)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(game)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(tape)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZX)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ZY)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitX)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExitY)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FrameCounter)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeFrames)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimePlayed)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimeLeft)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TapeTime)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovDir)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenMovPos)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenGfxPos)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Feld)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovPos)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDir)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovDelay)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeDelay)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangePage)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CustomValue)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Store2)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(StorePlayer)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Back)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(AmoebaNr)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustMoving)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(WasJustFalling)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CheckCollision)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(CheckImpact)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Stop)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(Pushed)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeCount)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ChangeEvent)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodePhase)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeDelay)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ExplodeField)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RunnerVisit)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(PlayerVisit)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxFrame)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxRandom)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxElement)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxAction)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxDir)); - - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_x)); - SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(scroll_y)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(stored_player)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(game)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(tape)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZX)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ZY)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitX)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExitY)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(FrameCounter)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimeFrames)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimePlayed)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TimeLeft)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(TapeTime)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenMovDir)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenMovPos)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScreenGfxPos)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ScrollStepSize)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AllPlayersGone)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaCnt2)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Feld)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovPos)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovDir)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(MovDelay)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeDelay)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangePage)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CustomValue)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Store)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Store2)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(StorePlayer)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Back)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(AmoebaNr)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(WasJustMoving)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(WasJustFalling)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CheckCollision)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(CheckImpact)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Stop)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(Pushed)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeCount)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ChangeEvent)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodePhase)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodeDelay)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(ExplodeField)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(RunnerVisit)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(PlayerVisit)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxFrame)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxRandom)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxElement)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxAction)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(GfxDir)); + + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(scroll_x)); + SaveSnapshotBuffer(&buffers, ARGS_ADDRESS_AND_SIZEOF(scroll_y)); /* save level identification information */ @@ -14665,14 +14736,41 @@ void SaveEngineSnapshot() printf("::: size of engine snapshot: %d bytes\n", num_bytes); #endif + + return buffers; +} + +void SaveEngineSnapshotSingle() +{ + ListNode *buffers = SaveEngineSnapshotBuffers(); + + /* finally save all snapshot buffers to single snapshot */ + SaveSnapshotSingle(buffers); } -void LoadEngineSnapshot() +boolean SaveEngineSnapshotToList() { - /* restore generically stored snapshot buffers */ + boolean save_snapshot = + (FrameCounter == 0 || + (game.snapshot.mode == SNAPSHOT_MODE_STEP) || + (game.snapshot.mode == SNAPSHOT_MODE_MOVE && + game.snapshot.changed_action)); - LoadEngineSnapshotBuffers(); + game.snapshot.changed_action = FALSE; + if (!save_snapshot) + return FALSE; + + ListNode *buffers = SaveEngineSnapshotBuffers(); + + /* finally save all snapshot buffers to snapshot list */ + SaveSnapshotToList(buffers); + + return TRUE; +} + +void LoadEngineSnapshotValues() +{ /* restore special values from snapshot structure */ if (level.game_engine_type == GAME_ENGINE_TYPE_RND) @@ -14683,6 +14781,27 @@ void LoadEngineSnapshot() LoadEngineSnapshotValues_SP(); } +void LoadEngineSnapshotSingle() +{ + LoadSnapshotSingle(); + + LoadEngineSnapshotValues(); +} + +void LoadEngineSnapshot_Undo(int steps) +{ + LoadSnapshotFromList_Older(steps); + + LoadEngineSnapshotValues(); +} + +void LoadEngineSnapshot_Redo(int steps) +{ + LoadSnapshotFromList_Newer(steps); + + LoadEngineSnapshotValues(); +} + boolean CheckEngineSnapshot() { return (strEqual(snapshot_level_identifier, leveldir_current->identifier) && @@ -14695,7 +14814,7 @@ boolean CheckEngineSnapshot() static struct { int graphic; - struct Rect *pos; + struct XY *pos; int gadget_id; char *infotext; } gamebutton_info[NUM_GAME_BUTTONS] = @@ -14713,16 +14832,12 @@ static struct GAME_CTRL_ID_PLAY, "play game" }, { - IMG_GAME_BUTTON_GFX_SOUND_MUSIC, &game.button.sound_music, - SOUND_CTRL_ID_MUSIC, "background music on/off" + IMG_GAME_BUTTON_GFX_UNDO, &game.button.undo, + GAME_CTRL_ID_UNDO, "undo step" }, { - IMG_GAME_BUTTON_GFX_SOUND_LOOPS, &game.button.sound_loops, - SOUND_CTRL_ID_LOOPS, "sound loops on/off" - }, - { - IMG_GAME_BUTTON_GFX_SOUND_SIMPLE, &game.button.sound_simple, - SOUND_CTRL_ID_SIMPLE, "normal sounds on/off" + IMG_GAME_BUTTON_GFX_REDO, &game.button.redo, + GAME_CTRL_ID_REDO, "redo step" }, { IMG_GAME_BUTTON_GFX_SAVE, &game.button.save, @@ -14731,6 +14846,18 @@ static struct { IMG_GAME_BUTTON_GFX_LOAD, &game.button.load, GAME_CTRL_ID_LOAD, "load game" + }, + { + IMG_GAME_BUTTON_GFX_SOUND_MUSIC, &game.button.sound_music, + SOUND_CTRL_ID_MUSIC, "background music on/off" + }, + { + IMG_GAME_BUTTON_GFX_SOUND_LOOPS, &game.button.sound_loops, + SOUND_CTRL_ID_LOOPS, "sound loops on/off" + }, + { + IMG_GAME_BUTTON_GFX_SOUND_SIMPLE, &game.button.sound_simple, + SOUND_CTRL_ID_SIMPLE, "normal sounds on/off" } }; @@ -14741,7 +14868,7 @@ void CreateGameButtons() for (i = 0; i < NUM_GAME_BUTTONS; i++) { struct GraphicInfo *gfx = &graphic_info[gamebutton_info[i].graphic]; - struct Rect *pos = gamebutton_info[i].pos; + struct XY *pos = gamebutton_info[i].pos; struct GadgetInfo *gi; int button_type; boolean checked; @@ -14775,6 +14902,13 @@ void CreateGameButtons() checked = FALSE; event_mask = GD_EVENT_RELEASED; } + else if (id == GAME_CTRL_ID_UNDO || + id == GAME_CTRL_ID_REDO) + { + button_type = GD_TYPE_NORMAL_BUTTON; + checked = FALSE; + event_mask = GD_EVENT_PRESSED | GD_EVENT_REPEATED; + } else { button_type = GD_TYPE_CHECK_BUTTON; @@ -14818,12 +14952,32 @@ void FreeGameButtons() FreeGadget(game_gadget[i]); } +void MapStopPlayButtons() +{ + UnmapGadget(game_gadget[GAME_CTRL_ID_UNDO]); + UnmapGadget(game_gadget[GAME_CTRL_ID_REDO]); + + MapGadget(game_gadget[GAME_CTRL_ID_STOP]); + MapGadget(game_gadget[GAME_CTRL_ID_PLAY]); +} + +void MapUndoRedoButtons() +{ + UnmapGadget(game_gadget[GAME_CTRL_ID_STOP]); + UnmapGadget(game_gadget[GAME_CTRL_ID_PLAY]); + + MapGadget(game_gadget[GAME_CTRL_ID_UNDO]); + MapGadget(game_gadget[GAME_CTRL_ID_REDO]); +} + void MapGameButtons() { int i; for (i = 0; i < NUM_GAME_BUTTONS; i++) - MapGadget(game_gadget[i]); + if (i != GAME_CTRL_ID_UNDO && + i != GAME_CTRL_ID_REDO) + MapGadget(game_gadget[i]); } void UnmapGameButtons() @@ -14845,8 +14999,45 @@ void RedrawGameButtons() redraw_mask &= ~REDRAW_ALL; } -static void HandleGameButtonsExt(int id) +void GameUndoRedoExt() +{ + ClearPlayerAction(); + + tape.pausing = TRUE; + + RedrawPlayfield(); + UpdateAndDisplayGameControlValues(); + + DrawCompleteVideoDisplay(); + DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime); + DrawVideoDisplay(VIDEO_STATE_FRAME_ON, FrameCounter); + + BackToFront(); +} + +void GameUndo(int steps) { + if (!CheckEngineSnapshot()) + return; + + LoadEngineSnapshot_Undo(steps); + + GameUndoRedoExt(); +} + +void GameRedo(int steps) +{ + if (!CheckEngineSnapshot()) + return; + + LoadEngineSnapshot_Redo(steps); + + GameUndoRedoExt(); +} + +static void HandleGameButtonsExt(int id, int button) +{ + int steps = BUTTON_STEPSIZE(button); boolean handle_game_buttons = (game_status == GAME_MODE_PLAYING || (game_status == GAME_MODE_MAIN && tape.show_game_buttons)); @@ -14900,6 +15091,22 @@ static void HandleGameButtonsExt(int id) } break; + case GAME_CTRL_ID_UNDO: + GameUndo(steps); + break; + + case GAME_CTRL_ID_REDO: + GameRedo(steps); + break; + + case GAME_CTRL_ID_SAVE: + TapeQuickSave(); + break; + + case GAME_CTRL_ID_LOAD: + TapeQuickLoad(); + break; + case SOUND_CTRL_ID_MUSIC: if (setup.sound_music) { @@ -14939,14 +15146,6 @@ static void HandleGameButtonsExt(int id) } break; - case GAME_CTRL_ID_SAVE: - TapeQuickSave(); - break; - - case GAME_CTRL_ID_LOAD: - TapeQuickLoad(); - break; - default: break; } @@ -14954,7 +15153,7 @@ static void HandleGameButtonsExt(int id) static void HandleGameButtons(struct GadgetInfo *gi) { - HandleGameButtonsExt(gi->custom_id); + HandleGameButtonsExt(gi->custom_id, gi->event.button); } void HandleSoundButtonKeys(Key key)