summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/config.h1
-rw-r--r--include/snapshot.h10
-rw-r--r--instructions.txt26
-rw-r--r--source/config.c5
-rw-r--r--source/main.c20
-rw-r--r--source/snapshot.c51
-rw-r--r--source/zx81.c46
7 files changed, 119 insertions, 40 deletions
diff --git a/include/config.h b/include/config.h
index 9946356..8dc05e8 100644
--- a/include/config.h
+++ b/include/config.h
@@ -31,6 +31,7 @@ typedef enum
DS81_STICKY_SHIFT,
DS81_AVERAGE_TOUCHSCREEN,
DS81_STATIC_RAM_AT_0x2000,
+ DS81_ALLOW_TAPE_SAVE,
DS81_LOAD_DEFAULT_SNAPSHOT,
DS81_NUM_CONFIG_ITEMS
} DS81_ConfigItem;
diff --git a/include/snapshot.h b/include/snapshot.h
index 0afd20b..5b0f536 100644
--- a/include/snapshot.h
+++ b/include/snapshot.h
@@ -24,8 +24,14 @@
#include "z80.h"
+typedef enum
+{
+ SNAP_TYPE_FULL,
+ SNAP_TYPE_KEYBOARD
+} SnapshotType;
+
void SNAP_Enable(int enable);
-void SNAP_Save(Z80 *cpu);
-void SNAP_Load(Z80 *cpu, const char *optional_name);
+void SNAP_Save(Z80 *cpu, SnapshotType type);
+void SNAP_Load(Z80 *cpu, const char *optional_name, SnapshotType type);
#endif /* DS81_SNAPSHOT_H */
diff --git a/instructions.txt b/instructions.txt
index 3b78efa..2e43577 100644
--- a/instructions.txt
+++ b/instructions.txt
@@ -123,16 +123,25 @@
See the second to last section for more details.
- LOAD MEMORY SNAPSHOT
- Loads a memory snapshot. This option only works if a FAT-enabled
+ 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.
- SAVE MEMORY SNAPSHOT
- Saves a memory snapshot. This option only works if a FAT-enabled
+ 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 JOYPAD/KEY STATE
+ Saves a snapshot that just contains the current state of the
+ keyboard and the joypad mappings. This just allows you to save
+ a complex controller mapping to share between different games.
+
+ LOAD JOYPAD/KEY STATE
+ This loads the state of the keyboard and the joypad mappings
+ from a selected file.
+
CANCEL
Cancels the menu.
@@ -273,6 +282,15 @@
Not that I've found any that work yet :-)
+ ALLOW TAPE SAVE
+
+ If enabled this means that files saved with the SAVE command will
+ try and create a .P file in the ZX81SNAP directory, or the root
+ directory. You can SAVE "*" to bring up the file selector.
+
+ If not enabled attempts to SAVE files from BASIC will be silently
+ ignored.
+
LOAD DEFAULT MEMORY SNAP
If enabled DS81 will look for a memory snapshot called AUTO.D81 in
diff --git a/source/config.c b/source/config.c
index 55141ba..9d02417 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",
+ "allow_tape_save",
"load_default_snapshot"
};
@@ -46,6 +47,7 @@ int DS81_Config[DS81_NUM_CONFIG_ITEMS]=
TRUE,
FALSE,
FALSE,
+ FALSE,
FALSE
};
@@ -133,6 +135,9 @@ const char *ConfigDesc(DS81_ConfigItem item)
case DS81_LOAD_DEFAULT_SNAPSHOT:
return "LOAD DEFAULT SNAPSHOT";
+ case DS81_ALLOW_TAPE_SAVE:
+ return "ALLOW TAPE SAVING";
+
default:
return "UNKNOWN";
}
diff --git a/source/main.c b/source/main.c
index 674478e..218dd40 100644
--- a/source/main.c
+++ b/source/main.c
@@ -59,8 +59,8 @@ static const char *main_menu[]=
#ifndef DS81_DISABLE_FAT
"Save Memory Snapshot",
"Load Memory Snapshot",
- "Save Joypad Mappings",
- "Load Joypad Mappings",
+ "Save Joypad/Key State",
+ "Load Joypad/Key State",
#endif
"Cancel",
NULL
@@ -98,9 +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. 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."
+ "hour. And no retro game is complete without a side-scroller... "
+ "Thanks to Slay Radio, Ladytron, the Genki Rockets, the High "
+ "Voltage SID Collection and Retro Gamer for coding fuel."
};
static const char *text[]=
@@ -394,7 +394,7 @@ int main(int argc, char *argv[])
if (DS81_Config[DS81_LOAD_DEFAULT_SNAPSHOT])
{
- SNAP_Load(z80, "AUTO");
+ SNAP_Load(z80, "AUTO", SNAP_TYPE_FULL);
}
while(1)
@@ -438,19 +438,19 @@ int main(int argc, char *argv[])
#ifndef DS81_DISABLE_FAT
case MenuSaveSnapshot:
- SNAP_Save(z80);
+ SNAP_Save(z80, SNAP_TYPE_FULL);
break;
case MenuLoadSnapshot:
- SNAP_Load(z80, NULL);
+ SNAP_Load(z80, NULL, SNAP_TYPE_FULL);
break;
case MenuSaveMappings:
- // TODO
+ SNAP_Save(z80, SNAP_TYPE_KEYBOARD);
break;
case MenuLoadMappings:
- // TODO
+ SNAP_Load(z80, NULL, SNAP_TYPE_KEYBOARD);
break;
#endif
}
diff --git a/source/snapshot.c b/source/snapshot.c
index 14f0e30..1d5aa37 100644
--- a/source/snapshot.c
+++ b/source/snapshot.c
@@ -28,6 +28,7 @@
#include <ctype.h>
#include <nds.h>
+#include "snapshot.h"
#include "zx81.h"
#include "gui.h"
@@ -47,12 +48,13 @@
/* ---------------------------------------- STATICS
*/
static int enabled;
-static const char *magic = "V00_DS81";
+static const char *magic = "V01_DS81";
+static const char *extension[2] = {".D81", ".K81"};
/* ---------------------------------------- PRIVATE FUNCTIONS
*/
-static void WriteMagic(FILE *fp)
+static void WriteMagic(FILE *fp, SnapshotType t)
{
const char *p = magic;
@@ -60,9 +62,11 @@ static void WriteMagic(FILE *fp)
{
fputc(*p++, fp);
}
+
+ fputc(t, fp);
}
-static int CheckMagic(FILE *fp)
+static int CheckMagic(FILE *fp, SnapshotType t)
{
const char *p = magic;
@@ -74,7 +78,7 @@ static int CheckMagic(FILE *fp)
}
}
- return TRUE;
+ return (fgetc(fp) == t);
}
@@ -85,7 +89,7 @@ void SNAP_Enable(int enable)
enabled = enable;
}
-void SNAP_Save(Z80 *cpu)
+void SNAP_Save(Z80 *cpu, SnapshotType type)
{
char base[FILENAME_MAX] = "";
char file[FILENAME_MAX];
@@ -96,12 +100,13 @@ void SNAP_Save(Z80 *cpu)
return;
}
- if(!GUI_InputName("enter snapshot filename", ".d81", base, 8) || !base[0])
+ if(!GUI_InputName("enter snapshot filename",
+ extension[type], base, 8) || !base[0])
{
return;
}
- strcat(base, ".D81");
+ strcat(base, extension[type]);
strcpy(file, DEFAULT_SNAPDIR);
strcat(file, base);
@@ -115,10 +120,16 @@ void SNAP_Save(Z80 *cpu)
if (fp)
{
- WriteMagic(fp);
+ WriteMagic(fp, type);
+
SK_SaveSnapshot(fp);
- Z80SaveSnapshot(cpu, fp);
- ZX81SaveSnapshot(fp);
+
+ if (type == SNAP_TYPE_FULL)
+ {
+ Z80SaveSnapshot(cpu, fp);
+ ZX81SaveSnapshot(fp);
+ }
+
fclose(fp);
}
else
@@ -127,7 +138,7 @@ void SNAP_Save(Z80 *cpu)
}
}
-void SNAP_Load(Z80 *cpu, const char *optional_name)
+void SNAP_Load(Z80 *cpu, const char *optional_name, SnapshotType type)
{
static char last_dir[FILENAME_MAX] = "/";
char file[FILENAME_MAX];
@@ -142,17 +153,21 @@ void SNAP_Load(Z80 *cpu, const char *optional_name)
{
strcpy(file, DEFAULT_SNAPDIR);
strcat(file, optional_name);
+ strcat(file, extension[type]);
fp = fopen(file, "rb");
if (!fp)
{
- fp = fopen(optional_name, "rb");
+ strcpy(file, optional_name);
+ strcat(file, extension[type]);
+
+ fp = fopen(file, "rb");
}
}
else
{
- if (GUI_FileSelect(last_dir, file, ".D81"))
+ if (GUI_FileSelect(last_dir, file, extension[type]))
{
fp = fopen(file, "rb");
}
@@ -160,15 +175,19 @@ void SNAP_Load(Z80 *cpu, const char *optional_name)
if (fp)
{
- if (!CheckMagic(fp))
+ if (!CheckMagic(fp, type))
{
GUI_Alert(FALSE, "Not a valid snapshot");
}
else
{
SK_LoadSnapshot(fp);
- Z80LoadSnapshot(cpu, fp);
- ZX81LoadSnapshot(fp);
+
+ if (type == SNAP_TYPE_FULL)
+ {
+ Z80LoadSnapshot(cpu, fp);
+ ZX81LoadSnapshot(fp);
+ }
}
fclose(fp);
diff --git a/source/zx81.c b/source/zx81.c
index 00d6015..b8143cd 100644
--- a/source/zx81.c
+++ b/source/zx81.c
@@ -62,6 +62,7 @@
#define SLOW_TSTATES 16000
#define FAST_TSTATES 64000
+#define E_LINE 16404
#define LASTK1 16421
#define LASTK2 16422
#define MARGIN 16424
@@ -103,6 +104,7 @@ static Z80Word RAMTOP=0;
/* Tape
*/
static int enable_filesystem;
+static int allow_save;
static const Z80Byte *tape_image;
static int tape_len;
@@ -254,12 +256,13 @@ static Z80Byte FromASCII(char c)
/* Open a tape file the passed address
*/
-static FILE *OpenTapeFile(Z80Word addr, int *cancelled)
+static FILE *OpenTapeFile(Z80Word addr, int *cancelled, const char *mode)
{
static const char zx_chars[] = "\"#$:?()><=+-*/;,."
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";
FILE *fp;
+ char full_fn[FILENAME_MAX] = DEFAULT_SNAPDIR;
char fn[FILENAME_MAX];
int f;
int done;
@@ -291,7 +294,7 @@ static FILE *OpenTapeFile(Z80Word addr, int *cancelled)
{
if (GUI_FileSelect(last_dir,fn,".P"))
{
- fp = fopen(fn,"rb");
+ fp = fopen(fn, mode);
}
else
{
@@ -306,12 +309,11 @@ static FILE *OpenTapeFile(Z80Word addr, int *cancelled)
fn[f++] = 'P';
fn[f] = 0;
- if (!(fp = fopen(fn,"rb")))
- {
- char full_fn[FILENAME_MAX] = DEFAULT_SNAPDIR;
+ strcat(full_fn,fn);
- strcat(full_fn,fn);
- fp = fopen(full_fn,"rb");
+ if (!(fp = fopen(full_fn, mode)))
+ {
+ fp = fopen(fn, mode);
}
}
@@ -339,6 +341,21 @@ static void LoadExternalTape(FILE *tape, Z80 *z80)
}
+static void SaveExternalTape(FILE *tape, Z80 *z80)
+{
+ int f;
+ int end;
+
+ f = 0x4009;
+ end = WORD(E_LINE);
+
+ while(f <= end)
+ {
+ fputc(mem[f++], tape);
+ }
+}
+
+
static void ClearBitmap(void)
{
uint16 *s;
@@ -744,6 +761,17 @@ static int EDCallback(Z80 *z80, Z80Val data)
switch((Z80Byte)data)
{
case ED_SAVE:
+ if (allow_save && z80->DE.w<0x8000)
+ {
+ FILE *fp;
+ int cancel;
+
+ if ((fp=OpenTapeFile(z80->HL.w, &cancel, "wb")))
+ {
+ SaveExternalTape(fp,z80);
+ fclose(fp);
+ }
+ }
break;
case ED_LOAD:
@@ -757,7 +785,7 @@ static int EDCallback(Z80 *z80, Z80Val data)
FILE *fp;
int cancel;
- if ((fp=OpenTapeFile(z80->DE.w,&cancel)))
+ if ((fp=OpenTapeFile(z80->DE.w, &cancel, "rb")))
{
LoadExternalTape(fp,z80);
fclose(fp);
@@ -1068,6 +1096,8 @@ void ZX81Reconfigure(void)
RAMBOT = 0x4000;
memcpy(mem+ROMLEN,mem,ROMLEN);
}
+
+ allow_save = enable_filesystem && DS81_Config[DS81_ALLOW_TAPE_SAVE];
}