From 9c8d7bd70a37a61d4a80887a8029bdeea14c61c3 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 1 Jun 2016 18:27:00 +0100 Subject: [PATCH] adventures: Commit regenerated games with save/load and bug fixes --- Applications/games/adv01.c | 264 +++++++++++++++++++++--------------- Applications/games/adv02.c | 264 +++++++++++++++++++++--------------- Applications/games/adv03.c | 264 +++++++++++++++++++++--------------- Applications/games/adv04.c | 264 +++++++++++++++++++++--------------- Applications/games/adv05.c | 264 +++++++++++++++++++++--------------- Applications/games/adv06.c | 264 +++++++++++++++++++++--------------- Applications/games/adv07.c | 264 +++++++++++++++++++++--------------- Applications/games/adv08.c | 264 +++++++++++++++++++++--------------- Applications/games/adv09.c | 264 +++++++++++++++++++++--------------- Applications/games/adv10.c | 264 +++++++++++++++++++++--------------- Applications/games/adv11.c | 264 +++++++++++++++++++++--------------- Applications/games/adv12.c | 264 +++++++++++++++++++++--------------- Applications/games/adv13.c | 264 +++++++++++++++++++++--------------- Applications/games/myst01.c | 264 +++++++++++++++++++++--------------- Applications/games/myst02.c | 264 +++++++++++++++++++++--------------- Applications/games/myst03.c | 264 +++++++++++++++++++++--------------- Applications/games/myst04.c | 264 +++++++++++++++++++++--------------- Applications/games/myst05.c | 264 +++++++++++++++++++++--------------- Applications/games/myst06.c | 264 +++++++++++++++++++++--------------- Applications/games/myst07.c | 264 +++++++++++++++++++++--------------- Applications/games/myst08.c | 264 +++++++++++++++++++++--------------- Applications/games/myst09.c | 264 +++++++++++++++++++++--------------- Applications/games/myst10.c | 264 +++++++++++++++++++++--------------- Applications/games/myst11.c | 264 +++++++++++++++++++++--------------- 24 files changed, 3792 insertions(+), 2544 deletions(-) diff --git a/Applications/games/adv01.c b/Applications/games/adv01.c index db87e7b2..ec8b45a4 100644 --- a/Applications/games/adv01.c +++ b/Applications/games/adv01.c @@ -1,5 +1,6 @@ #define NUM_OBJ 66 #define WORDSIZE 3 +#define GAME_MAGIC 416 #include struct location { @@ -1386,6 +1387,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1398,18 +1412,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1420,6 +1427,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1433,7 +1443,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1686,13 +1696,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1704,6 +1707,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1858,7 +1867,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1870,19 +1879,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1890,27 +1899,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1922,11 +1931,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -1938,7 +1947,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -1950,10 +1959,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -1975,8 +1984,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -1998,9 +2007,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2021,8 +2030,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2036,11 +2045,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2061,15 +2070,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2084,12 +2093,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2115,16 +2164,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2132,17 +2181,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2163,24 +2212,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2191,37 +2241,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2234,10 +2284,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2332,7 +2382,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2348,10 +2398,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2368,7 +2418,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2378,23 +2428,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2447,7 +2497,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2458,7 +2508,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2478,21 +2528,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv02.c b/Applications/games/adv02.c index ebba3a84..0de59413 100644 --- a/Applications/games/adv02.c +++ b/Applications/games/adv02.c @@ -1,5 +1,6 @@ #define NUM_OBJ 67 #define WORDSIZE 3 +#define GAME_MAGIC 408 #include struct location { @@ -1462,6 +1463,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1474,18 +1488,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1496,6 +1503,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1509,7 +1519,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1762,13 +1772,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1780,6 +1783,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1934,7 +1943,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1946,19 +1955,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1966,27 +1975,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1998,11 +2007,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2014,7 +2023,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2026,10 +2035,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2051,8 +2060,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2074,9 +2083,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2097,8 +2106,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2112,11 +2121,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2137,15 +2146,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2160,12 +2169,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2191,16 +2240,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2208,17 +2257,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2239,24 +2288,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2267,37 +2317,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2310,10 +2360,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2408,7 +2458,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2424,10 +2474,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2444,7 +2494,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2454,23 +2504,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2523,7 +2573,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2534,7 +2584,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2554,21 +2604,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv03.c b/Applications/games/adv03.c index 5497db80..c3811192 100644 --- a/Applications/games/adv03.c +++ b/Applications/games/adv03.c @@ -1,5 +1,6 @@ #define NUM_OBJ 54 #define WORDSIZE 3 +#define GAME_MAGIC 306 #include struct location { @@ -1250,6 +1251,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1262,18 +1276,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1284,6 +1291,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1297,7 +1307,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1550,13 +1560,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1568,6 +1571,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1722,7 +1731,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1734,19 +1743,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1754,27 +1763,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1786,11 +1795,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -1802,7 +1811,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -1814,10 +1823,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -1839,8 +1848,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -1862,9 +1871,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -1885,8 +1894,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -1900,11 +1909,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -1925,15 +1934,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -1948,12 +1957,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -1979,16 +2028,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -1996,17 +2045,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2027,24 +2076,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2055,37 +2105,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2098,10 +2148,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2196,7 +2246,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2212,10 +2262,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2232,7 +2282,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2242,23 +2292,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2311,7 +2361,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2322,7 +2372,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2342,21 +2392,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv04.c b/Applications/games/adv04.c index 53672727..6b2dddaa 100644 --- a/Applications/games/adv04.c +++ b/Applications/games/adv04.c @@ -1,5 +1,6 @@ #define NUM_OBJ 66 #define WORDSIZE 3 +#define GAME_MAGIC 119 #include struct location { @@ -1526,6 +1527,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1538,18 +1552,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1560,6 +1567,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1573,7 +1583,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1826,13 +1836,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1844,6 +1847,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1998,7 +2007,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2010,19 +2019,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2030,27 +2039,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2062,11 +2071,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2078,7 +2087,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2090,10 +2099,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2115,8 +2124,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2138,9 +2147,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2161,8 +2170,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2176,11 +2185,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2201,15 +2210,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2224,12 +2233,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2255,16 +2304,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2272,17 +2321,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2303,24 +2352,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2331,37 +2381,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2374,10 +2424,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2472,7 +2522,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2488,10 +2538,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2508,7 +2558,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2518,23 +2568,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2587,7 +2637,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2598,7 +2648,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2618,21 +2668,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv05.c b/Applications/games/adv05.c index b133b789..8e104958 100644 --- a/Applications/games/adv05.c +++ b/Applications/games/adv05.c @@ -1,5 +1,6 @@ #define NUM_OBJ 73 #define WORDSIZE 3 +#define GAME_MAGIC 115 #include struct location { @@ -1592,6 +1593,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1604,18 +1618,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1626,6 +1633,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1639,7 +1649,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1892,13 +1902,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1910,6 +1913,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2064,7 +2073,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2076,19 +2085,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2096,27 +2105,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2128,11 +2137,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2144,7 +2153,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2156,10 +2165,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2181,8 +2190,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2204,9 +2213,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2227,8 +2236,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2242,11 +2251,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2267,15 +2276,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2290,12 +2299,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2321,16 +2370,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2338,17 +2387,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2369,24 +2418,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2397,37 +2447,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2440,10 +2490,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2538,7 +2588,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2554,10 +2604,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2574,7 +2624,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2584,23 +2634,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2653,7 +2703,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2664,7 +2714,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2684,21 +2734,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv06.c b/Applications/games/adv06.c index 53d32192..20aa30c7 100644 --- a/Applications/games/adv06.c +++ b/Applications/games/adv06.c @@ -1,5 +1,6 @@ #define NUM_OBJ 56 #define WORDSIZE 4 +#define GAME_MAGIC 119 #include struct location { @@ -1565,6 +1566,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1577,18 +1591,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1599,6 +1606,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1612,7 +1622,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1865,13 +1875,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1883,6 +1886,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2037,7 +2046,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2049,19 +2058,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2069,27 +2078,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2101,11 +2110,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2117,7 +2126,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2129,10 +2138,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2154,8 +2163,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2177,9 +2186,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2200,8 +2209,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2215,11 +2224,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2240,15 +2249,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2263,12 +2272,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2294,16 +2343,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2311,17 +2360,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2342,24 +2391,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2370,37 +2420,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2413,10 +2463,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2511,7 +2561,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2527,10 +2577,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2547,7 +2597,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2557,23 +2607,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2626,7 +2676,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2637,7 +2687,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2657,21 +2707,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv07.c b/Applications/games/adv07.c index 22d642a7..55c786a7 100644 --- a/Applications/games/adv07.c +++ b/Applications/games/adv07.c @@ -1,5 +1,6 @@ #define NUM_OBJ 75 #define WORDSIZE 4 +#define GAME_MAGIC 145 #include struct location { @@ -1640,6 +1641,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1652,18 +1666,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1674,6 +1681,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1687,7 +1697,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1940,13 +1950,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1958,6 +1961,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2112,7 +2121,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2124,19 +2133,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2144,27 +2153,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2176,11 +2185,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2192,7 +2201,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2204,10 +2213,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2229,8 +2238,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2252,9 +2261,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2275,8 +2284,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2290,11 +2299,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2315,15 +2324,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2338,12 +2347,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2369,16 +2418,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2386,17 +2435,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2417,24 +2466,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2445,37 +2495,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2488,10 +2538,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2586,7 +2636,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2602,10 +2652,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2622,7 +2672,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2632,23 +2682,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2701,7 +2751,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2712,7 +2762,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2732,21 +2782,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv08.c b/Applications/games/adv08.c index 044fb8f8..9d162d6d 100644 --- a/Applications/games/adv08.c +++ b/Applications/games/adv08.c @@ -1,5 +1,6 @@ #define NUM_OBJ 101 #define WORDSIZE 3 +#define GAME_MAGIC 125 #include struct location { @@ -1780,6 +1781,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1792,18 +1806,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1814,6 +1821,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1827,7 +1837,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -2080,13 +2090,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -2098,6 +2101,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2252,7 +2261,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2264,19 +2273,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2284,27 +2293,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2316,11 +2325,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2332,7 +2341,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2344,10 +2353,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2369,8 +2378,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2392,9 +2401,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2415,8 +2424,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2430,11 +2439,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2455,15 +2464,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2478,12 +2487,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2509,16 +2558,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2526,17 +2575,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2557,24 +2606,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2585,37 +2635,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2628,10 +2678,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2726,7 +2776,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2742,10 +2792,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2762,7 +2812,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2772,23 +2822,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2841,7 +2891,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2852,7 +2902,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2872,21 +2922,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv09.c b/Applications/games/adv09.c index d85dd3d5..755f385c 100644 --- a/Applications/games/adv09.c +++ b/Applications/games/adv09.c @@ -1,5 +1,6 @@ #define NUM_OBJ 78 #define WORDSIZE 4 +#define GAME_MAGIC 223 #include struct location { @@ -1827,6 +1828,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1839,18 +1853,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1861,6 +1868,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1874,7 +1884,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -2127,13 +2137,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -2145,6 +2148,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2299,7 +2308,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2311,19 +2320,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2331,27 +2340,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2363,11 +2372,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2379,7 +2388,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2391,10 +2400,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2416,8 +2425,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2439,9 +2448,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2462,8 +2471,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2477,11 +2486,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2502,15 +2511,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2525,12 +2534,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2556,16 +2605,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2573,17 +2622,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2604,24 +2653,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2632,37 +2682,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2675,10 +2725,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2773,7 +2823,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2789,10 +2839,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2809,7 +2859,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2819,23 +2869,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2888,7 +2938,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2899,7 +2949,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2919,21 +2969,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv10.c b/Applications/games/adv10.c index e68dee4c..dec5658c 100644 --- a/Applications/games/adv10.c +++ b/Applications/games/adv10.c @@ -1,5 +1,6 @@ #define NUM_OBJ 59 #define WORDSIZE 4 +#define GAME_MAGIC 123 #include struct location { @@ -1707,6 +1708,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1719,18 +1733,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1741,6 +1748,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1754,7 +1764,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -2007,13 +2017,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -2025,6 +2028,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2179,7 +2188,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2191,19 +2200,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2211,27 +2220,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2243,11 +2252,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2259,7 +2268,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2271,10 +2280,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2296,8 +2305,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2319,9 +2328,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2342,8 +2351,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2357,11 +2366,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2382,15 +2391,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2405,12 +2414,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2436,16 +2485,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2453,17 +2502,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2484,24 +2533,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2512,37 +2562,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2555,10 +2605,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2653,7 +2703,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2669,10 +2719,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2689,7 +2739,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2699,23 +2749,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2768,7 +2818,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2779,7 +2829,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2799,21 +2849,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv11.c b/Applications/games/adv11.c index 147e2538..48071e8e 100644 --- a/Applications/games/adv11.c +++ b/Applications/games/adv11.c @@ -1,5 +1,6 @@ #define NUM_OBJ 49 #define WORDSIZE 4 +#define GAME_MAGIC 133 #include struct location { @@ -1582,6 +1583,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1594,18 +1608,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1616,6 +1623,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1629,7 +1639,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1882,13 +1892,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1900,6 +1903,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2054,7 +2063,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2066,19 +2075,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2086,27 +2095,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2118,11 +2127,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2134,7 +2143,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2146,10 +2155,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2171,8 +2180,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2194,9 +2203,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2217,8 +2226,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2232,11 +2241,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2257,15 +2266,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2280,12 +2289,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2311,16 +2360,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2328,17 +2377,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2359,24 +2408,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2387,37 +2437,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2430,10 +2480,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2528,7 +2578,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2544,10 +2594,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2564,7 +2614,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2574,23 +2624,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2643,7 +2693,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2654,7 +2704,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2674,21 +2724,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv12.c b/Applications/games/adv12.c index 2e707721..f0bec3b6 100644 --- a/Applications/games/adv12.c +++ b/Applications/games/adv12.c @@ -1,5 +1,6 @@ #define NUM_OBJ 80 #define WORDSIZE 4 +#define GAME_MAGIC 184 #include struct location { @@ -1727,6 +1728,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1739,18 +1753,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1761,6 +1768,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1774,7 +1784,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -2027,13 +2037,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -2045,6 +2048,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2199,7 +2208,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2211,19 +2220,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2231,27 +2240,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2263,11 +2272,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2279,7 +2288,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2291,10 +2300,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2316,8 +2325,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2339,9 +2348,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2362,8 +2371,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2377,11 +2386,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2402,15 +2411,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2425,12 +2434,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2456,16 +2505,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2473,17 +2522,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2504,24 +2553,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2532,37 +2582,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2575,10 +2625,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2673,7 +2723,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2689,10 +2739,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2709,7 +2759,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2719,23 +2769,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2788,7 +2838,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2799,7 +2849,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2819,21 +2869,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/adv13.c b/Applications/games/adv13.c index 15f04145..44a8cf43 100644 --- a/Applications/games/adv13.c +++ b/Applications/games/adv13.c @@ -1,5 +1,6 @@ #define NUM_OBJ 76 #define WORDSIZE 5 +#define GAME_MAGIC 126 #include struct location { @@ -1816,6 +1817,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1828,18 +1842,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1850,6 +1857,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1863,7 +1873,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -2116,13 +2126,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -2134,6 +2137,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2288,7 +2297,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2300,19 +2309,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2320,27 +2329,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2352,11 +2361,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2368,7 +2377,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2380,10 +2389,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2405,8 +2414,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2428,9 +2437,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2451,8 +2460,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2466,11 +2475,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2491,15 +2500,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2514,12 +2523,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2545,16 +2594,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2562,17 +2611,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2593,24 +2642,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2621,37 +2671,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2664,10 +2714,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2762,7 +2812,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2778,10 +2828,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2798,7 +2848,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2808,23 +2858,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2877,7 +2927,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2888,7 +2938,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2908,21 +2958,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst01.c b/Applications/games/myst01.c index c905d17d..b8b7b367 100644 --- a/Applications/games/myst01.c +++ b/Applications/games/myst01.c @@ -1,5 +1,6 @@ #define NUM_OBJ 49 #define WORDSIZE 4 +#define GAME_MAGIC 463 #include struct location { @@ -1393,6 +1394,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1405,18 +1419,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1427,6 +1434,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1440,7 +1450,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1693,13 +1703,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1711,6 +1714,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1865,7 +1874,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1877,19 +1886,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1897,27 +1906,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1929,11 +1938,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -1945,7 +1954,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -1957,10 +1966,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -1982,8 +1991,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2005,9 +2014,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2028,8 +2037,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2043,11 +2052,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2068,15 +2077,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2091,12 +2100,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2122,16 +2171,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2139,17 +2188,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2170,24 +2219,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2198,37 +2248,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2241,10 +2291,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2339,7 +2389,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2355,10 +2405,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2375,7 +2425,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2385,23 +2435,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2454,7 +2504,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2465,7 +2515,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2485,21 +2535,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst02.c b/Applications/games/myst02.c index ad980cae..5c5d50c7 100644 --- a/Applications/games/myst02.c +++ b/Applications/games/myst02.c @@ -1,5 +1,6 @@ #define NUM_OBJ 63 #define WORDSIZE 4 +#define GAME_MAGIC 515 #include struct location { @@ -1409,6 +1410,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1421,18 +1435,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1443,6 +1450,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1456,7 +1466,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1709,13 +1719,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1727,6 +1730,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1881,7 +1890,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1893,19 +1902,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1913,27 +1922,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1945,11 +1954,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -1961,7 +1970,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -1973,10 +1982,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -1998,8 +2007,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2021,9 +2030,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2044,8 +2053,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2059,11 +2068,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2084,15 +2093,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2107,12 +2116,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2138,16 +2187,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2155,17 +2204,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2186,24 +2235,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2214,37 +2264,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2257,10 +2307,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2355,7 +2405,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2371,10 +2421,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2391,7 +2441,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2401,23 +2451,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2470,7 +2520,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2481,7 +2531,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2501,21 +2551,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst03.c b/Applications/games/myst03.c index 104083cf..62f0bd91 100644 --- a/Applications/games/myst03.c +++ b/Applications/games/myst03.c @@ -1,5 +1,6 @@ #define NUM_OBJ 65 #define WORDSIZE 4 +#define GAME_MAGIC 33061 #include struct location { @@ -1426,6 +1427,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1438,18 +1452,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1460,6 +1467,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1473,7 +1483,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1726,13 +1736,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1744,6 +1747,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1898,7 +1907,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1910,19 +1919,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1930,27 +1939,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1962,11 +1971,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -1978,7 +1987,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -1990,10 +1999,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2015,8 +2024,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2038,9 +2047,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2061,8 +2070,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2076,11 +2085,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2101,15 +2110,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2124,12 +2133,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2155,16 +2204,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2172,17 +2221,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2203,24 +2252,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2231,37 +2281,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2274,10 +2324,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2372,7 +2422,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2388,10 +2438,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2408,7 +2458,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2418,23 +2468,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2487,7 +2537,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2498,7 +2548,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2518,21 +2568,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst04.c b/Applications/games/myst04.c index 0b10444f..6cff4663 100644 --- a/Applications/games/myst04.c +++ b/Applications/games/myst04.c @@ -1,5 +1,6 @@ #define NUM_OBJ 91 #define WORDSIZE 4 +#define GAME_MAGIC 734 #include struct location { @@ -1674,6 +1675,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1686,18 +1700,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1708,6 +1715,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1721,7 +1731,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1974,13 +1984,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1992,6 +1995,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2146,7 +2155,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2158,19 +2167,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2178,27 +2187,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2210,11 +2219,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2226,7 +2235,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2238,10 +2247,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2263,8 +2272,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2286,9 +2295,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2309,8 +2318,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2324,11 +2333,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2349,15 +2358,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2372,12 +2381,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2403,16 +2452,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2420,17 +2469,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2451,24 +2500,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2479,37 +2529,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2522,10 +2572,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2620,7 +2670,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2636,10 +2686,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2656,7 +2706,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2666,23 +2716,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2735,7 +2785,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2746,7 +2796,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2766,21 +2816,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst05.c b/Applications/games/myst05.c index 341677fc..c6597b86 100644 --- a/Applications/games/myst05.c +++ b/Applications/games/myst05.c @@ -1,5 +1,6 @@ #define NUM_OBJ 91 #define WORDSIZE 4 +#define GAME_MAGIC 562 #include struct location { @@ -1756,6 +1757,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1768,18 +1782,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1790,6 +1797,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1803,7 +1813,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -2056,13 +2066,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -2074,6 +2077,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2228,7 +2237,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2240,19 +2249,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2260,27 +2269,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2292,11 +2301,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2308,7 +2317,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2320,10 +2329,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2345,8 +2354,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2368,9 +2377,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2391,8 +2400,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2406,11 +2415,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2431,15 +2440,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2454,12 +2463,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2485,16 +2534,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2502,17 +2551,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2533,24 +2582,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2561,37 +2611,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2604,10 +2654,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2702,7 +2752,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2718,10 +2768,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2738,7 +2788,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2748,23 +2798,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2817,7 +2867,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2828,7 +2878,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2848,21 +2898,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst06.c b/Applications/games/myst06.c index 148fce4b..0e9b4867 100644 --- a/Applications/games/myst06.c +++ b/Applications/games/myst06.c @@ -1,5 +1,6 @@ #define NUM_OBJ 66 #define WORDSIZE 4 +#define GAME_MAGIC 427 #include struct location { @@ -1417,6 +1418,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1429,18 +1443,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1451,6 +1458,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1464,7 +1474,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1717,13 +1727,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1735,6 +1738,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1889,7 +1898,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1901,19 +1910,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1921,27 +1930,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1953,11 +1962,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -1969,7 +1978,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -1981,10 +1990,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2006,8 +2015,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2029,9 +2038,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2052,8 +2061,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2067,11 +2076,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2092,15 +2101,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2115,12 +2124,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2146,16 +2195,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2163,17 +2212,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2194,24 +2243,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2222,37 +2272,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2265,10 +2315,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2363,7 +2413,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2379,10 +2429,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2399,7 +2449,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2409,23 +2459,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2478,7 +2528,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2489,7 +2539,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2509,21 +2559,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst07.c b/Applications/games/myst07.c index 003dd824..181bb563 100644 --- a/Applications/games/myst07.c +++ b/Applications/games/myst07.c @@ -1,5 +1,6 @@ #define NUM_OBJ 66 #define WORDSIZE 4 +#define GAME_MAGIC 494 #include struct location { @@ -1410,6 +1411,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1422,18 +1436,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1444,6 +1451,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1457,7 +1467,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1710,13 +1720,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1728,6 +1731,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1882,7 +1891,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1894,19 +1903,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1914,27 +1923,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -1946,11 +1955,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -1962,7 +1971,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -1974,10 +1983,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -1999,8 +2008,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2022,9 +2031,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2045,8 +2054,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2060,11 +2069,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2085,15 +2094,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2108,12 +2117,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2139,16 +2188,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2156,17 +2205,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2187,24 +2236,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2215,37 +2265,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2258,10 +2308,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2356,7 +2406,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2372,10 +2422,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2392,7 +2442,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2402,23 +2452,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2471,7 +2521,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2482,7 +2532,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2502,21 +2552,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst08.c b/Applications/games/myst08.c index e6da0264..56774df5 100644 --- a/Applications/games/myst08.c +++ b/Applications/games/myst08.c @@ -1,5 +1,6 @@ #define NUM_OBJ 50 #define WORDSIZE 4 +#define GAME_MAGIC 784 #include struct location { @@ -1523,6 +1524,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1535,18 +1549,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1557,6 +1564,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1570,7 +1580,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1823,13 +1833,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1841,6 +1844,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1995,7 +2004,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2007,19 +2016,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2027,27 +2036,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2059,11 +2068,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2075,7 +2084,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2087,10 +2096,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2112,8 +2121,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2135,9 +2144,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2158,8 +2167,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2173,11 +2182,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2198,15 +2207,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2221,12 +2230,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2252,16 +2301,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2269,17 +2318,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2300,24 +2349,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2328,37 +2378,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2371,10 +2421,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2469,7 +2519,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2485,10 +2535,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2505,7 +2555,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2515,23 +2565,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2584,7 +2634,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2595,7 +2645,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2615,21 +2665,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst09.c b/Applications/games/myst09.c index 03a421c3..aa0e7c37 100644 --- a/Applications/games/myst09.c +++ b/Applications/games/myst09.c @@ -1,5 +1,6 @@ #define NUM_OBJ 60 #define WORDSIZE 4 +#define GAME_MAGIC 532 #include struct location { @@ -1527,6 +1528,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1539,18 +1553,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1561,6 +1568,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1574,7 +1584,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1827,13 +1837,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1845,6 +1848,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1999,7 +2008,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2011,19 +2020,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2031,27 +2040,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2063,11 +2072,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2079,7 +2088,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2091,10 +2100,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2116,8 +2125,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2139,9 +2148,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2162,8 +2171,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2177,11 +2186,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2202,15 +2211,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2225,12 +2234,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2256,16 +2305,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2273,17 +2322,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2304,24 +2353,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2332,37 +2382,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2375,10 +2425,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2473,7 +2523,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2489,10 +2539,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2509,7 +2559,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2519,23 +2569,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2588,7 +2638,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2599,7 +2649,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2619,21 +2669,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst10.c b/Applications/games/myst10.c index 4771a8ba..5ef8097b 100644 --- a/Applications/games/myst10.c +++ b/Applications/games/myst10.c @@ -1,5 +1,6 @@ #define NUM_OBJ 74 #define WORDSIZE 4 +#define GAME_MAGIC 854 #include struct location { @@ -1479,6 +1480,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1491,18 +1505,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1513,6 +1520,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1526,7 +1536,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1779,13 +1789,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1797,6 +1800,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -1951,7 +1960,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -1963,19 +1972,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -1983,27 +1992,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2015,11 +2024,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2031,7 +2040,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2043,10 +2052,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2068,8 +2077,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2091,9 +2100,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2114,8 +2123,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2129,11 +2138,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2154,15 +2163,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2177,12 +2186,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2208,16 +2257,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2225,17 +2274,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2256,24 +2305,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2284,37 +2334,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2327,10 +2377,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2425,7 +2475,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2441,10 +2491,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2461,7 +2511,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2471,23 +2521,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2540,7 +2590,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2551,7 +2601,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2571,21 +2621,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } diff --git a/Applications/games/myst11.c b/Applications/games/myst11.c index 417363ee..b4efa677 100644 --- a/Applications/games/myst11.c +++ b/Applications/games/myst11.c @@ -1,5 +1,6 @@ #define NUM_OBJ 58 #define WORDSIZE 4 +#define GAME_MAGIC 551 #include struct location { @@ -1559,6 +1560,19 @@ const uint8_t automap[] = { static jmp_buf restart; +struct savearea { + uint16_t magic; + uint8_t carried; + uint8_t lighttime; + uint8_t location; + uint8_t objloc[NUM_OBJ]; + uint8_t roomsave[6]; + uint8_t savedroom; + uint32_t bitflags; + int16_t counter; + int16_t counter_array[16]; +}; + static char linebuf[81]; static char *nounbuf; static char wordbuf[WORDSIZE + 1]; @@ -1571,18 +1585,11 @@ static uint8_t actmatch; static uint8_t continuation; static uint16_t *param; static uint16_t param_buf[5]; -static uint8_t carried; -static uint8_t lighttime; -static uint8_t location; -static uint8_t objloc[NUM_OBJ]; -static uint8_t roomsave[6]; -static uint8_t savedroom; -static uint32_t bitflags; -static int16_t counter; -static int16_t counter_array[16]; static uint8_t redraw; static uint8_t rows, cols; +static struct savearea game; + static void error(const char *p); #define VERB_GO 1 @@ -1593,6 +1600,9 @@ static void error(const char *p); #define DARKFLAG 15 #define LIGHT_SOURCE 9 +/* Define this because 1 << n might be 16bit */ +#define ONEBIT ((uint32_t)1) + #define REDRAW 1 #define REDRAW_MAYBE 2 @@ -1606,7 +1616,7 @@ static char wbuf[81]; static int wbp = 0; static int xpos = 0, ypos = 0; static int bottom; -WINDOW *topwin, *botwin, *curwin; +static WINDOW *topwin, *botwin, *curwin; static void flush_word(void) { @@ -1859,13 +1869,6 @@ static void strout_upper(const uint8_t *p) strout_lower(p); } -static char readchar(void) -{ - char c; - if (read(0, &c, 1) < 1) - return -1; - return c; -} static void line_input(void) { @@ -1877,6 +1880,12 @@ static void line_input(void) linebuf[l-1] = 0; } +static char readchar(void) +{ + line_input(); + return *linebuf; +} + static void begin_upper(void) { strout_upper("\n\n\n\n"); @@ -2031,7 +2040,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) for (i = 0; i < n; i++) { uint8_t opc = *p++; uint16_t par = *p++ | ((opc & 0xE0) >> 5); - uint8_t op = objloc[par]; + uint8_t op = game.objloc[par]; opc &= 0x1F; switch(opc) { @@ -2043,19 +2052,19 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 2: - if (op != location) + if (op != game.location) return NULL; break; case 3: - if (op != 255 && op != location) + if (op != 255 && op != game.location) return NULL; break; case 4: - if (location != par) + if (game.location != par) return NULL; break; case 5: - if (op == location) + if (op == game.location) return NULL; break; case 6: @@ -2063,27 +2072,27 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 7: - if (location == par) + if (game.location == par) return NULL; break; case 8: - if (!(bitflags & (1 << par))) + if (!(game.bitflags & (ONEBIT << par))) return NULL; break; case 9: - if (bitflags & (1 << par)) + if (game.bitflags & (ONEBIT << par)) return NULL; break; case 10: - if (!carried) + if (!game.carried) return NULL; break; case 11: - if (carried) + if (game.carried) return NULL; break; case 12: - if (op == 255 || op == location) + if (op == 255 || op == game.location) return NULL; break; case 13: @@ -2095,11 +2104,11 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 15: - if (counter > par) + if (game.counter > par) return NULL; break; case 16: - if (counter < par) + if (game.counter < par) return NULL; break; case 17: @@ -2111,7 +2120,7 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) return NULL; break; case 19: - if (counter != par) + if (game.counter != par) return NULL; break; default: @@ -2123,10 +2132,10 @@ static const uint8_t *run_conditions(const uint8_t *p, uint8_t n) uint8_t islight(void) { - uint8_t l = objloc[LIGHT_SOURCE]; - if (!(bitflags & (1 << DARKFLAG))) + uint8_t l = game.objloc[LIGHT_SOURCE]; + if (!(game.bitflags & (ONEBIT << DARKFLAG))) return 1; - if (l == 255 || l == location) + if (l == 255 || l == game.location) return 1; return 0; } @@ -2148,8 +2157,8 @@ static void action_look(void) end_upper(); return; } - p = locdata[location].text; - e = locdata[location].exit; + p = locdata[game.location].text; + e = locdata[game.location].exit; if (*p == '*') p++; else @@ -2171,9 +2180,9 @@ static void action_look(void) strout_upper(nonestr); strout_upper(dotnewline); f = 1; - e = objloc; - while(e < objloc + NUM_OBJ) { - if (*e++ == location) { + e = game.objloc; + while(e < game.objloc + NUM_OBJ) { + if (*e++ == game.location) { if (f) { strout_upper(canalsosee); f = 0; @@ -2194,8 +2203,8 @@ static void action_delay(void) static void action_dead(void) { strout_lower(dead); - bitflags &= ~(1 << DARKFLAG); - location = lastloc; + game.bitflags &= ~(ONEBIT << DARKFLAG); + game.location = lastloc; action_look(); } @@ -2209,11 +2218,11 @@ static void action_quit(void) static void action_score(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t t = 0, s = 0; - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*m[0] == '*') { t++; if (*p == treasure) @@ -2234,15 +2243,15 @@ static void action_score(void) static void action_inventory(void) { - uint8_t *p = objloc; + uint8_t *p = game.objloc; const uint8_t **m = objtext; uint8_t f = 1; strout_lower(carrying); - if (carried == 0) + if (game.carried == 0) strout_lower(nothing); else { - while(p < objloc + NUM_OBJ) { + while(p < game.objloc + NUM_OBJ) { if (*p == 255) { if (!f) strout_lower(dashstr); @@ -2257,12 +2266,52 @@ static void action_inventory(void) strout_lower(dotnewline); } +static char *filename(void) +{ + strout_lower("File name ? "); + line_input(); + return skip_spaces(linebuf); +} + +static void action_save(void) +{ + int fd; + char *p = filename(); + if (*p == 0) + return; + game.magic = GAME_MAGIC; + fd = open(p, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fd == -1 || write(fd, &game, sizeof(game)) != sizeof(game) || close(fd) == -1) + strout_lower("Save failed.\n"); + close(fd); /* Double closing is safe for non error path */ +} + +static int action_restore(void) +{ + while(1) { + char *p = filename(); + int fd; + + if (*p == 0) + return 0; + + fd = open(p, O_RDONLY, 0600); + + if (fd != -1 && read(fd, &game, sizeof(game)) == sizeof(game) && close(fd) != -1 && + game.magic == GAME_MAGIC) + return 1; + + strout_lower("Load failed.\n"); + close(fd); + } +} + static void moveitem(uint8_t i, uint8_t l) { - uint8_t *p = objloc + i; - if (*p == location) + uint8_t *p = game.objloc + i; + if (*p == game.location) redraw |= REDRAW_MAYBE; - if (l == location) + if (l == game.location) redraw |= REDRAW; *p = l; } @@ -2288,16 +2337,16 @@ static void run_actions(const uint8_t *p, uint8_t n) case 51: /* nop - check */ break; case 52: /* Get */ - if (carried >= maxcar) + if (game.carried >= maxcar) strout_lower(toomuch); else moveitem(*param++, 255); break; case 53: /* Drop */ - moveitem(*param++, location); + moveitem(*param++, game.location); break; case 54: /* Go */ - location = *param++; + game.location = *param++; redraw = REDRAW; break; case 55: /* Destroy */ @@ -2305,17 +2354,17 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 0); break; case 56: /* Set dark flag */ - bitflags |= (1 << DARKFLAG); + game.bitflags |= (ONEBIT << DARKFLAG); break; case 57: /* Clear dark flag */ - bitflags &= ~(1 << DARKFLAG); + game.bitflags &= ~(ONEBIT << DARKFLAG); break; case 58: /* Set bit */ - bitflags |= (1 << *param++); + game.bitflags |= (ONEBIT << *param++); break; /* 59 see 55 */ case 60: /* Clear bit */ - bitflags &= ~(1 << *param++); + game.bitflags &= ~(ONEBIT << *param++); break; case 61: /* Dead */ action_dead(); @@ -2336,24 +2385,25 @@ static void run_actions(const uint8_t *p, uint8_t n) case 66: /* Inventory */ action_inventory(); case 67: /* Set bit 0 */ - bitflags |= (1 << 0); + game.bitflags |= (ONEBIT << 0); break; case 68: /* Clear bit 0 */ - bitflags &= ~(1 << 0); + game.bitflags &= ~(ONEBIT << 0); break; case 69: /* Refill lamp */ - lighttime = lightfill; - bitflags &= ~(1 << LIGHTOUT); + game.lighttime = lightfill; + game.bitflags &= ~(ONEBIT << LIGHTOUT); moveitem(LIGHT_SOURCE, 255); break; case 70: /* Wipe lower */ /* TODO */ break; case 71: /* Save */ - /* TODO */ + action_save(); + break; case 72: /* Swap two objects */ - tmp = objloc[*param]; - moveitem(*param, objloc[param[1]]); + tmp = game.objloc[*param]; + moveitem(*param, game.objloc[param[1]]); moveitem(param[1], tmp); param += 2; break; @@ -2364,37 +2414,37 @@ static void run_actions(const uint8_t *p, uint8_t n) moveitem(*param++, 255); break; case 75: /* Put one item by another */ - moveitem(*param, objloc[param[1]]); + moveitem(*param, game.objloc[param[1]]); param += 2; break; case 77: /* Decrement counter */ - if (counter >= 0) - counter--; + if (game.counter >= 0) + game.counter--; break; case 78: /* Display counter */ - decout_lower(counter); + decout_lower(game.counter); break; case 79: /* Set counter */ - counter = *param++; + game.counter = *param++; break; case 80: /* Swap player and saved room */ - tmp = savedroom; - savedroom = location; - location = tmp; + tmp = game.savedroom; + game.savedroom = game.location; + game.location = tmp; redraw = REDRAW; break; case 81: /* Swap counter and counter n */ - tmp16 = counter; - counter = counter_array[*param]; - counter_array[*param++] = tmp16; + tmp16 = game.counter; + game.counter = game.counter_array[*param]; + game.counter_array[*param++] = tmp16; break; case 82: /* Add to counter */ - counter += *param++; + game.counter += *param++; break; case 83: /* Subtract from counter */ - counter -= *param++; - if (counter < 0) - counter = -1; + game.counter -= *param++; + if (game.counter < 0) + game.counter = -1; break; case 84: /* Print noun, newline */ strout_lower((uint8_t *)nounbuf); @@ -2407,10 +2457,10 @@ static void run_actions(const uint8_t *p, uint8_t n) break; case 87: /* Swap player and saveroom array entry */ tmp16 = *param++; - tmp = roomsave[tmp16]; - roomsave[tmp16] = location; - if (tmp != location) { - location = tmp; + tmp = game.roomsave[tmp16]; + game.roomsave[tmp16] = game.location; + if (tmp != game.location) { + game.location = tmp; redraw = REDRAW; } break; @@ -2505,7 +2555,7 @@ uint8_t autonoun(uint8_t loc) if (*wordbuf == ' ' || *wordbuf == 0) return 255; while(*p) { - if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && objloc[p[WORDSIZE]] == loc) + if (strncasecmp((const char *)p, wordbuf, WORDSIZE) == 0 && game.objloc[p[WORDSIZE]] == loc) return p[WORDSIZE]; p += WORDSIZE + 1; } @@ -2521,10 +2571,10 @@ void run_command(void) if (verb == VERB_GET) { /* Get */ if (noun == 0) strout_lower(whatstr); - else if (carried >= maxcar) + else if (game.carried >= maxcar) strout_lower(toomuch); else { - tmp = autonoun(location); + tmp = autonoun(game.location); if (tmp == 255) strout_lower(beyondpower); else @@ -2541,7 +2591,7 @@ void run_command(void) if (tmp == 255) strout_lower(beyondpower); else - moveitem(tmp, location); + moveitem(tmp, game.location); } actmatch = 1; return; @@ -2551,23 +2601,23 @@ void run_command(void) void process_light(void) { uint8_t l; - if ((l = objloc[LIGHT_SOURCE]) == 0) + if ((l = game.objloc[LIGHT_SOURCE]) == 0) return; - if (lighttime == 255) + if (game.lighttime == 255) return; - if (!--lighttime) { - bitflags &= ~(1 << LIGHTOUT); /* Check clear ! */ - if (l == 255 || l == location) { + if (!--game.lighttime) { + game.bitflags &= ~(ONEBIT << LIGHTOUT); /* Check clear ! */ + if (l == 255 || l == game.location) { strout_lower(lightout); redraw = REDRAW_MAYBE; return; } } - if (lighttime > 25) + if (game.lighttime > 25) return; strout_lower(lightoutin); - decout_lower(lighttime); - strout_lower(lighttime == 1 ? turn : turns); + decout_lower(game.lighttime); + strout_lower(game.lighttime == 1 ? turn : turns); } void main_loop(void) @@ -2620,7 +2670,7 @@ void main_loop(void) if (!light) strout_lower(darkdanger); - dir = locdata[location].exit[noun - 1]; + dir = locdata[game.location].exit[noun - 1]; if (!dir) { if (!light) { strout_lower(brokeneck); @@ -2631,7 +2681,7 @@ void main_loop(void) strout_lower(cantgo); continue; } - location = dir; + game.location = dir; redraw = REDRAW; continue; } @@ -2651,21 +2701,23 @@ void main_loop(void) void start_game(void) { - memcpy(objloc, objinit, sizeof(objloc)); - bitflags = 0; - counter = 0; - memset(counter_array, 0, sizeof(counter_array)); - savedroom = 0; - memset(roomsave, 0, sizeof(roomsave)); - location = startloc; - lighttime = startlamp; - carried = startcarried; + memcpy(game.objloc, objinit, sizeof(game.objloc)); + game.bitflags = 0; + game.counter = 0; + memset(game.counter_array, 0, sizeof(game.counter_array)); + game.savedroom = 0; + memset(game.roomsave, 0, sizeof(game.roomsave)); + game.location = startloc; + game.lighttime = startlamp; + game.carried = startcarried; } int main(int argc, char *argv[]) { display_init(); setjmp(restart); - start_game(); + strout_lower("Restore a saved game ? "); + if (!yes_or_no() || !action_restore()) + start_game(); main_loop(); } -- 2.34.1