aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2018-09-20 00:49:29 -0700
committerH. Peter Anvin <hpa@zytor.com>2018-09-20 00:49:29 -0700
commitbd9e555cab36920647a9b7b98a8b5fe66ba58ed1 (patch)
tree7063caef6973b28eb953eabcbdcfb2426a9f7b18
parent0a331bb8d9a34ab342acf3e1d709071bc83240b5 (diff)
downloadabc80sim-bd9e555cab36920647a9b7b98a8b5fe66ba58ed1.tar.gz
abc80sim-bd9e555cab36920647a9b7b98a8b5fe66ba58ed1.tar.xz
abc80sim-bd9e555cab36920647a9b7b98a8b5fe66ba58ed1.zip
Support loading a file into the ABC802 MEM: area
-rw-r--r--HELP.txt54
-rw-r--r--abc80.c11
-rw-r--r--abcio.h5
-rw-r--r--abcmem.c73
-rw-r--r--hostfile.c8
-rw-r--r--screenshot.c4
-rw-r--r--sdlscrn.c8
-rw-r--r--z80.h2
8 files changed, 130 insertions, 35 deletions
diff --git a/HELP.txt b/HELP.txt
index 7dfe3fc..7c2d7f5 100644
--- a/HELP.txt
+++ b/HELP.txt
@@ -1,28 +1,34 @@
-Usage: abc80 [options] [ihex_files...]
+Usage: ./abc80 [options] [ihex_files...]
Simulate a microcomputer from the Luxor ABC series.
- --abc80 simulate an ABC80 (default)
- --abc802 simulate an ABC802
- -4, --40 start in 40-column mode
- -8, --80 start in 80-column mode
- -b, --no-basic no BASIC ROM (uninitialized RAM instead)
- -B, --basic reverts the --no-basic option
- -d, --no-device no device driver ROMs
- -D, --device reverts the --no-device option
- --old-basic ABC80 only: run BASIC 1.0 (checksum 11273)
- --11273 same as --old-basic
- --new-basic ABC80 only: run BASIC 1.2 (checksum 9913)
- --9913 same as --new-basic
- -t, --trace ... trace various events (see "--trace help")
- -v, --version print the version string
- -h, --help print this help message
- -k, --kb set the memory size in K (ABC80: 1-32 or 64)
- --diskdir set directory for disk images (default abcdisk)
- --filedir set directory for file sharing (default abcdir)
- --scrndir set directory for screen shots (default null)
+ --abc80 simulate an ABC80 (default)
+ --abc802 simulate an ABC802
+ -4, --40 start in 40-column mode
+ -8, --80 start in 80-column mode
+ -b, --no-basic no BASIC ROM (uninitialized RAM instead)
+ -B, --basic reverts the --no-basic option
+ -d, --no-device no device driver ROMs
+ -D, --device reverts the --no-device option
+ --old-basic ABC80 only: run BASIC 1.0 (checksum 11273)
+ --11273 same as --old-basic
+ --new-basic ABC80 only: run BASIC 1.2 (checksum 9913)
+ --9913 same as --new-basic
+ -t, --trace ... trace various events (see "--trace help")
+ -T, --tracefile ... redirect trace output to a file
+ -v, --version print the version string
+ -h, --help print this help message
+ -k, --kb # set the memory size in K (ABC80: 1-32 or 64)
+ --diskdir ... set directory for disk images (default abcdisk)
+ --filedir ... set directory for file sharing (default abcdir)
+ --scrndir ... set directory for screen shots (default .)
+ --dumpdir ... set directory for memory dumps (default .)
+ --printcmd ... set command to launch a print job (* = filename)
+ --memfile ... load a file into the ABC802 MEM: device
The simulator supports the following hotkeys:
- Alt-q quit the simulator
- Alt-s take a screenshot
- Alt-r CPU reset
- Alt-n send NMI
+ Alt-q quit the simulator
+ Alt-s take a screenshot
+ Alt-r CPU reset
+ Alt-n send NMI
+ Alt-m dump memory as currently seen from the CPU
+ Alt-u dump underlying RAM only (even nonexistent)
diff --git a/abc80.c b/abc80.c
index 8b3a6a1..72cf7b8 100644
--- a/abc80.c
+++ b/abc80.c
@@ -103,14 +103,18 @@ static no_return help(void)
" -k, --kb # set the memory size in K (ABC80: 1-32 or 64)\n"
" --diskdir ... set directory for disk images (default abcdisk)\n"
" --filedir ... set directory for file sharing (default abcdir)\n"
- " --scrndir ... set directory for screen shots (default null)\n"
+ " --scrndir ... set directory for screen shots (default .)\n"
+ " --dumpdir ... set directory for memory dumps (default .)\n"
" --printcmd ... set command to launch a print job (* = filename)\n"
+ " --memfile ... load a file into the ABC802 MEM: device\n"
"\n"
"The simulator supports the following hotkeys:\n"
" Alt-q quit the simulator\n"
" Alt-s take a screenshot\n"
" Alt-r CPU reset\n"
" Alt-n send NMI\n"
+ " Alt-m dump memory as currently seen from the CPU\n"
+ " Alt-u dump underlying RAM only (even nonexistent)\n"
, program_name);
exit(1);
}
@@ -198,6 +202,7 @@ int main(int argc, char **argv)
const char *optstr;
char optchr;
const char *tracefile = NULL;
+ const char *memfile = NULL;
(void)argc;
program_name = argv[0];
@@ -256,6 +261,8 @@ int main(int argc, char **argv)
screen_path = LONG_ARG();
} else if (!strcmp(optstr, "printcmd")) {
lpr_command = LONG_ARG();
+ } else if (!strcmp(optstr, "memfile")) {
+ memfile = LONG_ARG();
} else {
fprintf(stderr, "%s: unknown option: --%s\n",
program_name, optstr);
@@ -326,7 +333,7 @@ int main(int argc, char **argv)
hostfile_init();
screen_init(width40);
- mem_init(memflags);
+ mem_init(memflags, memfile);
io_init();
/*
diff --git a/abcio.h b/abcio.h
index 3212efb..82d1a24 100644
--- a/abcio.h
+++ b/abcio.h
@@ -38,11 +38,10 @@ extern void keyboard_up(void);
extern void abc802_vsync(void);
-/* Helper in fileop.c */
-extern char *make_path(const char *prefix, const char *filename);
+extern void dump_memory(bool ramonly);
/* Directories */
-extern const char *fileop_path, *disk_path, *screen_path;
+extern const char *fileop_path, *disk_path, *screen_path, *memdump_path;
/* Program name for error messages */
extern const char *program_name;
diff --git a/abcmem.c b/abcmem.c
index ace9094..72f9910 100644
--- a/abcmem.c
+++ b/abcmem.c
@@ -3,6 +3,7 @@
#include "z80.h"
#include "abcio.h"
#include "rom.h"
+#include "hostfile.h"
#define MEMORY_SIZE Z80_ADDRESS_LIMIT
@@ -21,7 +22,7 @@ extern void write_screen(uint8_t *p, uint8_t v);
#define PAGE_SHIFT 10
#define PAGE_SIZE (1U << PAGE_SHIFT)
#define PAGE_MASK (PAGE_SIZE-1)
-#define PAGE_COUNT (65536U/PAGE_SIZE)
+#define PAGE_COUNT (Z80_ADDRESS_LIMIT/PAGE_SIZE)
/* Up to 8 memory maps */
#define MEM_MAPS 8
@@ -284,7 +285,47 @@ map_memory(unsigned int maps, size_t where, size_t size,
}
}
-void mem_init(unsigned int flags)
+/*
+ * Load a binary file into low (< 30K) RAM, in the format used by
+ * the ABC802 MEM: device.
+ */
+static void load_memfile(const char *memfile)
+{
+ struct host_file *hf;
+ uint8_t *rp;
+ size_t bytes, blk;
+
+ if (!memfile)
+ return;
+
+ hf = open_host_file(HF_BINARY, NULL, memfile, O_RDONLY);
+ if (!hf)
+ return;
+
+ rp = ram;
+ blk = 0;
+ for (blk = 0; blk < K(30)/256; blk++) {
+ bytes = fread(rp+3, 1, 253, hf->f);
+ if (!bytes)
+ break; /* Nothing left at all */
+ rp[0] = 0x53;
+ rp[1] = 0;
+ rp[2] = blk;
+ rp += 256;
+ if (bytes < 253)
+ break; /* Partial read = last block */
+ }
+
+ close_file(&hf);
+}
+
+/*
+ * Set up memory maps. Note: dump_memory() currently relies on
+ * map 7 being all RAM, regardless of if there is an actual
+ * map 7 or not. If this isn't reliable, change this to have a
+ * map set up specifically for Alt-u dumps.
+ */
+void mem_init(unsigned int flags, const char *memfile)
{
/* Start by initializing all memory maps to all RAM */
map_memory(ALL_MAPS, 0, K(64), ram, write_ram);
@@ -355,4 +396,32 @@ void mem_init(unsigned int flags)
abc802_set_mem(false); /* On start, MEM area closed */
break;
}
+
+ load_memfile(memfile);
+}
+
+/*
+ * Dump memory to a file
+ */
+const char *memdump_path;
+
+void dump_memory(bool ramonly)
+{
+ const struct mem_page *map =
+ ramonly ? memmaps[7] : current_map[0];
+ struct host_file *hf;
+ size_t i;
+
+ hf = dump_file(HF_BINARY, memdump_path,
+ ramonly ? "ram%04u.bin" : "mem%04u.bin");
+ if (!hf)
+ return;
+
+ for (i = 0; i < PAGE_COUNT; i++)
+ fwrite(map[i].data, 1, PAGE_SIZE, hf->f);
+
+ if (!ferror(hf->f))
+ keep_file(hf); /* It's good */
+
+ close_file(&hf);
}
diff --git a/hostfile.c b/hostfile.c
index 24d843f..c72ce8e 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -186,6 +186,9 @@ dump_file(enum host_file_mode mode, const char *dir, const char *pattern)
char *filename;
const int openflags = O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW;
+ if (!dir)
+ dir = "";
+
/* If it is a directory name, try to create it if it doesn't exist */
if (dir[0])
make_dir(dir);
@@ -332,8 +335,11 @@ int close_file(struct host_file **filep)
if (!filep || !(file = *filep))
return 0;
- if (file->prevp)
+ if (file->prevp) {
*file->prevp = file->next; /* Remove from linked list */
+ if (file->next)
+ file->next->prevp = file->prevp;
+ }
if (file->d) {
if (closedir(file->d))
diff --git a/screenshot.c b/screenshot.c
index 73eb948..2c74942 100644
--- a/screenshot.c
+++ b/screenshot.c
@@ -9,7 +9,7 @@
#include <png.h>
-const char *screen_path = "";
+const char *screen_path;
static inline void *pixel_row(const SDL_Surface *surf, size_t y)
{
@@ -311,7 +311,7 @@ int screenshot(SDL_Surface *surf)
memset(&a, 0, sizeof a);
rv = do_screenshot(surf, &a);
err = errno;
-
+
if (a.rgbsurf) {
SDL_UnlockSurface(a.rgbsurf);
SDL_FreeSurface(a.rgbsurf);
diff --git a/sdlscrn.c b/sdlscrn.c
index 090a34f..c705e93 100644
--- a/sdlscrn.c
+++ b/sdlscrn.c
@@ -473,6 +473,14 @@ void check_event(void)
z80_nmi();
break;
+ case SDLK_m:
+ dump_memory(false);
+ break;
+
+ case SDLK_u:
+ dump_memory(true);
+ break;
+
default:
break;
}
diff --git a/z80.h b/z80.h
index 38cfd7c..fc7e0ab 100644
--- a/z80.h
+++ b/z80.h
@@ -197,7 +197,7 @@ extern FILE *tracef;
extern uint8_t ram[]; /* Array for plain RAM */
-extern void mem_init(unsigned int flags);
+extern void mem_init(unsigned int flags, const char *memfile);
#define MEMFL_NOBASIC 1
#define MEMFL_NODEV 2