From 603f3fac82ccb77775d53fd77ae7c32167116ad7 Mon Sep 17 00:00:00 2001 From: Ian C Date: Mon, 3 Nov 2008 17:07:32 +0000 Subject: Initial snapshot code (in progress) --- CHANGES | 1 + include/config.h | 5 ++ include/ds81_debug.h | 15 ++++-- include/gui.h | 1 + include/keyboard.h | 7 +++ include/z80.h | 7 +++ include/zx81.h | 8 +++ instructions.txt | 40 ++++++++++++++- source/config.c | 5 ++ source/gui.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++ source/keyboard.c | 37 ++++++++++++++ source/main.c | 50 +++++++++++++++++- source/tapes.c | 15 +++--- source/z80.c | 65 +++++++++++++++++++++++ source/zx81.c | 40 ++++++++++++++- version | 2 +- 16 files changed, 424 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index dc1207f..8bbd5fc 100644 --- a/CHANGES +++ b/CHANGES @@ -49,3 +49,4 @@ Changes from V1.2a to V1.3 * Added memory snapshots. * Added auto-load of named snapshot. * Added auto initial pop-up of snapshot selection. + * Added save/load of keyboard mappings. diff --git a/include/config.h b/include/config.h index e2d96de..9946356 100644 --- a/include/config.h +++ b/include/config.h @@ -22,11 +22,16 @@ #ifndef DS81_CONFIG_H #define DS81_CONFIG_H +/* Default snapshot dir +*/ +#define DEFAULT_SNAPDIR "/ZX81SNAP/" + typedef enum { DS81_STICKY_SHIFT, DS81_AVERAGE_TOUCHSCREEN, DS81_STATIC_RAM_AT_0x2000, + DS81_LOAD_DEFAULT_SNAPSHOT, DS81_NUM_CONFIG_ITEMS } DS81_ConfigItem; diff --git a/include/ds81_debug.h b/include/ds81_debug.h index 82e8c45..ed7a1eb 100644 --- a/include/ds81_debug.h +++ b/include/ds81_debug.h @@ -22,15 +22,22 @@ #ifndef DS81_DEBUG_H #define DS81_DEBUG_H +#include "gui.h" #include "framebuffer.h" #define DS81_DEBUG(fmt, args...) \ do \ { \ - FB_FillBox(0,184,256,8,FB_RGB(10,0,0)); \ - FB_printf(0,184,FB_RGB(31,31,31),FB_RGB(10,0,0), fmt , ## args);\ - while (keysDownRepeat()!=KEY_A); \ + char tempdebug[512]; \ + sprintf(tempdebug, fmt, ## args); \ + GUI_Alert(FALSE, tempdebug); \ + } while(0) + +#define DS81_DEBUG_STATUS(fmt, args...) \ + do \ + { \ + FB_FillBox(0,184,256,8,COL_DARKGREY); \ + FB_printf(0,184,COL_WHITE,COL_DARKGREY, fmt , ## args); \ } while(0) - #endif /* DS81_DEBUG_H */ diff --git a/include/gui.h b/include/gui.h index 3795481..30989e6 100644 --- a/include/gui.h +++ b/include/gui.h @@ -26,5 +26,6 @@ int GUI_Menu(const char *opts[]); void GUI_Alert(int fatal, const char *text); void GUI_Config(void); int GUI_FileSelect(char pwd[], char selected_file[], const char *filter); +int GUI_InputName(char name[], int maxlen); #endif /* DS81_GUI_H */ diff --git a/include/keyboard.h b/include/keyboard.h index 0827b76..93538ec 100644 --- a/include/keyboard.h +++ b/include/keyboard.h @@ -22,6 +22,8 @@ #ifndef DS81_KEYBOARD_H #define DS81_KEYBOARD_H +#include + /* Note that the first 40 values purposefully are the keyboard matrix keys. Note also that they are in display order, not matrix order. */ @@ -132,4 +134,9 @@ void SK_DefinePad(SoftKey pad, SoftKey key); */ const char *SK_KeyName(SoftKey pad); +/* Allows the keyboard to save/restore its state from a stream +*/ +void SK_SaveSnapshot(FILE *fp); +void SK_LoadSnapshot(FILE *fp); + #endif /* DS81_KEYBOARD_H */ diff --git a/include/z80.h b/include/z80.h index 000b950..1250356 100644 --- a/include/z80.h +++ b/include/z80.h @@ -27,6 +27,8 @@ #ifndef Z80_H #define Z80_H "$Id$" +#include + /* Configuration */ #include "z80_config.h" @@ -245,6 +247,11 @@ void Z80SetLabels(Z80Label labels[]); */ const char *Z80Disassemble(Z80 *cpu, Z80Word *addr); +/* Allows the CPU state to be saved/loaded from a stream +*/ +void Z80SaveSnapshot(Z80 *cpu, FILE *fp); +void Z80LoadSnapshot(Z80 *cpu, FILE *fp); + #endif /* END OF FILE */ diff --git a/include/zx81.h b/include/zx81.h index 2606c98..1f77448 100644 --- a/include/zx81.h +++ b/include/zx81.h @@ -27,6 +27,8 @@ #ifndef DS81_ZX81_H #define DS81_ZX81_H +#include + #include "z80.h" #include "keyboard.h" @@ -79,6 +81,12 @@ void ZX81WritePort(Z80 *z80, Z80Word port, Z80Byte val); #define ZX81ReadDisassem ZX81ReadMem +/* Interfaces to allows the ZX81 to save/load itself as a snapshot to/from + a stream. +*/ +void ZX81SaveSnapshot(FILE *fp); +void ZX81LoadSnapshot(FILE *fp); + #endif diff --git a/instructions.txt b/instructions.txt index 99c2b23..3b78efa 100644 --- a/instructions.txt +++ b/instructions.txt @@ -70,6 +70,9 @@ Once the A button has been pressed the ZX81 resets and displays itself on the top screen, and a soft keyboard is displayed on the bottom, touch sensitive, DS screen. + + Also at this point, if so configured, a default memory snap will be loaded. + See the "Memory Snapshots" section for more details. If you've never used a ZX81 before then you may wish to find out how the keyboard works -- it uses a keyword entry system, rather than the straight @@ -120,6 +123,16 @@ See the second to last section for more details. + LOAD MEMORY SNAPSHOT + Loads a memory snapshot. This option only works if a FAT-enabled + version of DS81 is being used. See the "Memory Snapshot" section + for more details. + + SAVE MEMORY SNAPSHOT + Saves a memory snapshot. This option only works if a FAT-enabled + version of DS81 is being used. See the "Memory Snapshot" section + for more details. + CANCEL Cancels the menu. @@ -193,7 +206,7 @@ If you know of a game that seems to cause it real trouble, please let me know -- the high-resolution support is still a bit of a hack whereby the - 'emulator searches memory for the display file on detecting that the 'I' + emulator searches memory for the display file on detecting that the 'I' register has changed. @@ -260,6 +273,31 @@ Not that I've found any that work yet :-) + LOAD DEFAULT MEMORY SNAP + + If enabled DS81 will look for a memory snapshot called AUTO.D81 in + either the root directory or the ZX81SNAP directory. + + See the "Memory Snapshot" section for more details on snapshots. + + +9. Memory Snapshots +------------------- + + Since version 1.3 DS81 now supports basic memory snapshots. When you + select the "SAVE MEMORY SNAPSHOT" from the main menu DS81 will prompt + for a filename (only up to 8 alphabetical characters). Once entered + the snapshot will be saved in the directory ZX81SNAP with an automatically + added .D81 extension. If this save fails, an attempt is made to save the + snapshot in the root directory of the device. + + On selecting to load a memory snapshot a file selector is displayed. On + selecting one of the snapshots it will be instantly loaded. + + Note that along with the machine's state the currently configured keypad + mappings are saved in the snapshot and restored when loaded. + + ------------------------------------------------------------------------------- $Id$ diff --git a/source/config.c b/source/config.c index 433b5d6..55141ba 100644 --- a/source/config.c +++ b/source/config.c @@ -35,6 +35,7 @@ const char *conf_entry[DS81_NUM_CONFIG_ITEMS]= "sticky_shift", "average_touchscreen", "static_ram_at_0x2000", + "load_default_snapshot" }; @@ -44,6 +45,7 @@ int DS81_Config[DS81_NUM_CONFIG_ITEMS]= { TRUE, FALSE, + FALSE, FALSE }; @@ -128,6 +130,9 @@ const char *ConfigDesc(DS81_ConfigItem item) case DS81_STATIC_RAM_AT_0x2000: return "RAM AT 8192"; + case DS81_LOAD_DEFAULT_SNAPSHOT: + return "LOAD DEFAULT SNAPSHOT"; + default: return "UNKNOWN"; } diff --git a/source/gui.c b/source/gui.c index ed30706..0400197 100644 --- a/source/gui.c +++ b/source/gui.c @@ -28,6 +28,8 @@ #include #include "framebuffer.h" +#include "zx81.h" +#include "keyboard.h" #include "config.h" @@ -712,3 +714,143 @@ int GUI_FileSelect(char pwd[], char selected_file[], const char *filter) return ret; } + + +int GUI_InputName(char name[], int maxlen) +{ + struct + { + SoftKey key; + int ascii; + } keymap[] = + { + {SK_1, '1'}, + {SK_2, '2'}, + {SK_3, '3'}, + {SK_4, '4'}, + {SK_5, '5'}, + {SK_6, '6'}, + {SK_7, '7'}, + {SK_8, '8'}, + {SK_9, '9'}, + {SK_0, '0'}, + {SK_A, 'A'}, + {SK_B, 'B'}, + {SK_C, 'C'}, + {SK_D, 'D'}, + {SK_E, 'E'}, + {SK_F, 'F'}, + {SK_G, 'G'}, + {SK_H, 'H'}, + {SK_I, 'I'}, + {SK_J, 'J'}, + {SK_K, 'K'}, + {SK_L, 'L'}, + {SK_M, 'M'}, + {SK_N, 'N'}, + {SK_O, 'O'}, + {SK_P, 'P'}, + {SK_Q, 'Q'}, + {SK_R, 'R'}, + {SK_S, 'S'}, + {SK_T, 'T'}, + {SK_U, 'U'}, + {SK_V, 'V'}, + {SK_W, 'W'}, + {SK_X, 'X'}, + {SK_Y, 'Y'}, + {SK_Z, 'Z'}, + {0, 0} + }; + + SoftKeyEvent ev; + char text[1024]; + int done = FALSE; + int accept = FALSE; + int update = TRUE; + + SK_DisplayKeyboard(); + ZX81SuspendDisplay(); + + name[0] = 0; + + while(!done) + { + if (update) + { + sprintf(text, "enter the snapshot name:\n" + "\"%s%%l%%\"" + "\n\n\npress enter to accept.\n" + "press period to backspace.\n" + "press space/break to cancel\n", + name); + + ZX81DisplayString(text); + + update = FALSE; + } + + while(SK_GetBareEvent(&ev)) + { + if (!ev.pressed) + { + size_t l; + int f; + int ascii; + + l = strlen(name); + + switch(ev.key) + { + case SK_PERIOD: + if (l) + { + name[--l] = 0; + update = TRUE; + } + break; + + case SK_SPACE: + done = TRUE; + accept = FALSE; + break; + + case SK_NEWLINE: + done = TRUE; + accept = TRUE; + break; + + default: + if (l < maxlen) + { + f = 0; + ascii = 0; + + while(!ascii && keymap[f].ascii) + { + if (ev.key == keymap[f].key) + { + ascii = keymap[f].ascii; + } + + f++; + } + + if (ascii) + { + name[l++] = ascii; + name[l] = 0; + update = TRUE; + } + } + break; + } + } + } + + swiWaitForVBlank(); + } + + return accept; +} + diff --git a/source/keyboard.c b/source/keyboard.c index d2e7aa7..6483b1c 100644 --- a/source/keyboard.c +++ b/source/keyboard.c @@ -26,6 +26,7 @@ #include "framebuffer.h" #include "touchwrap.h" #include "keyb_bin.h" +#include "stream.h" /* ---------------------------------------- STATIC DATA */ @@ -409,3 +410,39 @@ const char *SK_KeyName(SoftKey k) } +void SK_SaveSnapshot(FILE *fp) +{ + STRPUT(fp, pad_left_key); + STRPUT(fp, pad_right_key); + STRPUT(fp, pad_up_key); + STRPUT(fp, pad_down_key); + STRPUT(fp, pad_A_key); + STRPUT(fp, pad_B_key); + STRPUT(fp, pad_X_key); + STRPUT(fp, pad_Y_key); + STRPUT(fp, pad_R_key); + STRPUT(fp, pad_L_key); + STRPUT(fp, pad_start_key); + STRPUT(fp, pad_select_key); + STRPUT(fp, key_state); +} + + +void SK_LoadSnapshot(FILE *fp) +{ + STRGET(fp, pad_left_key); + STRGET(fp, pad_right_key); + STRGET(fp, pad_up_key); + STRGET(fp, pad_down_key); + STRGET(fp, pad_A_key); + STRGET(fp, pad_B_key); + STRGET(fp, pad_X_key); + STRGET(fp, pad_Y_key); + STRGET(fp, pad_R_key); + STRGET(fp, pad_L_key); + STRGET(fp, pad_start_key); + STRGET(fp, pad_select_key); + STRGET(fp, key_state); +} + + diff --git a/source/main.c b/source/main.c index 5bef185..c196608 100644 --- a/source/main.c +++ b/source/main.c @@ -35,10 +35,13 @@ #include "config.h" #include "textmode.h" #include "monitor.h" +#include "snapshot.h" #include "splashimg_bin.h" #include "rom_font_bin.h" +#include "ds81_debug.h" + #ifndef DS81_VERSION #define DS81_VERSION "DEV " __TIME__ "/" __DATE__ #endif @@ -53,6 +56,12 @@ static const char *main_menu[]= "Configure", "Map Joypad to Keys", "Machine Code Monitor", +#ifndef DS81_DISABLE_FAT + "Save Memory Snapshot", + "Load Memory Snapshot", + "Save Joypad Mappings", + "Load Joypad Mappings", +#endif "Cancel", NULL }; @@ -64,6 +73,12 @@ typedef enum MenuConfigure, MenuMapJoypad, MenuMonitor, +#ifndef DS81_DISABLE_FAT + MenuSaveSnapshot, + MenuLoadSnapshot, + MenuSaveMappings, + MenuLoadMappings +#endif } MenuOpt; /* ---------------------------------------- IRQ FUNCS @@ -83,8 +98,9 @@ static void Splash(void) " " "Welcome to DS81, a ZX81 emulator for the Ninetendo DS. " "You can safely ignore this message. I was just bored for half an " - "hour. " - "Thanks to Slay Radio for coding fuel." + "hour. And no retro item is complete without a side-scroller... " + "Thanks to Slay Radio, the Genki Rockets and the High Voltage SID " + "Collection for coding fuel." }; static const char *text[]= @@ -144,6 +160,7 @@ static void Splash(void) if (res) { ZX81EnableFileSystem(TRUE); + SNAP_Enable(TRUE); FB_Centre("Found a FAT device.",y,COL_WHITE,COL_TRANSPARENT); y += 8; @@ -167,6 +184,7 @@ static void Splash(void) else { ZX81EnableFileSystem(FALSE); + SNAP_Enable(FALSE); FB_Centre("Sorry, but you don't have a",y,COL_WHITE,COL_TRANSPARENT); y += 8; @@ -374,10 +392,20 @@ int main(int argc, char *argv[]) SK_SetSticky(SK_SHIFT,DS81_Config[DS81_STICKY_SHIFT]); + if (DS81_Config[DS81_LOAD_DEFAULT_SNAPSHOT]) + { + SNAP_Load(z80, "AUTO"); + } + while(1) { + static unsigned cycle; + SoftKeyEvent ev; + DS81_DEBUG_STATUS("PC = %4.4x I = %u", z80->PC, cycle); + cycle++; + Z80Exec(z80); while(SK_GetEvent(&ev)) @@ -412,6 +440,24 @@ int main(int argc, char *argv[]) case MenuMonitor: MachineCodeMonitor(z80); break; + +#ifndef DS81_DISABLE_FAT + case MenuSaveSnapshot: + SNAP_Save(z80); + break; + + case MenuLoadSnapshot: + SNAP_Load(z80, NULL); + break; + + case MenuSaveMappings: + // TODO + break; + + case MenuLoadMappings: + // TODO + break; +#endif } SK_DisplayKeyboard(); diff --git a/source/tapes.c b/source/tapes.c index 26bbd24..2220778 100644 --- a/source/tapes.c +++ b/source/tapes.c @@ -36,13 +36,15 @@ #include "mazogs_bin.h" #include "mazogs_inlay_bin.h" +#include "ds81_debug.h" + /* ---------------------------------------- STATIC DATA */ typedef struct { const u8 *tape; - const u32 *tape_len; + const u8 *tape_end; sImage img; const void *source_pcx; SoftKey *keys; @@ -105,7 +107,7 @@ static Tape tapes[NO_TAPES]= { { maze_bin, - &maze_bin_size, + maze_bin_end, {0}, maze_inlay_bin, maze_keys, @@ -123,7 +125,7 @@ static Tape tapes[NO_TAPES]= }, { mazogs_bin, - &mazogs_bin_size, + mazogs_bin_end, {0}, mazogs_inlay_bin, mazogs_keys, @@ -141,7 +143,7 @@ static Tape tapes[NO_TAPES]= }, { cpatrol_bin, - &cpatrol_bin_size, + cpatrol_bin_end, {0}, cpatrol_inlay_bin, cpatrol_keys, @@ -162,7 +164,7 @@ static Tape tapes[NO_TAPES]= }, { sabotage_bin, - &sabotage_bin_size, + sabotage_bin_end, {0}, sabotage_inlay_bin, sabotage_keys, @@ -260,7 +262,8 @@ void SelectTape(void) int f; done=TRUE; - ZX81SetTape(tapes[current].tape,*tapes[current].tape_len); + ZX81SetTape(tapes[current].tape, + tapes[current].tape_end - tapes[current].tape); for(f=0;tapes[current].keys[f]!=NUM_SOFT_KEYS;f+=2) { diff --git a/source/z80.c b/source/z80.c index 36c5793..d4205c5 100644 --- a/source/z80.c +++ b/source/z80.c @@ -31,6 +31,8 @@ #include "z80.h" #include "z80_private.h" +#include "stream.h" + static const char ident[]="$Id$"; static const char ident_z80_header[]=Z80_H; static const char ident_z80_private_header[]=Z80_PRIVATE_H; @@ -328,4 +330,67 @@ const char *Z80Disassemble(Z80 *cpu, Z80Word *pc) #endif } + +void Z80SaveSnapshot(Z80 *cpu, FILE *fp) +{ + STRPUT(fp, cpu->PC); + STRPUT(fp, cpu->AF); + STRPUT(fp, cpu->BC); + STRPUT(fp, cpu->DE); + STRPUT(fp, cpu->HL); + STRPUT(fp, cpu->AF_); + STRPUT(fp, cpu->BC_); + STRPUT(fp, cpu->DE_); + STRPUT(fp, cpu->HL_); + STRPUT(fp, cpu->IX); + STRPUT(fp, cpu->IY); + STRPUT(fp, cpu->SP); + STRPUT(fp, cpu->IFF1); + STRPUT(fp, cpu->IFF2); + STRPUT(fp, cpu->IM); + STRPUT(fp, cpu->I); + STRPUT(fp, cpu->R); + STRPUT(fp, cpu->R); + + STRPUT(fp, cpu->priv->cycle); + STRPUT(fp, cpu->priv->halt); + STRPUT(fp, cpu->priv->shift); + STRPUT(fp, cpu->priv->raise); + STRPUT(fp, cpu->priv->devbyte); + STRPUT(fp, cpu->priv->nmi); + STRPUT(fp, cpu->priv->callback); + STRPUT(fp, cpu->priv->last_cb); +} + +void Z80LoadSnapshot(Z80 *cpu, FILE *fp) +{ + STRGET(fp, cpu->PC); + STRGET(fp, cpu->AF); + STRGET(fp, cpu->BC); + STRGET(fp, cpu->DE); + STRGET(fp, cpu->HL); + STRGET(fp, cpu->AF_); + STRGET(fp, cpu->BC_); + STRGET(fp, cpu->DE_); + STRGET(fp, cpu->HL_); + STRGET(fp, cpu->IX); + STRGET(fp, cpu->IY); + STRGET(fp, cpu->SP); + STRGET(fp, cpu->IFF1); + STRGET(fp, cpu->IFF2); + STRGET(fp, cpu->IM); + STRGET(fp, cpu->I); + STRGET(fp, cpu->R); + STRGET(fp, cpu->R); + + STRGET(fp, cpu->priv->cycle); + STRGET(fp, cpu->priv->halt); + STRGET(fp, cpu->priv->shift); + STRGET(fp, cpu->priv->raise); + STRGET(fp, cpu->priv->devbyte); + STRGET(fp, cpu->priv->nmi); + STRGET(fp, cpu->priv->callback); + STRGET(fp, cpu->priv->last_cb); +} + /* END OF FILE */ diff --git a/source/zx81.c b/source/zx81.c index c0af981..a8620c3 100644 --- a/source/zx81.c +++ b/source/zx81.c @@ -31,10 +31,14 @@ #include "zx81.h" #include "gui.h" +#include "stream.h" + #include "config.h" #include "zx81_bin.h" +#include "ds81_debug.h" + #ifndef TRUE #define TRUE 1 #endif @@ -77,6 +81,9 @@ static int hires=FALSE; static int hires_dfile; static int last_I; +static unsigned prev_lk1; +static unsigned prev_lk2; + #define SCR_W 256 #define SCR_H 192 #define TXT_W 32 @@ -313,7 +320,7 @@ static FILE *OpenTapeFile(Z80Word addr, int *cancelled) if (!(fp = fopen(fn,"rb"))) { - char full_fn[FILENAME_MAX+11] = "/ZX81SNAP/"; + char full_fn[FILENAME_MAX] = DEFAULT_SNAPDIR; strcat(full_fn,fn); fp = fopen(full_fn,"rb"); @@ -603,7 +610,6 @@ static void FindHiresDFILE(void) */ static void ZX81HouseKeeping(Z80 *z80) { - static unsigned prev_lk1,prev_lk2; unsigned row; unsigned lastk1; unsigned lastk2; @@ -1073,4 +1079,34 @@ void ZX81Reconfigure(void) } +void ZX81SaveSnapshot(FILE *fp) +{ + STRPUT(fp, mem); + STRPUT(fp, matrix); + STRPUT(fp, waitkey); + STRPUT(fp, started); + STRPUT(fp, RAMBOT); + STRPUT(fp, RAMTOP); + STRPUT(fp, prev_lk1); + STRPUT(fp, prev_lk2); +} + + +void ZX81LoadSnapshot(FILE *fp) +{ + STRGET(fp, mem); + STRGET(fp, matrix); + STRGET(fp, waitkey); + STRGET(fp, started); + STRGET(fp, RAMBOT); + STRGET(fp, RAMTOP); + STRGET(fp, prev_lk1); + STRGET(fp, prev_lk2); + + /* Reset last_I to force hi/lo res detection + */ + last_I = 0; +} + + /* END OF FILE */ diff --git a/version b/version index 929dd09..3789c31 100644 --- a/version +++ b/version @@ -1 +1 @@ -V1.3 devel +V1.3 beta1-devel -- cgit v1.2.3