X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Flibgame%2Fsnapshot.c;h=a3c2162da54a73215557bdd025b9af5792f65db1;hp=d28ae349e585acb88d8a4c1daa617f0d465d19ab;hb=0d214d4e314f6f42df24be140bb433e980319767;hpb=f926e522aef77158e0011ae5ad2cf8805509d6d1 diff --git a/src/libgame/snapshot.c b/src/libgame/snapshot.c index d28ae349..a3c2162d 100644 --- a/src/libgame/snapshot.c +++ b/src/libgame/snapshot.c @@ -1,25 +1,39 @@ -/*********************************************************** -* Artsoft Retro-Game Library * -*----------------------------------------------------------* -* (c) 1995-2006 Artsoft Entertainment * -* Holger Schemel * -* Detmolder Strasse 189 * -* 33604 Bielefeld * -* Germany * -* e-mail: info@artsoft.org * -*----------------------------------------------------------* -* snapshot.c * -***********************************************************/ +// ============================================================================ +// Artsoft Retro-Game Library +// ---------------------------------------------------------------------------- +// (c) 1995-2014 by Artsoft Entertainment +// Holger Schemel +// info@artsoft.org +// http://www.artsoft.org/ +// ---------------------------------------------------------------------------- +// snapshot.c +// ============================================================================ #include "snapshot.h" -static ListNode *engine_snapshot_list = NULL; +#ifdef DEBUG +#define DEBUG_SNAPSHOTS 0 +#endif -void SaveEngineSnapshotBuffer(void *buffer, int size) +static ListNode *snapshot_single = NULL; +static ListNode *snapshot_list = NULL; +static ListNode *snapshot_current = NULL; + +static int num_snapshots = 0; +static int num_snapshot_buffers = 0; +static int num_snapshot_bytes = 0; +static int next_snapshot_key = 0; + + +// ----------------------------------------------------------------------------- +// functions for handling buffers for a single snapshot +// ----------------------------------------------------------------------------- + +void SaveSnapshotBuffer(ListNode **snapshot_buffers, void *buffer, int size) { - struct EngineSnapshotNodeInfo *bi = - checked_calloc(sizeof(struct EngineSnapshotNodeInfo)); + struct SnapshotNodeInfo *bi = + checked_calloc(sizeof(struct SnapshotNodeInfo)); bi->buffer_orig = buffer; bi->buffer_copy = checked_malloc(size); @@ -27,29 +41,218 @@ void SaveEngineSnapshotBuffer(void *buffer, int size) memcpy(bi->buffer_copy, buffer, size); - addNodeToList(&engine_snapshot_list, NULL, bi); + addNodeToList(snapshot_buffers, NULL, bi); + + num_snapshot_buffers++; + num_snapshot_bytes += size; } -static void LoadEngineSnapshotBuffer(struct EngineSnapshotNodeInfo *bi) +static void LoadSnapshotBuffer(struct SnapshotNodeInfo *bi) { memcpy(bi->buffer_orig, bi->buffer_copy, bi->size); } -void LoadEngineSnapshotBuffers() +void LoadSnapshotBuffers(ListNode *snapshot_buffers) +{ + while (snapshot_buffers != NULL) + { + LoadSnapshotBuffer((struct SnapshotNodeInfo *)snapshot_buffers->content); + + snapshot_buffers = snapshot_buffers->next; + } +} + +static void FreeSnapshotBuffer(void *bi_raw) { - ListNode *node = engine_snapshot_list; + struct SnapshotNodeInfo *bi = (struct SnapshotNodeInfo *)bi_raw; + + num_snapshot_buffers--; + num_snapshot_bytes -= bi->size; + + checked_free(bi->buffer_copy); + checked_free(bi); +} + +void FreeSnapshotBuffers(ListNode *snapshot_buffers) +{ + while (snapshot_buffers != NULL) + deleteNodeFromList(&snapshot_buffers, NULL, FreeSnapshotBuffer); +} + +// ----------------------------------------------------------------------------- +// functions for handling single shapshot or list of snapshots +// ----------------------------------------------------------------------------- + +static void FreeSnapshot(void *snapshot_buffers_ptr) +{ + FreeSnapshotBuffers(snapshot_buffers_ptr); +} + +void FreeSnapshotSingle() +{ + FreeSnapshotBuffers(snapshot_single); + + snapshot_single = NULL; +} + +static void FreeSnapshotList_UpToNode(ListNode *node) +{ + while (snapshot_list != node) + { +#if DEBUG_SNAPSHOTS + printf("::: FreeSnapshotList_*() [%s, %d, %d]\n", + snapshot_list->key, num_snapshot_buffers, num_snapshot_bytes); +#endif + + deleteNodeFromList(&snapshot_list, snapshot_list->key, FreeSnapshot); + + num_snapshots--; + next_snapshot_key = (snapshot_list ? atoi(snapshot_list->key) + 1 : 0); + } +} + +void FreeSnapshotList() +{ +#if DEBUG_SNAPSHOTS + printf("::: FreeSnapshotList()\n"); +#endif + + FreeSnapshotList_UpToNode(NULL); + + num_snapshots = 0; + num_snapshot_buffers = 0; + num_snapshot_bytes = 0; + next_snapshot_key = 0; + + snapshot_current = NULL; +} + +void ReduceSnapshotList() +{ +#if DEBUG_SNAPSHOTS + printf("::: (Reducing number of snapshots from %d ", + num_snapshots); +#endif + + // maximum number of snapshots exceeded -- thin out list of snapshots + ListNode *node = snapshot_list; + int num_snapshots_to_skip = num_snapshots / 10; + + // do not remove the newest snapshots from the list + while (node && num_snapshots_to_skip--) + node = node->next; - while (node != NULL) + // remove every second snapshot from the remaining list + while (node) { - LoadEngineSnapshotBuffer((struct EngineSnapshotNodeInfo *)node->content); + // never delete the first list node (snapshot at game start) + if (node->next == NULL) + break; + // in alternation, delete one node from the list ... + deleteNodeFromList(&node, node->key, FreeSnapshot); + num_snapshots--; + + // ... and keep one node (which always exists here) + node = node->next; + } + +#if DEBUG_SNAPSHOTS + printf("to %d.)\n", num_snapshots); + +#if 0 + node = snapshot_list; + while (node) + { + printf("::: key: %s\n", node->key); node = node->next; } +#endif +#endif +} + +void SaveSnapshotSingle(ListNode *snapshot_buffers) +{ + if (snapshot_single) + FreeSnapshotSingle(); + + snapshot_single = snapshot_buffers; +} + +void SaveSnapshotToList(ListNode *snapshot_buffers) +{ + if (snapshot_current != snapshot_list) + FreeSnapshotList_UpToNode(snapshot_current); + +#if DEBUG_SNAPSHOTS + printf("::: SaveSnapshotToList() [%d] [%d snapshots, %d buffers, %d bytes]\n", + next_snapshot_key, num_snapshots, + num_snapshot_buffers, num_snapshot_bytes); +#endif + + addNodeToList(&snapshot_list, i_to_a(next_snapshot_key), + snapshot_buffers); + + snapshot_current = snapshot_list; + + num_snapshots++; + next_snapshot_key++; + + if (num_snapshot_bytes > setup.engine_snapshot_memory) + ReduceSnapshotList(); +} + +boolean LoadSnapshotSingle() +{ + if (snapshot_single) + { + LoadSnapshotBuffers(snapshot_single); + + return TRUE; + } + + return FALSE; +} + +boolean LoadSnapshotFromList_Older(int steps) +{ + if (snapshot_current && snapshot_current->next) + { + while (snapshot_current->next && steps--) + snapshot_current = snapshot_current->next; + + LoadSnapshotBuffers(snapshot_current->content); + +#if DEBUG_SNAPSHOTS + printf("::: LoadSnapshotFromList_Older() [%s]\n", snapshot_current->key); +#endif + + return TRUE; + } + + return FALSE; +} + +boolean LoadSnapshotFromList_Newer(int steps) +{ + if (snapshot_current && snapshot_current->prev) + { + while (snapshot_current->prev && steps--) + snapshot_current = snapshot_current->prev; + + LoadSnapshotBuffers(snapshot_current->content); + +#if DEBUG_SNAPSHOTS + printf("::: LoadSnapshotFromList_Newer() [%s]\n", snapshot_current->key); +#endif + + return TRUE; + } + + return FALSE; } -void FreeEngineSnapshotBuffers() +boolean CheckSnapshotList() { - while (engine_snapshot_list != NULL) - deleteNodeFromList(&engine_snapshot_list, engine_snapshot_list->key, - checked_free); + return (snapshot_list ? TRUE : FALSE); }