From f926e522aef77158e0011ae5ad2cf8805509d6d1 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Sat, 20 Feb 2010 00:31:14 +0100 Subject: [PATCH] rnd-20100220-1-src * started integrating snapshot functionality into Supaplex game engine --- ChangeLog | 3 + src/conftime.h | 2 +- src/game.c | 80 ++++++---------------- src/game_sp/DDScrollBuffer.c | 32 +++++++-- src/game_sp/DDScrollBuffer.h | 1 + src/game_sp/DoGameStuff.c | 14 ++-- src/game_sp/MainGameLoop.c | 4 +- src/game_sp/Murphy.c | 4 +- src/game_sp/export.h | 25 +++++-- src/game_sp/file.c | 29 ++++---- src/game_sp/init.c | 127 +++++++++++++++++++++++++++++++++++ src/game_sp/main.c | 11 +-- src/libgame/Makefile | 2 + src/libgame/libgame.h | 1 + src/libgame/snapshot.c | 55 +++++++++++++++ src/libgame/snapshot.h | 36 ++++++++++ 16 files changed, 325 insertions(+), 101 deletions(-) create mode 100644 src/libgame/snapshot.c create mode 100644 src/libgame/snapshot.h diff --git a/ChangeLog b/ChangeLog index 59251bf1..bb3788ef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2010-02-19 + * started integrating snapshot functionality into Supaplex game engine + 2010-02-16 * fixed bug in native Supaplex engine that broke several demo solutions * fixed bug with re-initializing already existing elements in function diff --git a/src/conftime.h b/src/conftime.h index 04dec544..9c1189a4 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "2010-02-18 09:22" +#define COMPILE_DATE_STRING "2010-02-20 00:28" diff --git a/src/game.c b/src/game.c index f8b9a085..cf7193f8 100644 --- a/src/game.c +++ b/src/game.c @@ -12058,17 +12058,17 @@ static void CheckLevelTime() } else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) { - if (game_sp_info.LevelSolved && - !game_sp_info.GameOver) /* game won */ + if (game_sp.LevelSolved && + !game_sp.GameOver) /* game won */ { PlayerWins(local_player); - game_sp_info.GameOver = TRUE; + game_sp.GameOver = TRUE; AllPlayersGone = TRUE; } - if (game_sp_info.GameOver) /* game lost */ + if (game_sp.GameOver) /* game lost */ AllPlayersGone = TRUE; } @@ -12268,17 +12268,17 @@ void GameActions() } else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) { - if (game_sp_info.LevelSolved && - !game_sp_info.GameOver) /* game won */ + if (game_sp.LevelSolved && + !game_sp.GameOver) /* game won */ { PlayerWins(local_player); - game_sp_info.GameOver = TRUE; + game_sp.GameOver = TRUE; AllPlayersGone = TRUE; } - if (game_sp_info.GameOver) /* game lost */ + if (game_sp.GameOver) /* game lost */ AllPlayersGone = TRUE; } @@ -16413,8 +16413,6 @@ unsigned int RND(int max) /* game engine snapshot handling functions */ /* ------------------------------------------------------------------------- */ -#define ARGS_ADDRESS_AND_SIZEOF(x) (&(x)), (sizeof(x)) - struct EngineSnapshotInfo { /* runtime values for custom element collect score */ @@ -16428,28 +16426,10 @@ struct EngineSnapshotInfo int belt_anim_mode[4 * NUM_BELT_PARTS]; }; -struct EngineSnapshotNodeInfo -{ - void *buffer_orig; - void *buffer_copy; - int size; -}; - static struct EngineSnapshotInfo engine_snapshot_rnd; -static ListNode *engine_snapshot_list = NULL; static char *snapshot_level_identifier = NULL; static int snapshot_level_nr = -1; -void FreeEngineSnapshot() -{ - while (engine_snapshot_list != NULL) - deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key, - checked_free); - - setString(&snapshot_level_identifier, NULL); - snapshot_level_nr = -1; -} - static void SaveEngineSnapshotValues_RND() { static int belt_base_active_element[4] = @@ -16535,36 +16515,26 @@ static void LoadEngineSnapshotValues_RND() } } -static void SaveEngineSnapshotBuffer(void *buffer, int size) -{ - struct EngineSnapshotNodeInfo *bi = - checked_calloc(sizeof(struct EngineSnapshotNodeInfo)); - - bi->buffer_orig = buffer; - bi->buffer_copy = checked_malloc(size); - bi->size = size; - - memcpy(bi->buffer_copy, buffer, size); - - addNodeToList(&engine_snapshot_list, NULL, bi); -} - void SaveEngineSnapshot() { - FreeEngineSnapshot(); /* free previous snapshot, if needed */ - - if (level_editor_test_game) /* do not save snapshots from editor */ + /* do not save snapshots from editor */ + if (level_editor_test_game) return; + /* free previous snapshot buffers, if needed */ + FreeEngineSnapshotBuffers(); + /* copy some special values to a structure better suited for the snapshot */ SaveEngineSnapshotValues_RND(); SaveEngineSnapshotValues_EM(); + SaveEngineSnapshotValues_SP(); /* save values stored in special snapshot structure */ SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_rnd)); SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_em)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(engine_snapshot_sp)); /* save further RND engine values */ @@ -16638,7 +16608,7 @@ void SaveEngineSnapshot() snapshot_level_nr = level_nr; #if 0 - ListNode *node = engine_snapshot_list; + ListNode *node = engine_snapshot_list_rnd; int num_bytes = 0; while (node != NULL) @@ -16652,29 +16622,17 @@ void SaveEngineSnapshot() #endif } -static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi) -{ - memcpy(bi->buffer_orig, bi->buffer_copy, bi->size); -} - void LoadEngineSnapshot() { - ListNode *node = engine_snapshot_list; + /* restore generically stored snapshot buffers */ - if (engine_snapshot_list == NULL) - return; - - while (node != NULL) - { - LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content); - - node = node->next; - } + LoadEngineSnapshotBuffers(); /* restore special values from snapshot structure */ LoadEngineSnapshotValues_RND(); LoadEngineSnapshotValues_EM(); + LoadEngineSnapshotValues_SP(); } boolean CheckEngineSnapshot() diff --git a/src/game_sp/DDScrollBuffer.c b/src/game_sp/DDScrollBuffer.c index 5a89919c..544b169e 100644 --- a/src/game_sp/DDScrollBuffer.c +++ b/src/game_sp/DDScrollBuffer.c @@ -39,6 +39,28 @@ boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; int TEST_flag = 0; +void RestorePlayfield() +{ + int x1 = mScrollX / TILEX - 2; + int y1 = mScrollY / TILEY - 2; + int x2 = mScrollX / TILEX + (SCR_FIELDX - 1) + 2; + int y2 = mScrollY / TILEY + (SCR_FIELDY - 1) + 2; + int x, y; + + DrawFrameIfNeeded(); + + for (y = DisplayMinY; y <= DisplayMaxY; y++) + { + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) + { + DrawFieldNoAnimated(x, y); + DrawFieldAnimated(x, y); + } + } + } +} static void ScrollPlayfield(int dx, int dy) { @@ -184,7 +206,7 @@ void InitScrollPlayfield() ScrollPlayfieldIfNeededExt(TRUE); } -void UpdatePlayfield() +void UpdatePlayfield(boolean force_redraw) { int x, y; #if 1 @@ -198,10 +220,10 @@ void UpdatePlayfield() int element = LowByte(PlayField16[GetSI(x, y)]); int graphic = GfxGraphic[x][y]; int sync_frame = GfxFrame[x][y]; -#if 1 - boolean redraw = FALSE; -#else - boolean redraw = TRUE; // !!! TEST ONLY -- ALWAYS REDRAW !!! + boolean redraw = force_redraw; + +#if 0 + redraw = TRUE; // !!! TEST ONLY -- ALWAYS REDRAW !!! #endif if (graphic < 0) diff --git a/src/game_sp/DDScrollBuffer.h b/src/game_sp/DDScrollBuffer.h index 402cdcad..aaaf63ab 100644 --- a/src/game_sp/DDScrollBuffer.h +++ b/src/game_sp/DDScrollBuffer.h @@ -22,6 +22,7 @@ extern int TEST_flag; extern void InitScrollPlayfield(); extern void UpdatePlayfield(); +extern void RestorePlayfield(); extern void DDScrollBuffer_Blt_Ext(Bitmap *); extern void DDScrollBuffer_Blt(); diff --git a/src/game_sp/DoGameStuff.c b/src/game_sp/DoGameStuff.c index 8e7d8830..81f4a954 100644 --- a/src/game_sp/DoGameStuff.c +++ b/src/game_sp/DoGameStuff.c @@ -77,8 +77,8 @@ int subDoGameStuff() { #if 1 if (LeadOutCounter == 0 && - !game_sp_info.LevelSolved && - !game_sp_info.GameOver) + !game_sp.LevelSolved && + !game_sp.GameOver) #else if (LeadOutCounter == 0) #endif @@ -101,7 +101,7 @@ int subDoGameStuff() #if 1 /* give Murphy some more time (LeadOutCounter) to reach the exit */ #else - game_sp_info.GameOver = TRUE; + game_sp.GameOver = TRUE; #endif #endif @@ -110,19 +110,19 @@ int subDoGameStuff() #if 1 #if 0 printf("::: *** %d, %d, %d\n", KillMurphyFlag, - game_sp_info.LevelSolved, game_sp_info.GameOver); + game_sp.LevelSolved, game_sp.GameOver); #endif #if 0 if (KillMurphyFlag == 1 && - !game_sp_info.LevelSolved && - !game_sp_info.GameOver) + !game_sp.LevelSolved && + !game_sp.GameOver) { #if 1 printf("::: DoGameStuff.c: !!!!!!!!!! GAME OVER !!!!!!!!!!\n"); #endif - game_sp_info.GameOver = TRUE; + game_sp.GameOver = TRUE; } #endif #endif diff --git a/src/game_sp/MainGameLoop.c b/src/game_sp/MainGameLoop.c index 60a479db..028c861e 100644 --- a/src/game_sp/MainGameLoop.c +++ b/src/game_sp/MainGameLoop.c @@ -293,8 +293,8 @@ locExitMainGameLoop: #if 1 /* if the game is not won when reaching this point, then it is lost */ - if (!game_sp_info.LevelSolved) - game_sp_info.GameOver = TRUE; + if (!game_sp.LevelSolved) + game_sp.GameOver = TRUE; #endif #if 1 diff --git a/src/game_sp/Murphy.c b/src/game_sp/Murphy.c index e104a5c7..f42d8da9 100644 --- a/src/game_sp/Murphy.c +++ b/src/game_sp/Murphy.c @@ -1073,12 +1073,12 @@ loc_g_6756: return; #if 1 - if (!game_sp_info.LevelSolved) + if (!game_sp.LevelSolved) printf("::: Murphy.c: !!!!!!!!!! LEVEL %d SOLVED !!!!!!!!!!\n",LevelNumber); #endif #if 1 - game_sp_info.LevelSolved = TRUE; + game_sp.LevelSolved = TRUE; #endif subSoundFXExit(); diff --git a/src/game_sp/export.h b/src/game_sp/export.h index f54bb28a..bfeab9dd 100644 --- a/src/game_sp/export.h +++ b/src/game_sp/export.h @@ -14,15 +14,17 @@ #define SP_NUM_LEVELS_PER_PACKAGE 111 -#define SP_PLAYFIELD_WIDTH 60 -#define SP_PLAYFIELD_HEIGHT 24 +#define SP_STD_PLAYFIELD_WIDTH 60 +#define SP_STD_PLAYFIELD_HEIGHT 24 #define SP_LEVEL_NAME_LEN 23 #define SP_MAX_SPECIAL_PORTS 10 #define SP_HEADER_SIZE 96 -#define SP_PLAYFIELD_SIZE (SP_PLAYFIELD_WIDTH * \ - SP_PLAYFIELD_HEIGHT) -#define SP_LEVEL_SIZE (SP_HEADER_SIZE + SP_PLAYFIELD_SIZE) +#define SP_STD_PLAYFIELD_SIZE (SP_STD_PLAYFIELD_WIDTH * \ + SP_STD_PLAYFIELD_HEIGHT) +#define SP_MAX_PLAYFIELD_SIZE (SP_MAX_PLAYFIELD_WIDTH * \ + SP_MAX_PLAYFIELD_HEIGHT) +#define SP_STD_LEVEL_SIZE (SP_HEADER_SIZE + SP_STD_PLAYFIELD_SIZE) #if 0 #define SP_SCREEN_BUFFER_XSIZE (SCR_FIELDX + 2) @@ -87,6 +89,9 @@ struct GameInfo_SP { boolean LevelSolved; boolean GameOver; + + /* needed for engine snapshots */ + int preceding_buffer_size; }; struct DemoInfo_SP @@ -132,6 +137,14 @@ struct GraphicInfo_SP struct EngineSnapshotInfo_SP { struct GameInfo_SP game_sp; + + int PlayField16[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; + byte PlayField8[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; + byte DisPlayField[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; + + int AnimationPosTable[SP_MAX_PLAYFIELD_SIZE]; + byte AnimationSubTable[SP_MAX_PLAYFIELD_SIZE]; + byte TerminalState[SP_MAX_PLAYFIELD_SIZE + SP_HEADER_SIZE]; }; @@ -140,7 +153,7 @@ struct EngineSnapshotInfo_SP /* ------------------------------------------------------------------------- */ extern struct GlobalInfo_SP global_sp_info; -extern struct GameInfo_SP game_sp_info; +extern struct GameInfo_SP game_sp; extern struct LevelInfo_SP native_sp_level; extern struct GraphicInfo_SP graphic_info_sp_object[TILE_MAX][8]; extern struct GraphicInfo_SP graphic_info_sp_player[MAX_PLAYERS][SPR_MAX][8]; diff --git a/src/game_sp/file.c b/src/game_sp/file.c index 2ba322d7..5a525214 100644 --- a/src/game_sp/file.c +++ b/src/game_sp/file.c @@ -13,8 +13,8 @@ void setLevelInfoToDefaults_SP() char *empty_title = "-------- EMPTY --------"; int i, x, y; - native_sp_level.width = SP_PLAYFIELD_WIDTH; - native_sp_level.height = SP_PLAYFIELD_HEIGHT; + native_sp_level.width = SP_STD_PLAYFIELD_WIDTH; + native_sp_level.height = SP_STD_PLAYFIELD_HEIGHT; for (x = 0; x < native_sp_level.width; x++) for (y = 0; y < native_sp_level.height; y++) @@ -110,6 +110,9 @@ void copyInternalEngineVars_SP() preceding_buffer_size += 8; /* eight 16-bit integer values */ #endif + /* needed for engine snapshots */ + game_sp.preceding_buffer_size = preceding_buffer_size; + LInfo = native_sp_level.header; FieldWidth = native_sp_level.width; @@ -416,9 +419,9 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos) strSuffixLower(filename, ".mpx")); boolean demo_available = is_single_level_file; boolean is_mpx_file = strSuffixLower(filename, ".mpx"); - int file_seek_pos = level_pos * SP_LEVEL_SIZE; - int level_width = SP_PLAYFIELD_WIDTH; - int level_height = SP_PLAYFIELD_HEIGHT; + int file_seek_pos = level_pos * SP_STD_LEVEL_SIZE; + int level_width = SP_STD_PLAYFIELD_WIDTH; + int level_height = SP_STD_PLAYFIELD_HEIGHT; /* always start with reliable default values */ setLevelInfoToDefaults_SP(); @@ -611,8 +614,8 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos) multipart_xpos, multipart_ypos, multipart_level.header.LevelTitle); #endif - if (multipart_xpos * SP_PLAYFIELD_WIDTH > SP_MAX_PLAYFIELD_WIDTH || - multipart_ypos * SP_PLAYFIELD_HEIGHT > SP_MAX_PLAYFIELD_HEIGHT) + if (multipart_xpos * SP_STD_PLAYFIELD_WIDTH > SP_MAX_PLAYFIELD_WIDTH || + multipart_ypos * SP_STD_PLAYFIELD_HEIGHT > SP_MAX_PLAYFIELD_HEIGHT) { Error(ERR_WARN, "multi-part level is too big -- ignoring part of it"); @@ -620,17 +623,17 @@ boolean LoadNativeLevel_SP(char *filename, int level_pos) } multipart_level.width = MAX(multipart_level.width, - multipart_xpos * SP_PLAYFIELD_WIDTH); + multipart_xpos * SP_STD_PLAYFIELD_WIDTH); multipart_level.height = MAX(multipart_level.height, - multipart_ypos * SP_PLAYFIELD_HEIGHT); + multipart_ypos * SP_STD_PLAYFIELD_HEIGHT); /* copy level part at the right position of multi-part level */ - for (x = 0; x < SP_PLAYFIELD_WIDTH; x++) + for (x = 0; x < SP_STD_PLAYFIELD_WIDTH; x++) { - for (y = 0; y < SP_PLAYFIELD_HEIGHT; y++) + for (y = 0; y < SP_STD_PLAYFIELD_HEIGHT; y++) { - int start_x = (multipart_xpos - 1) * SP_PLAYFIELD_WIDTH; - int start_y = (multipart_ypos - 1) * SP_PLAYFIELD_HEIGHT; + int start_x = (multipart_xpos - 1) * SP_STD_PLAYFIELD_WIDTH; + int start_y = (multipart_ypos - 1) * SP_STD_PLAYFIELD_HEIGHT; multipart_level.playfield[start_x + x][start_y + y] = native_sp_level.playfield[x][y]; diff --git a/src/game_sp/init.c b/src/game_sp/init.c index 5fb36f19..76e690e1 100644 --- a/src/game_sp/init.c +++ b/src/game_sp/init.c @@ -7,6 +7,8 @@ Bitmap *sp_objects; Bitmap *screenBitmap; +struct EngineSnapshotInfo_SP engine_snapshot_sp; + static void init_struct_functions() { Stage.Blt = &DDScrollBuffer_Blt; @@ -76,3 +78,128 @@ unsigned int InitEngineRandom_SP(long seed) return (unsigned int) seed; } + + +/* ------------------------------------------------------------------------- */ +/* Supaplex game engine snapshot handling functions */ +/* ------------------------------------------------------------------------- */ + +static ListNode *engine_snapshot_list_sp = NULL; + +void SaveEngineSnapshotValues_SP() +{ + int i; + + engine_snapshot_sp.game_sp = game_sp; + + /* these arrays have playfield-size dependent variable size */ + + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.PlayField16[i] = PlayField16[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.PlayField8[i] = PlayField8[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.DisPlayField[i] = DisPlayField[i]; + + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + engine_snapshot_sp.AnimationPosTable[i] = AnimationPosTable[i]; + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + engine_snapshot_sp.AnimationSubTable[i] = AnimationSubTable[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + engine_snapshot_sp.TerminalState[i] = TerminalState[i]; + + /* store special data into engine snapshot buffers */ + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldWidth)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldHeight)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FieldMax)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(LevelMax)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(FileMax)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TimerVar)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RandomSeed)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(TerminalMaxCycles)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollX_last)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(mScrollY_last)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenScrollXPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScreenScrollYPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMinX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMinY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMaxX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayMaxY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayWidth)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(DisplayHeight)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(InfotronsNeeded)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(KillMurphyFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyMoveCounter)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyExplodePos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(SplitMoveFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseMurphyPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyPosIndex)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyXPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyYPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyScreenXPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyScreenYPos)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MurphyVarFaceLeft)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskCount)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleaseFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(MovingPictureSequencePhase)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(RedDiskReleasePhase)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScratchGravity)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GravityFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(SnikSnaksElectronsFrozen)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(UpdateTimeFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(UpdatedFlag)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(YellowDisksExploded)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(YawnSleepCounter)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(LeadOutCounter)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxElementLast)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxGraphicLast)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxGraphic)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(GfxFrame)); + + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMinX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMinY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMaxX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollMaxY)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollX)); + SaveEngineSnapshotBuffer(ARGS_ADDRESS_AND_SIZEOF(ScrollY)); + + SaveEngineSnapshotBuffer(&PlayField16[-game_sp.preceding_buffer_size], + game_sp.preceding_buffer_size * sizeof(int)); +} + +void LoadEngineSnapshotValues_SP() +{ + int i; + + /* stored engine snapshot buffers already restored at this point */ + + game_sp = engine_snapshot_sp.game_sp; + + /* these arrays have playfield-size dependent variable size */ + + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + PlayField16[i] = engine_snapshot_sp.PlayField16[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + PlayField8[i] = engine_snapshot_sp.PlayField8[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + DisPlayField[i] = engine_snapshot_sp.DisPlayField[i]; + + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + AnimationPosTable[i] = engine_snapshot_sp.AnimationPosTable[i]; + for (i = 0; i < FieldWidth * (FieldHeight - 2); i++) + AnimationSubTable[i] = engine_snapshot_sp.AnimationSubTable[i]; + for (i = 0; i < FieldWidth * FieldHeight + HeaderSize; i++) + TerminalState[i] = engine_snapshot_sp.TerminalState[i]; + + RedrawPlayfield_SP(TRUE); +} diff --git a/src/game_sp/main.c b/src/game_sp/main.c index 38e54a36..f30aa0db 100644 --- a/src/game_sp/main.c +++ b/src/game_sp/main.c @@ -3,7 +3,7 @@ #include "global.h" -struct GameInfo_SP game_sp_info; +struct GameInfo_SP game_sp; struct LevelInfo_SP native_sp_level; @@ -19,8 +19,8 @@ void InitGameEngine_SP() gfx.anim_random_frame = -1; // (use simple, ad-hoc random numbers) - game_sp_info.LevelSolved = FALSE; - game_sp_info.GameOver = FALSE; + game_sp.LevelSolved = FALSE; + game_sp.GameOver = FALSE; menBorder.Checked = setup.sp_show_border_elements; @@ -65,7 +65,10 @@ void RedrawPlayfield_SP(boolean force_redraw) { // subDisplayLevel(); - UpdatePlayfield(); + if (force_redraw) + RestorePlayfield(); + + UpdatePlayfield(force_redraw); BackToFront_SP(); } diff --git a/src/libgame/Makefile b/src/libgame/Makefile index 6148a985..140e9fd9 100644 --- a/src/libgame/Makefile +++ b/src/libgame/Makefile @@ -13,6 +13,7 @@ SRCS = system.c \ text.c \ sound.c \ joystick.c \ + snapshot.c \ toons.c \ pcx.c \ image.c \ @@ -28,6 +29,7 @@ OBJS = system.o \ gadgets.o \ text.o \ sound.o \ + snapshot.o \ joystick.o \ toons.o \ pcx.o \ diff --git a/src/libgame/libgame.h b/src/libgame/libgame.h index 6f4c20c2..d1f05c82 100644 --- a/src/libgame/libgame.h +++ b/src/libgame/libgame.h @@ -23,6 +23,7 @@ #include "gadgets.h" #include "text.h" #include "sound.h" +#include "snapshot.h" #include "joystick.h" #include "toons.h" #include "image.h" diff --git a/src/libgame/snapshot.c b/src/libgame/snapshot.c new file mode 100644 index 00000000..d28ae349 --- /dev/null +++ b/src/libgame/snapshot.c @@ -0,0 +1,55 @@ +/*********************************************************** +* Artsoft Retro-Game Library * +*----------------------------------------------------------* +* (c) 1995-2006 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * +*----------------------------------------------------------* +* snapshot.c * +***********************************************************/ + +#include "snapshot.h" + + +static ListNode *engine_snapshot_list = NULL; + +void SaveEngineSnapshotBuffer(void *buffer, int size) +{ + struct EngineSnapshotNodeInfo *bi = + checked_calloc(sizeof(struct EngineSnapshotNodeInfo)); + + bi->buffer_orig = buffer; + bi->buffer_copy = checked_malloc(size); + bi->size = size; + + memcpy(bi->buffer_copy, buffer, size); + + addNodeToList(&engine_snapshot_list, NULL, bi); +} + +static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi) +{ + memcpy(bi->buffer_orig, bi->buffer_copy, bi->size); +} + +void LoadEngineSnapshotBuffers() +{ + ListNode *node = engine_snapshot_list; + + while (node != NULL) + { + LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content); + + node = node->next; + } +} + +void FreeEngineSnapshotBuffers() +{ + while (engine_snapshot_list != NULL) + deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key, + checked_free); +} diff --git a/src/libgame/snapshot.h b/src/libgame/snapshot.h new file mode 100644 index 00000000..706fc054 --- /dev/null +++ b/src/libgame/snapshot.h @@ -0,0 +1,36 @@ +/*********************************************************** +* Artsoft Retro-Game Library * +*----------------------------------------------------------* +* (c) 1995-2006 Artsoft Entertainment * +* Holger Schemel * +* Detmolder Strasse 189 * +* 33604 Bielefeld * +* Germany * +* e-mail: info@artsoft.org * +*----------------------------------------------------------* +* snapshot.h * +***********************************************************/ + +#ifndef SNAPSHOT_H +#define SNAPSHOT_H + +#include "system.h" +#include "misc.h" + + +/* needed for comfortably saving engine snapshot buffers */ +#define ARGS_ADDRESS_AND_SIZEOF(x) (&(x)), (sizeof(x)) + +struct EngineSnapshotNodeInfo +{ + void *buffer_orig; + void *buffer_copy; + int size; +}; + + +void SaveEngineSnapshotBuffer(void *buffer, int size); +void LoadEngineSnapshotBuffers(); +void FreeEngineSnapshotBuffers(); + +#endif /* SNAPSHOT_H */ -- 2.34.1