summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2018-09-18 19:48:45 -0700
committerH. Peter Anvin <hpa@zytor.com>2018-09-18 19:48:45 -0700
commitc5bb7646fd58e9e9b3976e6d553926bfe46e603e (patch)
tree3f5dce268c8900505da735e7469232ad8822da0d
parentb48072bec7a7035bb8135d779ee5792e377fa057 (diff)
downloadabc80sim-c5bb7646fd58e9e9b3976e6d553926bfe46e603e.tar.gz
abc80sim-c5bb7646fd58e9e9b3976e6d553926bfe46e603e.tar.xz
abc80sim-c5bb7646fd58e9e9b3976e6d553926bfe46e603e.zip
Actual working implementation of abc80 and 802, with user stuff...
-rw-r--r--Makefile.in14
-rw-r--r--abc80.c242
-rw-r--r--abcio.c2
-rw-r--r--abcio.h6
-rw-r--r--abcprint.c4
-rw-r--r--abcprintd.h11
-rw-r--r--clock.c2
-rw-r--r--disk.c22
-rw-r--r--fileop.c21
-rw-r--r--print.c4
10 files changed, 228 insertions, 100 deletions
diff --git a/Makefile.in b/Makefile.in
index 59097bb..904d2d8 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -33,7 +33,8 @@ SRCS = abc80.c clock.c sdlscrn.c screenshot.c z80.c abcmem.c abcio.c \
abcfont.c disk.c rtc.c abcprint.c print.c fileop.c z80dis.c \
nstime.c tempfile.c $(GENC)
HDRS = clock.h screen.h z80.h patchlevel.h screenshot.h abcio.h \
- abcprintd.h rom.h nstime.h
+ abcprintd.h rom.h nstime.h tempfile.h \
+ compiler.h config/config.h
OBJS = $(patsubst %.c,%.$(O),$(SRCS))
@@ -53,20 +54,15 @@ abc80$(X): $(OBJS)
$(PERL) bin2c.pl $< > $@ || ( rm -f $@ ; false )
.PRECIOUS: %.o
-%.o: %.c
+%.o: %.c $(HDRS)
$(CC) $(CFLAGS) -c -o $@ $<
-%.i: %.c
+%.i: %.c $(HDRS)
$(CC) $(CFLAGS) -E -o $@ $<
-%.s: %.c
+%.s: %.c $(HDRS)
$(CC) $(CFLAGS) -S -o $@ $<
-abc80.$(O): clock.h screen.h z80.h patchlevel.h
-clock.$(O): clock.h z80.h
-sdlscrn.$(O): screen.h z80.h
-z80.$(O): z80.h
-
clean:
$(RM_F) abc80$(X) *.$(O) *~ core *.lst *.i *.s *~
$(RM_F) $(GENC)
diff --git a/abc80.c b/abc80.c
index 87284f8..9574494 100644
--- a/abc80.c
+++ b/abc80.c
@@ -8,7 +8,8 @@
#include <SDL_main.h>
-static char __version_string[] = VERSION;
+static const char version_string[] = VERSION;
+static const char *program_name;
int events_in_queue = 1;
volatile int event_pending = 1;
@@ -64,73 +65,196 @@ load_sysfile(FILE *sysfile)
/*
* Print usage message
*/
-static void
-usage(void)
+
+static no_return usage(void)
{
- fprintf(stderr, "Usage: abc80 [-v] [-b] [-d] [hexfile...]\n");
+ fprintf(stderr, "Type \"%s --help\" for help\n", program_name);
exit(1);
}
-enum model model = MODEL_ABC802;
+static no_return show_version(void)
+{
+ printf("abc80sim %s\n", version_string);
+ exit(0);
+}
+
+static no_return help(void)
+{
+ printf("Usage: %s [options] [ihex_files...]\n"
+ "Simulate a microcomputer from the Luxor ABC series.\n"
+ "\n"
+ " --abc80 simulate an ABC80 (default)\n"
+ " --abc802 simulate an ABC802\n"
+ " -4, --40 start in 40-column mode\n"
+ " -8, --80 start in 80-column mode\n"
+ " -b, --no-basic no BASIC ROM (uninitialized RAM instead)\n"
+ " -B, --basic reverts the --no-basic option\n"
+ " -d, --no-device no device driver ROMs\n"
+ " -D, --device reverts the --no-device option\n"
+ " -t, --trace ... trace various events (see \"--trace help\")\n"
+ " -v, --version print the version string\n"
+ " -h, --help print this help message\n"
+ " --diskdir set directory for disk images (default abcdisk)\n"
+ " --filedir set directory for file sharing (default abcdir)\n"
+ "\n",
+ program_name);
+ exit(1);
+}
+
+static void parse_trace(char *arg)
+{
+ static const struct trace_args {
+ const char *name;
+ unsigned int mask;
+ const char *help;
+ } trace_args[] = {
+ { "all", ~0U, "all traceable events" },
+ { "cpu", TRACE_CPU, "cpu execution and memory accesses" },
+ { "io", TRACE_IO, "port I/O"},
+ { "disk", TRACE_DISK, "disk commands" },
+ { NULL, 0, NULL }
+ };
+ const struct trace_args *trp;
+
+
+ if (!arg) {
+ fprintf(stderr,
+ "%s: --trace option requires an event list "
+ "(see --trace help)\n",
+ program_name);
+ usage();
+ }
+
+ if (!strcmp(arg, "help")) {
+ printf("Option: %s --trace [no-]event[,[no-]event...]\n"
+ " The \"no-\" prefix disables a trace event.\n"
+ " The following trace events are currently implemented:\n",
+ program_name);
+ for (trp = trace_args; trp->name; trp++)
+ printf(" %-7s %s\n", trp->name, trp->help);
+ exit(0);
+ }
+
-extern int optind;
-extern char *optarg;
-extern int getopt(int, char * const *, const char *);
+ for (arg = strtok(arg, ","); arg; arg = strtok(NULL, ",")) {
+ bool invert = false;
+ if (!strcmp(arg, "none")) {
+ tracing = 0;
+ continue;
+ }
+ if (!strncmp(arg, "no-", 3)) {
+ arg += 3;
+ invert = true;
+ }
+ for (trp = trace_args; trp->name; trp++) {
+ if (!strcmp(arg, trp->name)) {
+ if (invert)
+ tracing &= ~trp->mask;
+ else
+ tracing |= trp->mask;
+ }
+ }
+ }
+}
+
+enum model model = MODEL_ABC80;
int main(int argc, char **argv)
{
unsigned int memflags = 0;
bool width40 = false;
- int c;
-
- while ((c = getopt(argc, argv, "bdvt:48")) != EOF) {
- switch (c) {
-
- case 'v':
- printf("ABC80 emulator version %s\n", __version_string);
- exit(0);
- break;
-
- case 'b':
- memflags |= MEMFL_NOBASIC;
- break;
-
- case 'd':
- memflags |= MEMFL_NODEV;
- break;
-
- case 't':
- {
- const char *tok;
- tok = strtok(optarg, ",");
- while (tok) {
- if (!strcasecmp(tok, "cpu"))
- tracing |= TRACE_CPU;
- else if (!strcasecmp(tok, "io"))
- tracing |= TRACE_IO;
- else if (!strcasecmp(tok, "disk"))
- tracing |= TRACE_DISK;
- else if (!strcasecmp(tok, "all"))
- tracing = -1;
-
- tok = strtok(NULL, ",");
- }
- break;
- }
+ char **option;
+ const char *optstr;
+ char optchr;
- case '4':
- width40 = true;
- break;
+ (void)argc;
+ program_name = argv[0];
- case '8':
- width40 = false;
- break;
+ option = &argv[1];
+ while ((optstr = *option) != NULL) {
+ if (*optstr++ != '-')
+ break; /* Not an option */
- default:
- usage();
- exit(1);
- break;
- }
+ option++;
+
+ optchr = *optstr++;
+ if (optchr == '-') {
+ /* Long option */
+
+ if (!optstr[0])
+ break; /* -- means end of options */
+
+ if (!strcmp(optstr, "abc80")) {
+ model = MODEL_ABC80;
+ } else if (!strcmp(optstr, "abc802")) {
+ model = MODEL_ABC802;
+ } else if (!strcmp(optstr, "40")) {
+ width40 = true;
+ } else if (!strcmp(optstr, "80")) {
+ width40 = false;
+ } else if (!strcmp(optstr, "no-basic")) {
+ memflags |= MEMFL_NOBASIC;
+ } else if (!strcmp(optstr, "basic")) {
+ memflags &= ~MEMFL_NOBASIC;
+ } else if (!strcmp(optstr, "no-device")) {
+ memflags |= MEMFL_NODEV;
+ } else if (!strcmp(optstr, "device")) {
+ memflags &= ~MEMFL_NODEV;
+ } else if (!strcmp(optstr, "help")) {
+ help();
+ } else if (!strcmp(optstr, "version")) {
+ show_version();
+ } else if (!strcmp(optstr, "trace")) {
+ parse_trace(*option++);
+ } else if (!strcmp(optstr, "diskdir")) {
+ disk_path = *option++;
+ } else if (!strcmp(optstr, "filedir")) {
+ fileop_path = *option++;
+ } else {
+ fprintf(stderr, "%s: unknown option: --%s\n",
+ program_name, optstr);
+ usage();
+ }
+ } else {
+ /* Short option */
+ while (optchr) {
+ switch (optchr) {
+ case 't':
+ parse_trace(*option++);
+ break;
+ case 'b':
+ memflags |= MEMFL_NOBASIC;
+ break;
+ case 'B':
+ memflags &= ~MEMFL_NOBASIC;
+ break;
+ case 'd':
+ memflags |= MEMFL_NODEV;
+ break;
+ case 'D':
+ memflags &= ~MEMFL_NODEV;
+ break;
+ case '4':
+ width40 = true;
+ break;
+ case '8':
+ width40 = false;
+ break;
+ case 'v':
+ show_version();
+ break;
+ case 'h':
+ help();
+ break;
+ default:
+ fprintf(stderr, "%s: unknown option: -%c\n",
+ program_name, optchr);
+ usage();
+ break;
+ }
+ optchr = *optstr++;
+ }
+ }
}
screen_init(width40);
@@ -141,16 +265,16 @@ int main(int argc, char **argv)
* Load any other program files the
* user gave on the command line.
*/
- while (optind < argc) {
- const char *sysfile_name = argv[optind];
+ while (*option) {
+ const char *sysfile_name = *option++;
FILE *sysfile;
if ((sysfile = fopen(sysfile_name, "r")) == NULL) {
- fprintf(stderr, "ABC80: Can't open file: %s\n", sysfile_name);
+ fprintf(stderr, "%s: Can't open file: %s: %s\n",
+ argv[0], sysfile_name, strerror(errno));
exit(1);
}
load_sysfile(sysfile);
fclose(sysfile);
- optind++;
}
/*
diff --git a/abcio.c b/abcio.c
index 173fea4..a987557 100644
--- a/abcio.c
+++ b/abcio.c
@@ -286,7 +286,7 @@ static uint8_t abc80_in(uint8_t port)
{
uint8_t v = 0xff;
- port &= 0x1f;
+ port &= 0x17;
switch (port) {
case 0:
diff --git a/abcio.h b/abcio.h
index 5f5e3ca..db3b5fb 100644
--- a/abcio.h
+++ b/abcio.h
@@ -36,4 +36,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);
+
+/* Directories */
+extern const char *fileop_path, *disk_path;
+
#endif
diff --git a/abcprint.c b/abcprint.c
index 766da90..12acf9d 100644
--- a/abcprint.c
+++ b/abcprint.c
@@ -3,10 +3,10 @@
void printer_reset(void)
{
- static int init = 0;
+ static bool init = false;
if (!init) {
- fileop_prefix = "abcdir/";
+ init = true;
abcprint_init();
}
}
diff --git a/abcprintd.h b/abcprintd.h
index 0c15d08..3dec0ef 100644
--- a/abcprintd.h
+++ b/abcprintd.h
@@ -7,20 +7,11 @@
#include <locale.h>
#include <wchar.h>
-#ifndef O_TEXT
-# define O_TEXT 0
-#endif
-#ifndef O_BINARY
-# define O_BINARY 0
-#endif
-
-extern int lpr_argc;
-extern const char **lpr_argv;
extern void abcprint_init(void);
extern void abcprint(const void *, size_t);
extern int abcprint_read(void);
extern int abcprint_poll(void);
extern bool file_op(unsigned char);
-extern const char *fileop_prefix;
+extern const char *fileop_path, *lpr_command;
#endif
diff --git a/clock.c b/clock.c
index 2de4c63..15a8542 100644
--- a/clock.c
+++ b/clock.c
@@ -38,7 +38,7 @@ void timer_init(void)
static inline bool trigger(uint64_t now, struct abctimer *tmr)
{
/* This expression: a) will overflow safely, b) will never trigger for 0 */
- if (likely((now - tmr->last) < tmr->period))
+ if (likely((now - tmr->last) <= (tmr->period - 1)))
return false;
tmr->last += tmr->period;
diff --git a/disk.c b/disk.c
index d996337..0b064db 100644
--- a/disk.c
+++ b/disk.c
@@ -6,6 +6,8 @@
#include "z80.h"
#include "abcio.h"
+const char *disk_path = "abcdisk";
+
#define NOTTHERE 0
#define READONLY 0
#define INTERLEAVE 0
@@ -112,15 +114,23 @@ static void disk_reset_state(struct ctl_state *state)
static void disk_init(struct ctl_state *state)
{
- char filename[64];
+ char *filename;
+ char devname[4];
int i;
/* If any of these don't exist we simply report device not ready */
- for (i = 0; i < 8; i++) {
- snprintf(filename, sizeof filename, "abcdisk/%s%d", state->name, i);
- state->files[i] = fopen(filename, "r+b");
- if (!state->files[i])
- state->files[i] = fopen(filename, "rb"); /* Try open readonly */
+ if (disk_path) {
+ devname[0] = state->name[0];
+ devname[1] = state->name[1];
+ devname[3] = '\0';
+ for (i = 0; i < 8; i++) {
+ devname[2] = i + '0';
+ filename = make_path(disk_path, devname);
+ state->files[i] = fopen(filename, "r+b");
+ if (!state->files[i])
+ state->files[i] = fopen(filename, "rb"); /* Try open readonly */
+ free(filename);
+ }
}
disk_reset_state(state);
}
diff --git a/fileop.c b/fileop.c
index 56bf023..3e5c768 100644
--- a/fileop.c
+++ b/fileop.c
@@ -1,16 +1,17 @@
#include "abcprintd.h"
+#include "abcio.h"
-const char *fileop_prefix;
+const char *fileop_path = "abcdir";
#define BUF_SIZE 512
static unsigned char output_buf[BUF_SIZE];
static int output_head, output_tail;
-static char *make_path(const char *filename)
+char *make_path(const char *prefix, const char *filename)
{
char *p;
- int pl = strlen(fileop_prefix);
+ int pl = strlen(prefix);
int fl = strlen(filename);
p = malloc(pl + fl + 2);
@@ -19,13 +20,13 @@ static char *make_path(const char *filename)
exit(1);
}
- sprintf(p, "%s%s%s", fileop_prefix,
+ sprintf(p, "%s%s%s", prefix,
(pl > 0 &&
#ifdef WIN32
- fileop_prefix[pl-1] != ':' &&
- fileop_prefix[pl-1] != '\\' &&
+ prefix[pl-1] != ':' &&
+ prefix[pl-1] != '\\' &&
#endif
- fileop_prefix[pl-1] != ':') ? "/" : "",
+ prefix[pl-1] != ':') ? "/" : "",
filename);
return p;
@@ -168,7 +169,7 @@ static void do_open(uint16_t ix, char *name)
char path_buf[64];
char *path;
- if (!fileop_prefix) {
+ if (!fileop_path) {
send_reply(128+42); /* Skivan ej klar */
return;
}
@@ -176,7 +177,7 @@ static void do_open(uint16_t ix, char *name)
do_close(ix);
unmangle_filename(path_buf, name);
- path = make_path(path_buf[0] ? path_buf : ".");
+ path = make_path(fileop_path, path_buf[0] ? path_buf : ".");
if (!path) {
send_reply(128+42);
return;
@@ -414,7 +415,7 @@ static void do_input(uint16_t ix)
if (de->d_name[0] != '.' &&
(dlen = mangle_for_readdir(data1+2, de->d_name))) {
bool ok;
- path = make_path(de->d_name);
+ path = make_path(fileop_path, de->d_name);
if (!path) {
err = 128+42;
goto err;
diff --git a/print.c b/print.c
index b07a6e0..86fc38e 100644
--- a/print.c
+++ b/print.c
@@ -22,9 +22,9 @@
#include "tempfile.h"
#ifdef __WIN32__
-const char lpr_command[] = "powershell -command \"GetContent -raw -path '*' | OutPrinter\"";
+const char *lpr_command = "powershell -command \"GetContent -raw -path '*' | OutPrinter\"";
#else
-const char lpr_command[] = "lpr '*'";
+const char *lpr_command = "lpr '*'";
#endif
static struct temp_file *temp;