summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile2
-rw-r--r--src/main.c49
-rw-r--r--src/spec.c69
-rw-r--r--src/spec.h11
-rw-r--r--src/tape.c160
-rw-r--r--src/tape.h78
-rw-r--r--src/util.c10
-rw-r--r--src/util.h7
8 files changed, 284 insertions, 102 deletions
diff --git a/src/Makefile b/src/Makefile
index f8a0a14..96193fe 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -40,6 +40,7 @@ SOURCE = main.c \
util.c \
kbbmp.c \
exit.c \
+ tape.c \
expr.c \
z80.c \
z80_decode.c \
@@ -55,6 +56,7 @@ OBJECTS = main.o \
util.o \
kbbmp.o \
exit.o \
+ tape.o \
expr.o \
z80.o \
z80_decode.o \
diff --git a/src/main.c b/src/main.c
index a657edb..7e2844e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -35,6 +35,7 @@
#include "config.h"
#include "kbbmp.h"
#include "exit.h"
+#include "tape.h"
#include "util.h"
@@ -69,8 +70,6 @@ static void Usage(void)
*/
int main(int argc, char *argv[])
{
- char tape_in[FILENAME_MAX]="";
- char tape_out[FILENAME_MAX]="";
Z80 *z80;
SDL_Event *e;
int quit;
@@ -99,9 +98,6 @@ int main(int argc, char *argv[])
/* Parse switches
*/
inital_menu=FALSE;
- tape_in[0]=0;
- tape_out[0]=0;
-
f=1;
while(f<argc && argv[f][0]=='-')
@@ -118,7 +114,7 @@ int main(int argc, char *argv[])
Usage();
}
- strcpy(tape_in,argv[++f]);
+ TAPEMount(TAP_IN, argv[++f]);
break;
case 's':
@@ -127,7 +123,7 @@ int main(int argc, char *argv[])
Usage();
}
- strcpy(tape_out,argv[++f]);
+ TAPEMount(TAP_OUT, argv[++f]);
break;
default:
@@ -143,16 +139,6 @@ int main(int argc, char *argv[])
quit=MemoryMenu(z80);
}
- if (tape_in[0])
- {
- SPECMount(SPEC_TAPE_IN,tape_in);
- }
-
- if (tape_out[0])
- {
- SPECMount(SPEC_TAPE_IN,tape_out);
- }
-
/* Main loop
*/
while(!quit)
@@ -233,48 +219,29 @@ int main(int argc, char *argv[])
break;
case SDLK_F4:
- if (e->key.state==SDL_PRESSED)
- GUIMessage(eMessageBox,
- "Mounted Tape Files",
- "In: %-20.20s\nOut: %-20.20s",
- tape_in[0] ? Basename(tape_in):"None",
- tape_out[0] ? Basename(tape_out):"None");
+ TAPEDisplayInfo();
break;
case SDLK_F8:
if (e->key.state==SDL_PRESSED)
{
- if (GUIFileSelect("TAPE TO LOAD",TRUE,
- tape_in[0] ?
- Dirname(tape_in) :
- SConfig(CONF_TAPEDIR),
- tape_in))
- {
- SPECMount(SPEC_TAPE_IN,tape_in);
- }
+ TAPESelectInput();
}
break;
case SDLK_F9:
if (e->key.state==SDL_PRESSED)
{
- if (GUIFileSelect("TAPE TO SAVE",FALSE,
- tape_out[0] ?
- Dirname(tape_out) :
- SConfig(CONF_TAPEDIR),
- tape_out))
- {
- SPECMount(SPEC_TAPE_OUT,tape_out);
- }
+ TAPESelectOutput();
}
break;
case SDLK_F10:
if (e->key.state==SDL_PRESSED)
{
- SPECUnmount(SPEC_TAPE_IN);
- SPECUnmount(SPEC_TAPE_OUT);
+ TAPEUnmount(TAP_IN);
+ TAPEUnmount(TAP_OUT);
}
break;
diff --git a/src/spec.c b/src/spec.c
index 7066292..3a872dd 100644
--- a/src/spec.c
+++ b/src/spec.c
@@ -32,6 +32,7 @@
#include "gui.h"
#include "config.h"
#include "exit.h"
+#include "tape.h"
#include "util.h"
#ifndef TRUE
@@ -52,8 +53,8 @@ static const int ROMLEN=0x4000;
static const int ROM_SAVE=0x4c6;
static const int ROM_LOAD=0x562;
-static FILE *tape_in;
-static FILE *tape_out;
+static int selected_in_tape = FALSE;
+static int selected_out_tape = FALSE;
#define LOAD_PATCH 0xf0
#define SAVE_PATCH 0xf1
@@ -350,13 +351,19 @@ static int EDCallback(Z80 *z80, Z80Val data)
case SAVE_PATCH:
Z80GetState(z80,&state);
- if (!tape_out)
+ if (!TAPEFile(TAP_OUT) && !selected_out_tape)
+ {
+ TAPESelectOutput();
+ selected_out_tape = TRUE;
+ }
+
+ if (!TAPEFile(TAP_OUT))
{
state.AF|=eZ80_Carry;
}
else
{
- if (TAPSave(tape_out,
+ if (TAPSave(TAPEFile(TAP_OUT),
HIBYTE(state.AF),
&state.IX,
&state.DE,
@@ -377,13 +384,19 @@ static int EDCallback(Z80 *z80, Z80Val data)
case LOAD_PATCH:
Z80GetState(z80,&state);
- if (!tape_in)
+ if (!TAPEFile(TAP_IN) && !selected_in_tape)
+ {
+ TAPESelectInput();
+ selected_in_tape = TRUE;
+ }
+
+ if (!TAPEFile(TAP_IN))
{
state.AF|=eZ80_Carry;
}
else
{
- if (TAPLoad(tape_in,
+ if (TAPLoad(TAPEFile(TAP_IN),
HIBYTE(state.AF),
&state.IX,
&state.DE,
@@ -858,48 +871,4 @@ void SPECReset(Z80 *z80)
}
-void SPECMount(SPECMountType type, const char *path)
-{
- switch(type)
- {
- case SPEC_TAPE_IN:
- if (tape_in)
- fclose(tape_in);
-
- tape_in=fopen(path,"rb");
- break;
-
- case SPEC_TAPE_OUT:
- if (tape_out)
- fclose(tape_out);
-
- tape_out=fopen(path,"wb");
- break;
- }
-}
-
-
-void SPECUnmount(SPECMountType type)
-{
- switch(type)
- {
- case SPEC_TAPE_IN:
- if (tape_in)
- {
- fclose(tape_in);
- tape_in=NULL;
- }
- break;
-
- case SPEC_TAPE_OUT:
- if (tape_out)
- {
- fclose(tape_out);
- tape_out=NULL;
- }
- break;
- }
-}
-
-
/* END OF FILE */
diff --git a/src/spec.h b/src/spec.h
index d5429cd..261429c 100644
--- a/src/spec.h
+++ b/src/spec.h
@@ -29,11 +29,6 @@
#include "z80.h"
#include "SDL.h"
-/* Types for Mount and Unmount
-*/
-typedef enum {SPEC_TAPE_IN,SPEC_TAPE_OUT} SPECMountType;
-
-
/* Initialise the SPEC
*/
void SPECInit(Z80 *z80);
@@ -64,12 +59,6 @@ void SPECShowScreen(void);
*/
void SPECReset(Z80 *z80);
-
-/* Interfaces for snapshot and device control
-*/
-void SPECMount(SPECMountType type, const char *path);
-void SPECUnmount(SPECMountType type);
-
#endif
diff --git a/src/tape.c b/src/tape.c
new file mode 100644
index 0000000..157d644
--- /dev/null
+++ b/src/tape.c
@@ -0,0 +1,160 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2026 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Selected tape files
+
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <sys/param.h>
+
+#include "tape.h"
+#include "util.h"
+#include "gui.h"
+#include "config.h"
+
+
+/* ---------------------------------------- MACROS
+*/
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+/* ---------------------------------------- GLOBALS
+*/
+static char tape_in[FILENAME_MAX]="";
+static char tape_out[FILENAME_MAX]="";
+static FILE *in;
+static FILE *out;
+
+/* ---------------------------------------- INTERFACES
+*/
+
+int TAPESelectInput(void)
+{
+ char path[FILENAME_MAX];
+
+ if (GUIFileSelect("TAPE TO LOAD",TRUE,
+ tape_in[0] ? Dirname(tape_in) : SConfig(CONF_TAPEDIR),
+ path))
+ {
+ TAPEMount(TAP_IN, path);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+int TAPESelectOutput(void)
+{
+ char path[FILENAME_MAX];
+
+ if (GUIFileSelect("TAPE TO SAVE",FALSE,
+ tape_out[0] ? Dirname(tape_out) : SConfig(CONF_TAPEDIR),
+ path))
+ {
+ TAPEMount(TAP_OUT, path);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+void TAPEMount(TAPEMountType type, const char *path)
+{
+ TAPEUnmount(type);
+
+ switch(type)
+ {
+ case TAP_IN:
+ strncpy(tape_in, path, FILENAME_MAX);
+ in = fopen(tape_in, "rb");
+ break;
+
+ case TAP_OUT:
+ strncpy(tape_out, path, FILENAME_MAX);
+ out = fopen(tape_out, "wb");
+ break;
+ }
+}
+
+
+void TAPEUnmount(TAPEMountType type)
+{
+ switch(type)
+ {
+ case TAP_IN:
+ if (in)
+ {
+ fclose(in);
+ in = NULL;
+ }
+ tape_in[0] = 0;
+ break;
+
+ case TAP_OUT:
+ if (out)
+ {
+ fclose(out);
+ out = NULL;
+ }
+ tape_out[0] = 0;
+ break;
+ }
+}
+
+
+FILE *TAPEFile(TAPEMountType type)
+{
+ switch(type)
+ {
+ case TAP_IN:
+ return in;
+
+ case TAP_OUT:
+ return out;
+
+ default:
+ return NULL;
+ }
+}
+
+
+void TAPEDisplayInfo(void)
+{
+ GUIMessage(eMessageBox,
+ "Mounted Tape Files",
+ "In: %-20.20s\nOut: %-20.20s",
+ tape_in[0] ? Basename(tape_in):"None",
+ tape_out[0] ? Basename(tape_out):"None");
+}
+
+
+/* END OF FILE */
diff --git a/src/tape.h b/src/tape.h
new file mode 100644
index 0000000..05e09e9
--- /dev/null
+++ b/src/tape.h
@@ -0,0 +1,78 @@
+/*
+
+ espec - Sinclair Spectrum emulator
+
+ Copyright (C) 2026 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Seleted tape files
+
+*/
+
+#ifndef ESPEC_TAPE_H
+#define ESPEC_TAPE_H "$Id$"
+
+#include <stdio.h>
+
+/* ---------------------------------------- TYPES
+*/
+
+/* Types for Mount and Unmount
+*/
+typedef enum {TAP_IN, TAP_OUT} TAPEMountType;
+
+
+/* ---------------------------------------- INTERFACES
+*/
+
+/* Select the tape file to use for input. Returns TRUE if a tape was
+ selected.
+*/
+int TAPESelectInput(void);
+
+
+/* Select the tape file to use for output. Returns TRUE if a tape was
+ selected.
+*/
+int TAPESelectOutput(void);
+
+
+/* Mount a file without using the selector
+*/
+void TAPEMount(TAPEMountType type, const char *path);
+
+
+/* Unmount a file without using the selector
+*/
+void TAPEUnmount(TAPEMountType type);
+
+
+/* Get the current tape
+*/
+FILE *TAPEFile(TAPEMountType type);
+
+
+/* Display tape info in a message box
+*/
+void TAPEDisplayInfo(void);
+
+
+#endif
+
+
+/* END OF FILE */
diff --git a/src/util.c b/src/util.c
index ee43a3c..c16584c 100644
--- a/src/util.c
+++ b/src/util.c
@@ -66,6 +66,16 @@ char *StrCopy(const char *source)
}
+char *SafeStrCopy(char *destination,
+ const char *source,
+ size_t destination_size)
+{
+ strncpy(destination, source, destination_size);
+ destination[destination_size - 1] = 0;
+ return destination;
+}
+
+
const char *Basename(const char *path)
{
const char *p=path+strlen(path);
diff --git a/src/util.h b/src/util.h
index 922f641..c82169e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -47,6 +47,13 @@ void *Realloc(void *p, size_t size);
char *StrCopy(const char *source);
+/* Safely copies a string. The destination is returned.
+*/
+char *SafeStrCopy(char *destination,
+ const char *source,
+ size_t destination_size);
+
+
/* Returns the filename portion of path. Note returned pointer is pointing
inside of path.
*/