diff options
-rwxr-xr-x | Nindent | 18 | ||||
-rw-r--r-- | abc80.c | 620 | ||||
-rw-r--r-- | abcfile.c | 291 | ||||
-rw-r--r-- | abcfont.c | 512 | ||||
-rw-r--r-- | abcio.c | 685 | ||||
-rw-r--r-- | abcio.h | 4 | ||||
-rw-r--r-- | abcmem.c | 241 | ||||
-rw-r--r-- | cas.c | 645 | ||||
-rw-r--r-- | clib/asprintf.c | 16 | ||||
-rw-r--r-- | clib/inttypes.h | 38 | ||||
-rw-r--r-- | clock.c | 313 | ||||
-rw-r--r-- | compiler.h | 156 | ||||
-rw-r--r-- | console.c | 54 | ||||
-rw-r--r-- | disk.c | 494 | ||||
-rw-r--r-- | filelist.c | 54 | ||||
-rw-r--r-- | fileop.c | 1124 | ||||
-rw-r--r-- | hostfile.c | 352 | ||||
-rw-r--r-- | hostfile.h | 51 | ||||
-rw-r--r-- | nstime.c | 108 | ||||
-rw-r--r-- | print.c | 223 | ||||
-rw-r--r-- | rtc.c | 149 | ||||
-rw-r--r-- | screen.h | 16 | ||||
-rw-r--r-- | screenshot.c | 401 | ||||
-rw-r--r-- | sdlscrn.c | 1010 | ||||
-rw-r--r-- | simprint.c | 215 | ||||
-rw-r--r-- | trace.c | 44 | ||||
-rw-r--r-- | trace.h | 16 | ||||
-rw-r--r-- | z80.c | 5351 | ||||
-rw-r--r-- | z80.h | 31 | ||||
-rw-r--r-- | z80asm/gnulib/getopt.c | 1497 | ||||
-rw-r--r-- | z80asm/gnulib/getopt.h | 66 | ||||
-rw-r--r-- | z80asm/gnulib/getopt1.c | 196 | ||||
-rw-r--r-- | z80asm/gnulib/gettext.h | 22 | ||||
-rw-r--r-- | z80asm/z80asm.c | 5867 | ||||
-rw-r--r-- | z80dis.c | 610 | ||||
-rw-r--r-- | z80irq.c | 32 | ||||
-rw-r--r-- | z80irq.h | 17 |
37 files changed, 10592 insertions, 10947 deletions
@@ -0,0 +1,18 @@ +#!/bin/sh +PARAM="-npro -kr -i4 -ts8 -nut -sob -l80 -ss -ncs -cp1" +RES=`indent --version` +V1=`echo $RES | cut -d' ' -f3 | cut -d'.' -f1` +V2=`echo $RES | cut -d' ' -f3 | cut -d'.' -f2` +V3=`echo $RES | cut -d' ' -f3 | cut -d'.' -f3` +if [ $V1 -gt 2 ]; then + PARAM="$PARAM -il0" +elif [ $V1 -eq 2 ]; then + if [ $V2 -gt 2 ]; then + PARAM="$PARAM -il0"; + elif [ $V2 -eq 2 ]; then + if [ $V3 -ge 10 ]; then + PARAM="$PARAM -il0" + fi + fi +fi +exec indent $PARAM "$@" @@ -16,8 +16,8 @@ static int z80_thread(void *); -double ns_per_tstate = 1000.0/3.0; /* Nanoseconds per tstate (clock cycle) */ -double tstate_per_ns = 3.0/1000.0; /* Inverse of the above = freq in GHz */ +double ns_per_tstate = 1000.0 / 3.0; /* Nanoseconds per tstate (clock cycle) */ +double tstate_per_ns = 3.0 / 1000.0; /* Inverse of the above = freq in GHz */ bool limit_speed = true; static const char version_string[] = VERSION; @@ -34,33 +34,32 @@ int events_in_queue = 1; volatile int event_pending = 1; /* This reflects the screen width at system boot; e.g. ABC802 jumper setting */ -bool startup_width40 = false; +bool startup_width40 = false; /* * Read a two digit hex number from a string * and return its numeric value. */ -static char *hexstring = "0123456789ABCDEF"; +static char *hexstring = "0123456789ABCDEF"; static uint8_t gethex(char *p) { - return (uint8_t)(((strchr(hexstring, *p) - hexstring) << 4) - + (strchr(hexstring, *(p + 1)) - hexstring)); + return (uint8_t) (((strchr(hexstring, *p) - hexstring) << 4) + + (strchr(hexstring, *(p + 1)) - hexstring)); } /* * Load in Intel-hex file into memory. * No checking of the checksum is performed. */ -static void -load_sysfile(FILE *sysfile) +static void load_sysfile(FILE * sysfile) { uint8_t *memory; - char line[128]; + char line[128]; char *pos; - int len; - int type; + int len; + int type; - while ( !feof(sysfile) ) { + while (!feof(sysfile)) { memory = ram; fgets(line, 128, sysfile); if (line[0] != ':') { @@ -68,15 +67,19 @@ load_sysfile(FILE *sysfile) exit(1); } pos = line + 1; - len = gethex(pos); pos += 2; - memory += (gethex(pos) << 8); pos += 2; - memory += gethex(pos); pos += 2; - type = gethex(pos); pos += 2; - if (type == 1) - break; /* End of file record */ - if (type != 0) - continue; /* Not a data record */ - while (len--) { + len = gethex(pos); + pos += 2; + memory += (gethex(pos) << 8); + pos += 2; + memory += gethex(pos); + pos += 2; + type = gethex(pos); + pos += 2; + if (type == 1) + break; /* End of file record */ + if (type != 0) + continue; /* Not a data record */ + while (len--) { *memory++ = gethex(pos); pos += 2; } @@ -102,106 +105,105 @@ static no_return show_version(void) static no_return help(void) { printf("Usage: %s [options] [ihex_files...]\n" - "Simulate a microcomputer from the Luxor ABC series.\n" - "\n" - "Options (defaults in brackets):\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 (default)\n" - " -b, --no-basic no BASIC ROM (uninitialized RAM instead)\n" - " --basic reverts the --no-basic option\n" - " -d, --no-device no device driver ROMs\n" - " --device reverts the --no-device option\n" - " -t, --trace event,... trace various events (see \"--trace help\")\n" - " -Ft, --tracefile file redirect trace output to a file\n" - " -v, - -version print the version string\n" - " -h, --help print this help message\n" - " -s, --speed #.#|max set the CPU frequency to #.# MHz [3.0]\n" - " --color allow ABC800C-style color (default)\n" - " --no-color black and white only\n" - " -Dd, --diskdir dir set directory for disk images [abcdisk]\n" - " -Df, --filedir dir set directory for file sharing [abcdir]\n" - " -Ds, --scrndir dir set directory for screen shots [.]\n" - " -Dd, --dumpdir dir set directory for memory dumps [.]\n" - " -Cp, --printcmd cmd set command to launch a print job (* = filename)\n" - " -Fc, --casfile file input file for cassette (CAS:)\n" - " -Lc, --caslist file read list of files for the cassette from a file\n" - " -Dc, --casdir dir set directory for named cassette files [= filedir]\n" - " -e, --console enable console output device (PRC:)\n" - " -Fe, --consolefile file enable console output device to a file\n" - " --detach detach from console if run from a command line\n" - "\n" - "Options for ABC80 only:\n" - " -k, --kb # set the memory size K (1-32 or 64)\n" - " --old-basic run BASIC 1.0 (checksum 11273)\n" - " --11273 same as --old-basic\n" - " --new-basic run BASIC 1.2 (checksum 9913)\n" - " --9913 same as --new-basic\n" - " --faketype fake short keystrokes (default > 12.5 MHz)\n" - " --realtype true key up/down emulation (default < 12.5 MHz)\n" - "\n" - "Options for ABC802 only:\n" - " -Fm, --memfile file 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" - " Alt-f turn faketype on or off\n" - , program_name); + "Simulate a microcomputer from the Luxor ABC series.\n" + "\n" + "Options (defaults in brackets):\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 (default)\n" + " -b, --no-basic no BASIC ROM (uninitialized RAM instead)\n" + " --basic reverts the --no-basic option\n" + " -d, --no-device no device driver ROMs\n" + " --device reverts the --no-device option\n" + " -t, --trace event,... trace various events (see \"--trace help\")\n" + " -Ft, --tracefile file redirect trace output to a file\n" + " -v, - -version print the version string\n" + " -h, --help print this help message\n" + " -s, --speed #.#|max set the CPU frequency to #.# MHz [3.0]\n" + " --color allow ABC800C-style color (default)\n" + " --no-color black and white only\n" + " -Dd, --diskdir dir set directory for disk images [abcdisk]\n" + " -Df, --filedir dir set directory for file sharing [abcdir]\n" + " -Ds, --scrndir dir set directory for screen shots [.]\n" + " -Dd, --dumpdir dir set directory for memory dumps [.]\n" + " -Cp, --printcmd cmd set command to launch a print job (* = filename)\n" + " -Fc, --casfile file input file for cassette (CAS:)\n" + " -Lc, --caslist file read list of files for the cassette from a file\n" + " -Dc, --casdir dir set directory for named cassette files [= filedir]\n" + " -e, --console enable console output device (PRC:)\n" + " -Fe, --consolefile file enable console output device to a file\n" + " --detach detach from console if run from a command line\n" + "\n" + "Options for ABC80 only:\n" + " -k, --kb # set the memory size K (1-32 or 64)\n" + " --old-basic run BASIC 1.0 (checksum 11273)\n" + " --11273 same as --old-basic\n" + " --new-basic run BASIC 1.2 (checksum 9913)\n" + " --9913 same as --new-basic\n" + " --faketype fake short keystrokes (default > 12.5 MHz)\n" + " --realtype true key up/down emulation (default < 12.5 MHz)\n" + "\n" + "Options for ABC802 only:\n" + " -Fm, --memfile file 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" + " Alt-f turn faketype on or off\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; + const char *name; + unsigned int mask; + const char *help; } trace_args[] = { - { "all", TRACE_ALL, "all traceable events" }, - { "cpu", TRACE_CPU, "cpu execution and memory accesses" }, - { "io", TRACE_IO, "port I/O"}, - { "disk", TRACE_DISK, "disk commands" }, - { "cas", TRACE_CAS, "cassette I/O" }, - { "pr", TRACE_PR, "printer interface"}, - { NULL, 0, NULL } + { + "all", TRACE_ALL, "all traceable events"}, { + "cpu", TRACE_CPU, "cpu execution and memory accesses"}, { + "io", TRACE_IO, "port I/O"}, { + "disk", TRACE_DISK, "disk commands"}, { + "cas", TRACE_CAS, "cassette I/O"}, { + "pr", TRACE_PR, "printer interface"}, { + NULL, 0, NULL} }; const struct trace_args *trp; 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); + 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); } - for (arg = strtok(arg, ","); arg; arg = strtok(NULL, ",")) { - bool invert = false; - if (!strcmp(arg, "none")) { - traceflags = TRACE_NONE; - continue; - } - if (!strncmp(arg, "no-", 3)) { - arg += 3; - invert = true; - } - for (trp = trace_args; trp->name; trp++) { - if (!strcmp(arg, trp->name)) { - if (invert) - traceflags &= ~trp->mask; - else - traceflags |= trp->mask; - } - } + bool invert = false; + if (!strcmp(arg, "none")) { + traceflags = TRACE_NONE; + continue; + } + if (!strncmp(arg, "no-", 3)) { + arg += 3; + invert = true; + } + for (trp = trace_args; trp->name; trp++) { + if (!strcmp(arg, trp->name)) { + if (invert) + traceflags &= ~trp->mask; + else + traceflags |= trp->mask; + } + } } } @@ -209,11 +211,11 @@ static void set_speed(const char *arg) { double mhz = atof(arg); if (mhz <= 0.001 || mhz >= 1.0e+6) { - limit_speed = false; + limit_speed = false; } else { - limit_speed = true; - ns_per_tstate = 1000.0/mhz; - tstate_per_ns = mhz/1000.0; + limit_speed = true; + ns_per_tstate = 1000.0 / mhz; + tstate_per_ns = mhz / 1000.0; } } @@ -232,53 +234,53 @@ static void add_caslist(const char *what, const char **pvt) } struct path_option { - const char *opt[2]; /* Short and long */ + const char *opt[2]; /* Short and long */ const char **what; - void (*set_special)(const char *, const char **); + void (*set_special) (const char *, const char **); }; static const struct path_option path_options[] = { - { { "Ft", "-tracefile" }, &tracefile, NULL }, - { { "Dd", "-diskdir" }, &disk_path, NULL }, - { { "Df", "-filedir" }, &fileop_path, NULL }, - { { "Ds", "-scrndir" }, &screen_path, NULL }, - { { "Dd", "-dumpdir" }, &memdump_path, NULL }, - { { "Cp", "-printcmd" }, &lpr_command, NULL }, - { { "Fe", "-consolefile" }, &console_filename, NULL }, - { { "Fm", "-memfile" }, &memfile, NULL }, - { { "Fc", "-casfile" }, NULL, add_casfile }, - { { "Lc", "-caslist" }, NULL, add_caslist }, - { { "Dc", "-casdir" }, &cas_path, NULL }, + {{"Ft", "-tracefile"}, &tracefile, NULL}, + {{"Dd", "-diskdir"}, &disk_path, NULL}, + {{"Df", "-filedir"}, &fileop_path, NULL}, + {{"Ds", "-scrndir"}, &screen_path, NULL}, + {{"Dd", "-dumpdir"}, &memdump_path, NULL}, + {{"Cp", "-printcmd"}, &lpr_command, NULL}, + {{"Fe", "-consolefile"}, &console_filename, NULL}, + {{"Fm", "-memfile"}, &memfile, NULL}, + {{"Fc", "-casfile"}, NULL, add_casfile}, + {{"Lc", "-caslist"}, NULL, add_caslist}, + {{"Dc", "-casdir"}, &cas_path, NULL}, }; static int set_path(const char *opt, const char *what) { - const int nopts = (sizeof path_options)/(sizeof path_options[0]); + const int nopts = (sizeof path_options) / (sizeof path_options[0]); const struct path_option *po; int i, j; po = path_options; for (i = 0; i < nopts; i++) { - for (j = 0; j < 2; j++) { - if (!strcmp(po->opt[j], opt)) - goto found; - } - po++; + for (j = 0; j < 2; j++) { + if (!strcmp(po->opt[j], opt)) + goto found; + } + po++; } - return -1; /* Not a valid file option */ + return -1; /* Not a valid file option */ found: if (!what) { - fprintf(stderr, "%s: the -%s option requires an argument\n", - program_name, opt); - usage(); + fprintf(stderr, "%s: the -%s option requires an argument\n", + program_name, opt); + usage(); } if (po->set_special) { - po->set_special(what, po->what); + po->set_special(what, po->what); } else { - *po->what = what; + *po->what = what; } return 0; @@ -292,9 +294,9 @@ bool old_basic = false; static char *short_arg(char opt, char *arg) { if (!arg) { - fprintf(stderr, "%s: the -%c option requires an argument\n", - program_name, opt); - usage(); + fprintf(stderr, "%s: the -%c option requires an argument\n", + program_name, opt); + usage(); } return arg; } @@ -302,14 +304,13 @@ static char *short_arg(char opt, char *arg) static char *long_arg(bool enable, const char *opt, char *arg) { if (!enable) { - fprintf(stderr, "%s: unknown option: --no-%s\n", - program_name, opt); - usage(); + fprintf(stderr, "%s: unknown option: --no-%s\n", program_name, opt); + usage(); } if (!arg) { - fprintf(stderr, "%s: the --%s option requires an argument\n", - program_name, opt); - usage(); + fprintf(stderr, "%s: the --%s option requires an argument\n", + program_name, opt); + usage(); } return arg; } @@ -336,181 +337,178 @@ int main(int argc, char **argv) option = &argv[1]; while ((optstr = *option) != NULL) { - if (*optstr++ != '-') - break; /* Not an option */ - - option++; - - optchr = *optstr++; - if (optchr == '-') { - bool enable = true; - - /* Long option */ - - if (!optstr[0]) - break; /* -- means end of options */ - - if (!strncmp(optstr, "no-", 3)) { - enable = false; - optstr += 3; - } - if (!strcmp(optstr, "abc80")) { - model = MODEL_ABC80; - } else if (!strcmp(optstr, "abc802")) { - model = MODEL_ABC802; - } else if (!strcmp(optstr, "40")) { - startup_width40 = enable; - } else if (!strcmp(optstr, "80")) { - startup_width40 = !enable; - } else if (!strcmp(optstr, "basic")) { - memflags &= ~MEMFL_NOBASIC; - memflags |= (enable ? 0 : MEMFL_NOBASIC); - } else if (!strcmp(optstr, "old-basic") || - !strcmp(optstr, "11273")) { - old_basic = enable; - } else if (!strcmp(optstr, "new-basic") || - !strcmp(optstr, "9913")) { - old_basic = !enable; - } else if (!strcmp(optstr, "device")) { - memflags &= ~MEMFL_NODEV; - memflags |= enable ? 0 : MEMFL_NODEV; - } else if (!strcmp(optstr, "kb")) { - kilobytes = strtoul(LONG_ARG(), NULL, 0); - } else if (!strcmp(optstr, "help")) { - if (enable) - help(); - } else if (!strcmp(optstr, "version")) { - if (enable) - show_version(); - } else if (!strcmp(optstr, "trace")) { - parse_trace(LONG_ARG()); - } else if (!strcmp(optstr, "detach")) { - detach = enable; - } else if (!strcmp(optstr, "color") || - !strcmp(optstr, "colour")) { - color = enable; - } else if (!strcmp(optstr, "MHz") || - !strcmp(optstr, "mhz") || - !strcmp(optstr, "speed") || - !strcmp(optstr, "frequency")) { - set_speed(LONG_ARG()); - } else if (!strcmp(optstr, "faketype")) { - faketype = enable; - faketype_set = true; - } else if (!strcmp(optstr, "realtype")) { - faketype = !enable; - faketype_set = true; - } else { - if (set_path(optstr-1, *option++)) { - fprintf(stderr, "%s: unknown option: --%s\n", - program_name, optstr); - usage(); - } - } - } else { - /* Short option */ - while (optchr) { - switch (optchr) { - case 't': - parse_trace(SHORT_ARG()); - break; - case 'b': - memflags |= MEMFL_NOBASIC; - break; - case 'e': - console = true; - break; - case 'd': - memflags |= MEMFL_NODEV; - break; - case '4': - startup_width40 = true; - break; - case '8': - startup_width40 = false; - break; - case 'k': - kilobytes = strtoul(SHORT_ARG(), NULL, 0); - break; - case 's': - set_speed(SHORT_ARG()); - break; - case 'F': - case 'C': - case 'D': - case 'L': - { - /* Various types of file paths */ - char fopt[3]; - fopt[0] = optchr; - fopt[1] = *optstr++; - fopt[2] = '\0'; - /* If *optstr was \0, set_path() will error out */ - if (set_path(fopt, *option++)) { - fprintf(stderr, "%s: unknown option: -%s\n", - program_name, fopt); - usage(); - } - 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++; - } - } + if (*optstr++ != '-') + break; /* Not an option */ + + option++; + + optchr = *optstr++; + if (optchr == '-') { + bool enable = true; + + /* Long option */ + + if (!optstr[0]) + break; /* -- means end of options */ + + if (!strncmp(optstr, "no-", 3)) { + enable = false; + optstr += 3; + } + if (!strcmp(optstr, "abc80")) { + model = MODEL_ABC80; + } else if (!strcmp(optstr, "abc802")) { + model = MODEL_ABC802; + } else if (!strcmp(optstr, "40")) { + startup_width40 = enable; + } else if (!strcmp(optstr, "80")) { + startup_width40 = !enable; + } else if (!strcmp(optstr, "basic")) { + memflags &= ~MEMFL_NOBASIC; + memflags |= (enable ? 0 : MEMFL_NOBASIC); + } else if (!strcmp(optstr, "old-basic") || !strcmp(optstr, "11273")) { + old_basic = enable; + } else if (!strcmp(optstr, "new-basic") || !strcmp(optstr, "9913")) { + old_basic = !enable; + } else if (!strcmp(optstr, "device")) { + memflags &= ~MEMFL_NODEV; + memflags |= enable ? 0 : MEMFL_NODEV; + } else if (!strcmp(optstr, "kb")) { + kilobytes = strtoul(LONG_ARG(), NULL, 0); + } else if (!strcmp(optstr, "help")) { + if (enable) + help(); + } else if (!strcmp(optstr, "version")) { + if (enable) + show_version(); + } else if (!strcmp(optstr, "trace")) { + parse_trace(LONG_ARG()); + } else if (!strcmp(optstr, "detach")) { + detach = enable; + } else if (!strcmp(optstr, "color") || !strcmp(optstr, "colour")) { + color = enable; + } else if (!strcmp(optstr, "MHz") || + !strcmp(optstr, "mhz") || + !strcmp(optstr, "speed") || + !strcmp(optstr, "frequency")) { + set_speed(LONG_ARG()); + } else if (!strcmp(optstr, "faketype")) { + faketype = enable; + faketype_set = true; + } else if (!strcmp(optstr, "realtype")) { + faketype = !enable; + faketype_set = true; + } else { + if (set_path(optstr - 1, *option++)) { + fprintf(stderr, "%s: unknown option: --%s\n", + program_name, optstr); + usage(); + } + } + } else { + /* Short option */ + while (optchr) { + switch (optchr) { + case 't': + parse_trace(SHORT_ARG()); + break; + case 'b': + memflags |= MEMFL_NOBASIC; + break; + case 'e': + console = true; + break; + case 'd': + memflags |= MEMFL_NODEV; + break; + case '4': + startup_width40 = true; + break; + case '8': + startup_width40 = false; + break; + case 'k': + kilobytes = strtoul(SHORT_ARG(), NULL, 0); + break; + case 's': + set_speed(SHORT_ARG()); + break; + case 'F': + case 'C': + case 'D': + case 'L': + { + /* Various types of file paths */ + char fopt[3]; + fopt[0] = optchr; + fopt[1] = *optstr++; + fopt[2] = '\0'; + /* If *optstr was \0, set_path() will error out */ + if (set_path(fopt, *option++)) { + fprintf(stderr, "%s: unknown option: -%s\n", + program_name, fopt); + usage(); + } + 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++; + } + } } if (!faketype_set) - faketype = !limit_speed || (ns_per_tstate < 1000.0/12.5); + faketype = !limit_speed || (ns_per_tstate < 1000.0 / 12.5); /* If no --casdir has been given, default to --filedir */ if (!cas_path) - cas_path = fileop_path; + cas_path = fileop_path; hostfile_init(); if (memfile && model != MODEL_ABC802) { - fprintf(stderr, "WARNING: --memfile specified for a system " - "other than ABC802 - not possible\n"); + fprintf(stderr, "WARNING: --memfile specified for a system " + "other than ABC802 - not possible\n"); } if (traceflags) { - if (is_stdio(tracefile)) { - tracef = stdout; - } else { - tracef = fopen(tracefile, "wt"); - if (!tracef) { - fprintf(stderr, "%s: Unable to open trace file %s: %s\n", - program_name, tracefile, strerror(errno)); - traceflags = TRACE_NONE; - } - } + if (is_stdio(tracefile)) { + tracef = stdout; + } else { + tracef = fopen(tracefile, "wt"); + if (!tracef) { + fprintf(stderr, "%s: Unable to open trace file %s: %s\n", + program_name, tracefile, strerror(errno)); + traceflags = TRACE_NONE; + } + } } if (console) { - if (is_stdio(console_filename)) { - console_file = stdout; - } else { - console_file = fopen(console_filename, "wt"); - if (!console_file) { - fprintf(stderr, "%s: Unable to open console file %s: %s\n", - program_name, console_filename, strerror(errno)); - } - } + if (is_stdio(console_filename)) { + console_file = stdout; + } else { + console_file = fopen(console_filename, "wt"); + if (!console_file) { + fprintf(stderr, "%s: Unable to open console file %s: %s\n", + program_name, console_filename, strerror(errno)); + } + } } if (detach) - detach_console(); + detach_console(); screen_init(startup_width40, color); @@ -522,22 +520,22 @@ int main(int argc, char **argv) * user gave on the command line. */ while (*option) { - const char *sysfile_name = *option++; - FILE *sysfile; - if ((sysfile = fopen(sysfile_name, "r")) == NULL) { - fprintf(stderr, "%s: Can't open file: %s: %s\n", - argv[0], sysfile_name, strerror(errno)); - exit(1); - } - load_sysfile(sysfile); - fclose(sysfile); + const char *sysfile_name = *option++; + FILE *sysfile; + if ((sysfile = fopen(sysfile_name, "r")) == NULL) { + fprintf(stderr, "%s: Can't open file: %s: %s\n", + argv[0], sysfile_name, strerror(errno)); + exit(1); + } + load_sysfile(sysfile); + fclose(sysfile); } /* * Off we go... */ cpu_thread = SDL_CreateThread(z80_thread, NULL); - event_loop(); /* Handling external events and screen */ + event_loop(); /* Handling external events and screen */ z80_quit = true; SDL_WaitThread(cpu_thread, NULL); @@ -3,128 +3,127 @@ */ #include "abcfile.h" -#include "hostfile.h" /* For host_strip_path() */ +#include "hostfile.h" /* For host_strip_path() */ #include <wchar.h> void unmangle_filename(char *dst, const char *src) { - static const wchar_t my_tolower[256] = - L"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" - L"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" - L" !\"#¤%&'()*+,-./0123456789:;<=>?" - L"éabcdefghijklmnopqrstuvwxyzäöåü_" - L"éabcdefghijklmnopqrstuvwxyzäöåü\377" - L"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217" - L"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237" - L"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257" - L"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" - L"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317" - L"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" - L"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" - L"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"; - int i; - - wctomb(NULL, 0); - - for (i = 0; i < 8; i++) { - if (*src != ' ') - dst += wctomb(dst, my_tolower[(unsigned char)*src]); - src++; - } - - if (memcmp(src, " ", 3) && memcmp(src, "Ufd", 3)) { - dst += wctomb(dst, L'.'); - for (i = 0; i < 3; i++) { - if (*src != ' ') - dst += wctomb(dst, my_tolower[(unsigned char)*src]); - src++; + static const wchar_t my_tolower[256] = + L"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" + L"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" + L" !\"#¤%&'()*+,-./0123456789:;<=>?" + L"éabcdefghijklmnopqrstuvwxyzäöåü_" + L"éabcdefghijklmnopqrstuvwxyzäöåü\377" + L"\200\201\202\203\204\205\206\207\210\211\212\213\214\215\216\217" + L"\220\221\222\223\224\225\226\227\230\231\232\233\234\235\236\237" + L"\240\241\242\243\244\245\246\247\250\251\252\253\254\255\256\257" + L"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" + L"\300\301\302\303\304\305\306\307\310\311\312\313\314\315\316\317" + L"\320\321\322\323\324\325\326\327\330\331\332\333\334\335\336\337" + L"\340\341\342\343\344\345\346\347\350\351\352\353\354\355\356\357" + L"\360\361\362\363\364\365\366\367\370\371\372\373\374\375\376\377"; + int i; + + wctomb(NULL, 0); + + for (i = 0; i < 8; i++) { + if (*src != ' ') + dst += wctomb(dst, my_tolower[(unsigned char)*src]); + src++; } - } - *dst = '\0'; + if (memcmp(src, " ", 3) && memcmp(src, "Ufd", 3)) { + dst += wctomb(dst, L'.'); + for (i = 0; i < 3; i++) { + if (*src != ' ') + dst += wctomb(dst, my_tolower[(unsigned char)*src]); + src++; + } + } + + *dst = '\0'; } void mangle_filename(char *dst, const char *src) { - static const wchar_t srcset[] = - L"0123456789_." - L"ÉABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÅÜÆØ" - L"éabcdefghijklmnopqrstuvwxyzäöåüæø"; - static const char dstset[] = - "0123456789_." - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^[\\" - "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^[\\"; - char *d; - const char *s; - wchar_t sc; - const wchar_t *scp; - char dc; - int n; - - /* Skip any path prefix */ - s = host_strip_path(src); - - memset(dst, ' ', 11); - dst[11] = '\0'; - - mbtowc(NULL, NULL, 0); /* Reset the shift state */ - - d = dst; - while (d < dst+11 && (n = mbtowc(&sc, s, (size_t)~0)) > 0) { - s += n; - - if ( (scp = wcschr(srcset, sc)) ) { - dc = dstset[scp - srcset]; - } else { - dc = '_'; + static const wchar_t srcset[] = + L"0123456789_." + L"ÉABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÅÜÆØ" + L"éabcdefghijklmnopqrstuvwxyzäöåüæø"; + static const char dstset[] = + "0123456789_." + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^[\\" + "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^[\\"; + char *d; + const char *s; + wchar_t sc; + const wchar_t *scp; + char dc; + int n; + + /* Skip any path prefix */ + s = host_strip_path(src); + + memset(dst, ' ', 11); + dst[11] = '\0'; + + mbtowc(NULL, NULL, 0); /* Reset the shift state */ + + d = dst; + while (d < dst + 11 && (n = mbtowc(&sc, s, (size_t) ~ 0)) > 0) { + s += n; + + if ((scp = wcschr(srcset, sc))) { + dc = dstset[scp - srcset]; + } else { + dc = '_'; + } + + if (dc == '.') + d = dst + 8; + else + *d++ = dc; } - - if ( dc == '.' ) - d = dst+8; - else - *d++ = dc; - } } - /* * Returns length for OK, 0 for failure */ int mangle_for_readdir(char *dst, const char *src) { - int n; - const char *s; - char *d; - char mangle_buf[12], unmangle_buf[64]; - - s = src; - - mangle_filename(mangle_buf, src); - unmangle_filename(unmangle_buf, mangle_buf); - - if (strcmp(unmangle_buf, src)) - return 0; /* Not round-trippable */ - - /* Compact to 8.3 notation */ - d = dst; - s = mangle_buf; - for (n = 0; n < 8; n++) { - if (*s != ' ') - *d++ = *s; - s++; - } - if (memcmp(s, " ", 3)) { - *d++ = '.'; - for (n = 0; n < 3; n++) { - if (*s != ' ') - *d++ = *s; - s++; + int n; + const char *s; + char *d; + char mangle_buf[12], unmangle_buf[64]; + + s = src; + + mangle_filename(mangle_buf, src); + unmangle_filename(unmangle_buf, mangle_buf); + + if (strcmp(unmangle_buf, src)) + return 0; /* Not round-trippable */ + + /* Compact to 8.3 notation */ + d = dst; + s = mangle_buf; + for (n = 0; n < 8; n++) { + if (*s != ' ') + *d++ = *s; + s++; + } + if (memcmp(s, " ", 3)) { + *d++ = '.'; + for (n = 0; n < 3; n++) { + if (*s != ' ') + *d++ = *s; + s++; + } } - } - *d = '\0'; + *d = '\0'; - return d - dst; + return d - dst; } /* @@ -144,22 +143,22 @@ unsigned int init_abcdata(struct abcdata *abc, const void *data, size_t len) size_t cc = 0; abc->data = data; - abc->len = len; + abc->len = len; abc->is_text = false; cc = 0; while (left--) { - uint8_t c = *p++; + uint8_t c = *p++; - if (c >= 0x80 || c == 0 || c == 3) { - /* Binary file */ - return (len + 252)/253; /* Just the data */ - } - cc += (c != '\r'); + if (c >= 0x80 || c == 0 || c == 3) { + /* Binary file */ + return (len + 252) / 253; /* Just the data */ + } + cc += (c != '\r'); } abc->is_text = true; - return (cc + 251)/252 + 1; /* Each block will need ETX + EOF block */ + return (cc + 251) / 252 + 1; /* Each block will need ETX + EOF block */ } /* @@ -167,7 +166,7 @@ unsigned int init_abcdata(struct abcdata *abc, const void *data, size_t len) * a binary file or a conventional text file in memory. * Return true if this is the final (EOF) block. */ -bool get_abc_block(void *block, struct abcdata *abc) +bool get_abc_block(void *block, struct abcdata * abc) { size_t l = abc->len; const uint8_t *p = abc->data; @@ -176,48 +175,48 @@ bool get_abc_block(void *block, struct abcdata *abc) bool done; if (!abc->is_text) { - /* It is a binary file */ + /* It is a binary file */ - ob = l < 253 ? l : 253; + ob = l < 253 ? l : 253; - memcpy(q, p, ob); - p += ob; - l -= ob; - done = !l; /* If no more data this is the last block */ + memcpy(q, p, ob); + p += ob; + l -= ob; + done = !l; /* If no more data this is the last block */ } else { - /* It is a text file */ - - ob = 0; - done = false; - - while (l && ob < 252) { - uint8_t c = *p++; - l--; - - /* Convert CR LF or LF -> CR */ - switch (c) { - case '\r': - break; - case '\n': - c = '\r'; - /* fall through */ - default: - q[ob++] = c; - break; - } - } - - if (!ob) { - /* This is apparently the EOF block */ - memset(q, 0, ob = 6); - done = true; - } - - q[ob++] = 0x03; /* ETX = end of block */ + /* It is a text file */ + + ob = 0; + done = false; + + while (l && ob < 252) { + uint8_t c = *p++; + l--; + + /* Convert CR LF or LF -> CR */ + switch (c) { + case '\r': + break; + case '\n': + c = '\r'; + /* fall through */ + default: + q[ob++] = c; + break; + } + } + + if (!ob) { + /* This is apparently the EOF block */ + memset(q, 0, ob = 6); + done = true; + } + + q[ob++] = 0x03; /* ETX = end of block */ } if (ob < 253) - memset(q+ob, 0, 253-ob); + memset(q + ob, 0, 253 - ob); abc->data = p; abc->len = l; @@ -1,258 +1,258 @@ const unsigned char abc_font[256][10] = { - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 0T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 1T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 2T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 3T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 4T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 5T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 6T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 7T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 8T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 9T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 10T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 11T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 12T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 13T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 14T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 15T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 16T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 17T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 18T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 19T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 20T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 21T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 22T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 23T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 24T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 25T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 26T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 27T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 28T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 29T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 30T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 31T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 32T */ - {0x00,0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00,0x00}, /* 33T */ - {0x00,0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00,0x00}, /* 34T */ - {0x00,0x50,0x50,0xf8,0x50,0xf8,0x50,0x50,0x00,0x00}, /* 35T */ - {0x00,0x00,0x00,0x88,0x70,0x50,0x70,0x88,0x00,0x00}, /* 36T */ - {0x00,0x48,0xa8,0x50,0x20,0x50,0xa8,0x90,0x00,0x00}, /* 37T */ - {0x00,0x40,0xa0,0xa0,0x40,0xa8,0x90,0x68,0x00,0x00}, /* 38T */ - {0x00,0x10,0x10,0x20,0x00,0x00,0x00,0x00,0x00,0x00}, /* 39T */ - {0x00,0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00,0x00}, /* 40T */ - {0x00,0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00,0x00}, /* 41T */ - {0x00,0x00,0x88,0x50,0xf8,0x50,0x88,0x00,0x00,0x00}, /* 42T */ - {0x00,0x00,0x20,0x20,0xf8,0x20,0x20,0x00,0x00,0x00}, /* 43T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x20,0x40,0x00}, /* 44T */ - {0x00,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0x00,0x00}, /* 45T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x70,0x20,0x00}, /* 46T */ - {0x00,0x08,0x08,0x10,0x20,0x40,0x80,0x80,0x00,0x00}, /* 47T */ - {0x00,0x70,0x88,0x88,0xa8,0x88,0x88,0x70,0x00,0x00}, /* 48T */ - {0x00,0x20,0x60,0xa0,0x20,0x20,0x20,0xf8,0x00,0x00}, /* 49T */ - {0x00,0x70,0x88,0x08,0x30,0x40,0x80,0xf8,0x00,0x00}, /* 50T */ - {0x00,0xf8,0x08,0x10,0x30,0x08,0x88,0x70,0x00,0x00}, /* 51T */ - {0x00,0x10,0x30,0x50,0x90,0xf8,0x10,0x10,0x00,0x00}, /* 52T */ - {0x00,0xf8,0x80,0xf0,0x08,0x08,0x88,0x70,0x00,0x00}, /* 53T */ - {0x00,0x30,0x40,0x80,0xf0,0x88,0x88,0x70,0x00,0x00}, /* 54T */ - {0x00,0xf8,0x08,0x10,0x10,0x20,0x40,0x40,0x00,0x00}, /* 55T */ - {0x00,0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00,0x00}, /* 56T */ - {0x00,0x70,0x88,0x88,0x78,0x08,0x10,0x60,0x00,0x00}, /* 57T */ - {0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00,0x00}, /* 58T */ - {0x00,0x00,0x30,0x30,0x00,0x00,0x30,0x10,0x20,0x00}, /* 59T */ - {0x00,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00,0x00}, /* 60T */ - {0x00,0x00,0x00,0xf8,0x00,0xf8,0x00,0x00,0x00,0x00}, /* 61T */ - {0x00,0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00,0x00}, /* 62T */ - {0x00,0x70,0x88,0x10,0x20,0x20,0x00,0x20,0x00,0x00}, /* 63T */ - {0x10,0x20,0x00,0xf8,0x80,0xf0,0x80,0xf8,0x00,0x00}, /* 64T */ - {0x00,0x20,0x50,0x88,0x88,0xf8,0x88,0x88,0x00,0x00}, /* 65T */ - {0x00,0xf0,0x48,0x48,0x70,0x48,0x48,0xf0,0x00,0x00}, /* 66T */ - {0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00,0x00}, /* 67T */ - {0x00,0xf0,0x48,0x48,0x48,0x48,0x48,0xf0,0x00,0x00}, /* 68T */ - {0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,0x00}, /* 69T */ - {0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0x80,0x00,0x00}, /* 70T */ - {0x00,0x70,0x88,0x80,0x80,0x98,0x88,0x70,0x00,0x00}, /* 71T */ - {0x00,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x00}, /* 72T */ - {0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00}, /* 73T */ - {0x00,0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x00}, /* 74T */ - {0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00,0x00}, /* 75T */ - {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x00}, /* 76T */ - {0x00,0x88,0x88,0xd8,0xa8,0x88,0x88,0x88,0x00,0x00}, /* 77T */ - {0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00,0x00}, /* 78T */ - {0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 79T */ - {0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00,0x00}, /* 80T */ - {0x00,0x70,0x88,0x88,0x88,0x88,0xa8,0x70,0x08,0x00}, /* 81T */ - {0x00,0xf0,0x88,0x88,0xf0,0xa0,0x90,0x88,0x00,0x00}, /* 82T */ - {0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00,0x00}, /* 83T */ - {0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00}, /* 84T */ - {0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 85T */ - {0x00,0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x00,0x00}, /* 86T */ - {0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00}, /* 87T */ - {0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x00}, /* 88T */ - {0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00,0x00}, /* 89T */ - {0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00}, /* 90T */ - {0x50,0x00,0x70,0x88,0x88,0xf8,0x88,0x88,0x00,0x00}, /* 91T */ - {0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 92T */ - {0x20,0x50,0x70,0x88,0x88,0xf8,0x88,0x88,0x00,0x00}, /* 93T */ - {0x50,0x00,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 94T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00}, /* 95T */ - {0x10,0x20,0x00,0x70,0x88,0xf8,0x80,0x70,0x00,0x00}, /* 96T */ - {0x00,0x00,0x00,0x70,0x08,0x78,0x88,0x78,0x00,0x00}, /* 97T */ - {0x00,0x80,0x80,0xf0,0x88,0x88,0x88,0xf0,0x00,0x00}, /* 98T */ - {0x00,0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00,0x00}, /* 99T */ - {0x00,0x08,0x08,0x78,0x88,0x88,0x88,0x78,0x00,0x00}, /* 100T */ - {0x00,0x00,0x00,0x70,0x88,0xf8,0x80,0x70,0x00,0x00}, /* 101T */ - {0x00,0x30,0x48,0x40,0xf0,0x40,0x40,0x40,0x00,0x00}, /* 102T */ - {0x00,0x00,0x00,0x78,0x88,0x88,0x78,0x08,0x88,0x70}, /* 103T */ - {0x00,0x80,0x80,0xb0,0xc8,0x88,0x88,0x88,0x00,0x00}, /* 104T */ - {0x00,0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00,0x00}, /* 105T */ - {0x00,0x08,0x00,0x18,0x08,0x08,0x08,0x48,0x48,0x30}, /* 106T */ - {0x00,0x80,0x80,0x88,0x90,0xe0,0x90,0x88,0x00,0x00}, /* 107T */ - {0x00,0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00}, /* 108T */ - {0x00,0x00,0x00,0xd0,0xa8,0xa8,0xa8,0x88,0x00,0x00}, /* 109T */ - {0x00,0x00,0x00,0xb0,0xc8,0x88,0x88,0x88,0x00,0x00}, /* 110T */ - {0x00,0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00,0x00}, /* 111T */ - {0x00,0x00,0x00,0xf0,0x88,0x88,0x88,0xf0,0x80,0x80}, /* 112T */ - {0x00,0x00,0x00,0x78,0x88,0x88,0x88,0x78,0x08,0x08}, /* 113T */ - {0x00,0x00,0x00,0xb0,0xc8,0x80,0x80,0x80,0x00,0x00}, /* 114T */ - {0x00,0x00,0x00,0x70,0x80,0x70,0x08,0xf0,0x00,0x00}, /* 115T */ - {0x00,0x40,0x40,0xf0,0x40,0x40,0x48,0x30,0x00,0x00}, /* 116T */ - {0x00,0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00,0x00}, /* 117T */ - {0x00,0x00,0x00,0x88,0x88,0x50,0x50,0x20,0x00,0x00}, /* 118T */ - {0x00,0x00,0x00,0x88,0x88,0xa8,0xa8,0x50,0x00,0x00}, /* 119T */ - {0x00,0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00,0x00}, /* 120T */ - {0x00,0x00,0x00,0x88,0x88,0x98,0x68,0x08,0x88,0x70}, /* 121T */ - {0x00,0x00,0x00,0xf8,0x10,0x20,0x40,0xf8,0x00,0x00}, /* 122T */ - {0x00,0x50,0x00,0x70,0x08,0x78,0x88,0x78,0x00,0x00}, /* 123T */ - {0x00,0x50,0x00,0x70,0x88,0x88,0x88,0x70,0x00,0x00}, /* 124T */ - {0x20,0x50,0x20,0x70,0x08,0x78,0x88,0x78,0x00,0x00}, /* 125T */ - {0x00,0x50,0x00,0x88,0x88,0x88,0x98,0x68,0x00,0x00}, /* 126T */ - {0x00,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0xf8,0x00,0x00}, /* 127T */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 0G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 1G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 2G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 3G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 4G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 5G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 6G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 7G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 8G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 9G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 10G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 11G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 12G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 13G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 14G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 15G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 16G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 17G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 18G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 19G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 20G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 21G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 22G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 23G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 24G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 25G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 26G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 27G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 28G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 29G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 30G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 31G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 32G */ - {0xe0,0xe0,0xe0,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 33G */ - {0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 34G */ - {0xfc,0xfc,0xfc,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, /* 35G */ - {0x00,0x00,0x00,0xe0,0xe0,0xe0,0xe0,0x00,0x00,0x00}, /* 36G */ - {0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x00,0x00,0x00}, /* 37G */ - {0x1c,0x1c,0x1c,0xe0,0xe0,0xe0,0xe0,0x00,0x00,0x00}, /* 38G */ - {0xfc,0xfc,0xfc,0xe0,0xe0,0xe0,0xe0,0x00,0x00,0x00}, /* 39G */ - {0x00,0x00,0x00,0x1c,0x1c,0x1c,0x1c,0x00,0x00,0x00}, /* 40G */ - {0xe0,0xe0,0xe0,0x1c,0x1c,0x1c,0x1c,0x00,0x00,0x00}, /* 41G */ - {0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x00,0x00,0x00}, /* 42G */ - {0xfc,0xfc,0xfc,0x1c,0x1c,0x1c,0x1c,0x00,0x00,0x00}, /* 43G */ - {0x00,0x00,0x00,0xfc,0xfc,0xfc,0xfc,0x00,0x00,0x00}, /* 44G */ - {0xe0,0xe0,0xe0,0xfc,0xfc,0xfc,0xfc,0x00,0x00,0x00}, /* 45G */ - {0x1c,0x1c,0x1c,0xfc,0xfc,0xfc,0xfc,0x00,0x00,0x00}, /* 46G */ - {0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0x00,0x00,0x00}, /* 47G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xe0,0xe0}, /* 48G */ - {0xe0,0xe0,0xe0,0x00,0x00,0x00,0x00,0xe0,0xe0,0xe0}, /* 49G */ - {0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0xe0,0xe0,0xe0}, /* 50G */ - {0xfc,0xfc,0xfc,0x00,0x00,0x00,0x00,0xe0,0xe0,0xe0}, /* 51G */ - {0x00,0x00,0x00,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0}, /* 52G */ - {0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0}, /* 53G */ - {0x1c,0x1c,0x1c,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0}, /* 54G */ - {0xfc,0xfc,0xfc,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0}, /* 55G */ - {0x00,0x00,0x00,0x1c,0x1c,0x1c,0x1c,0xe0,0xe0,0xe0}, /* 56G */ - {0xe0,0xe0,0xe0,0x1c,0x1c,0x1c,0x1c,0xe0,0xe0,0xe0}, /* 57G */ - {0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0xe0,0xe0,0xe0}, /* 58G */ - {0xfc,0xfc,0xfc,0x1c,0x1c,0x1c,0x1c,0xe0,0xe0,0xe0}, /* 59G */ - {0x00,0x00,0x00,0xfc,0xfc,0xfc,0xfc,0xe0,0xe0,0xe0}, /* 60G */ - {0xe0,0xe0,0xe0,0xfc,0xfc,0xfc,0xfc,0xe0,0xe0,0xe0}, /* 61G */ - {0x1c,0x1c,0x1c,0xfc,0xfc,0xfc,0xfc,0xe0,0xe0,0xe0}, /* 62G */ - {0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xe0,0xe0,0xe0}, /* 63G */ - {0x10,0x20,0x00,0xf8,0x80,0xf0,0x80,0xf8,0x00,0x00}, /* 64G */ - {0x00,0x20,0x50,0x88,0x88,0xf8,0x88,0x88,0x00,0x00}, /* 65G */ - {0x00,0xf0,0x48,0x48,0x70,0x48,0x48,0xf0,0x00,0x00}, /* 66G */ - {0x00,0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00,0x00}, /* 67G */ - {0x00,0xf0,0x48,0x48,0x48,0x48,0x48,0xf0,0x00,0x00}, /* 68G */ - {0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0xf8,0x00,0x00}, /* 69G */ - {0x00,0xf8,0x80,0x80,0xf0,0x80,0x80,0x80,0x00,0x00}, /* 70G */ - {0x00,0x70,0x88,0x80,0x80,0x98,0x88,0x70,0x00,0x00}, /* 71G */ - {0x00,0x88,0x88,0x88,0xf8,0x88,0x88,0x88,0x00,0x00}, /* 72G */ - {0x00,0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00,0x00}, /* 73G */ - {0x00,0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00,0x00}, /* 74G */ - {0x00,0x88,0x90,0xa0,0xc0,0xa0,0x90,0x88,0x00,0x00}, /* 75G */ - {0x00,0x80,0x80,0x80,0x80,0x80,0x80,0xf8,0x00,0x00}, /* 76G */ - {0x00,0x88,0x88,0xd8,0xa8,0x88,0x88,0x88,0x00,0x00}, /* 77G */ - {0x00,0x88,0x88,0xc8,0xa8,0x98,0x88,0x88,0x00,0x00}, /* 78G */ - {0x00,0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 79G */ - {0x00,0xf0,0x88,0x88,0xf0,0x80,0x80,0x80,0x00,0x00}, /* 80G */ - {0x00,0x70,0x88,0x88,0x88,0x88,0xa8,0x70,0x08,0x00}, /* 81G */ - {0x00,0xf0,0x88,0x88,0xf0,0xa0,0x90,0x88,0x00,0x00}, /* 82G */ - {0x00,0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00,0x00}, /* 83G */ - {0x00,0xf8,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00}, /* 84G */ - {0x00,0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 85G */ - {0x00,0x88,0x88,0x88,0x50,0x50,0x50,0x20,0x00,0x00}, /* 86G */ - {0x00,0x88,0x88,0x88,0xa8,0xa8,0xd8,0x88,0x00,0x00}, /* 87G */ - {0x00,0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00,0x00}, /* 88G */ - {0x00,0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00,0x00}, /* 89G */ - {0x00,0xf8,0x08,0x10,0x20,0x40,0x80,0xf8,0x00,0x00}, /* 90G */ - {0x50,0x00,0x70,0x88,0x88,0xf8,0x88,0x88,0x00,0x00}, /* 91G */ - {0x50,0x00,0x70,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 92G */ - {0x20,0x50,0x70,0x88,0x88,0xf8,0x88,0x88,0x00,0x00}, /* 93G */ - {0x50,0x00,0x88,0x88,0x88,0x88,0x88,0x70,0x00,0x00}, /* 94G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf8,0x00}, /* 95G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1c,0x1c,0x1c}, /* 96G */ - {0xe0,0xe0,0xe0,0x00,0x00,0x00,0x00,0x1c,0x1c,0x1c}, /* 97G */ - {0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0x1c,0x1c,0x1c}, /* 98G */ - {0xfc,0xfc,0xfc,0x00,0x00,0x00,0x00,0x1c,0x1c,0x1c}, /* 99G */ - {0x00,0x00,0x00,0xe0,0xe0,0xe0,0xe0,0x1c,0x1c,0x1c}, /* 100G */ - {0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0x1c,0x1c,0x1c}, /* 101G */ - {0x1c,0x1c,0x1c,0xe0,0xe0,0xe0,0xe0,0x1c,0x1c,0x1c}, /* 102G */ - {0xfc,0xfc,0xfc,0xe0,0xe0,0xe0,0xe0,0x1c,0x1c,0x1c}, /* 103G */ - {0x00,0x00,0x00,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c}, /* 104G */ - {0xe0,0xe0,0xe0,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c}, /* 105G */ - {0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c}, /* 106G */ - {0xfc,0xfc,0xfc,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c}, /* 107G */ - {0x00,0x00,0x00,0xfc,0xfc,0xfc,0xfc,0x1c,0x1c,0x1c}, /* 108G */ - {0xe0,0xe0,0xe0,0xfc,0xfc,0xfc,0xfc,0x1c,0x1c,0x1c}, /* 109G */ - {0x1c,0x1c,0x1c,0xfc,0xfc,0xfc,0xfc,0x1c,0x1c,0x1c}, /* 110G */ - {0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0x1c,0x1c,0x1c}, /* 111G */ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xfc,0xfc,0xfc}, /* 112G */ - {0xe0,0xe0,0xe0,0x00,0x00,0x00,0x00,0xfc,0xfc,0xfc}, /* 113G */ - {0x1c,0x1c,0x1c,0x00,0x00,0x00,0x00,0xfc,0xfc,0xfc}, /* 114G */ - {0xfc,0xfc,0xfc,0x00,0x00,0x00,0x00,0xfc,0xfc,0xfc}, /* 115G */ - {0x00,0x00,0x00,0xe0,0xe0,0xe0,0xe0,0xfc,0xfc,0xfc}, /* 116G */ - {0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xe0,0xfc,0xfc,0xfc}, /* 117G */ - {0x1c,0x1c,0x1c,0xe0,0xe0,0xe0,0xe0,0xfc,0xfc,0xfc}, /* 118G */ - {0xfc,0xfc,0xfc,0xe0,0xe0,0xe0,0xe0,0xfc,0xfc,0xfc}, /* 119G */ - {0x00,0x00,0x00,0x1c,0x1c,0x1c,0x1c,0xfc,0xfc,0xfc}, /* 120G */ - {0xe0,0xe0,0xe0,0x1c,0x1c,0x1c,0x1c,0xfc,0xfc,0xfc}, /* 121G */ - {0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0xfc,0xfc,0xfc}, /* 122G */ - {0xfc,0xfc,0xfc,0x1c,0x1c,0x1c,0x1c,0xfc,0xfc,0xfc}, /* 123G */ - {0x00,0x00,0x00,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc}, /* 124G */ - {0xe0,0xe0,0xe0,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc}, /* 125G */ - {0x1c,0x1c,0x1c,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc}, /* 126G */ - {0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc,0xfc}, /* 127G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 1T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 4T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 5T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 6T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 7T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 8T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 9T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 10T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 11T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 12T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 13T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 14T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 15T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 16T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 17T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 18T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 19T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 20T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 21T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 22T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 23T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 24T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 25T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 26T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 27T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 28T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 29T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 30T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 31T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 32T */ + {0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00}, /* 33T */ + {0x00, 0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 34T */ + {0x00, 0x50, 0x50, 0xf8, 0x50, 0xf8, 0x50, 0x50, 0x00, 0x00}, /* 35T */ + {0x00, 0x00, 0x00, 0x88, 0x70, 0x50, 0x70, 0x88, 0x00, 0x00}, /* 36T */ + {0x00, 0x48, 0xa8, 0x50, 0x20, 0x50, 0xa8, 0x90, 0x00, 0x00}, /* 37T */ + {0x00, 0x40, 0xa0, 0xa0, 0x40, 0xa8, 0x90, 0x68, 0x00, 0x00}, /* 38T */ + {0x00, 0x10, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 39T */ + {0x00, 0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00, 0x00}, /* 40T */ + {0x00, 0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00, 0x00}, /* 41T */ + {0x00, 0x00, 0x88, 0x50, 0xf8, 0x50, 0x88, 0x00, 0x00, 0x00}, /* 42T */ + {0x00, 0x00, 0x20, 0x20, 0xf8, 0x20, 0x20, 0x00, 0x00, 0x00}, /* 43T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x20, 0x40, 0x00}, /* 44T */ + {0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 45T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x20, 0x00}, /* 46T */ + {0x00, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x80, 0x00, 0x00}, /* 47T */ + {0x00, 0x70, 0x88, 0x88, 0xa8, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 48T */ + {0x00, 0x20, 0x60, 0xa0, 0x20, 0x20, 0x20, 0xf8, 0x00, 0x00}, /* 49T */ + {0x00, 0x70, 0x88, 0x08, 0x30, 0x40, 0x80, 0xf8, 0x00, 0x00}, /* 50T */ + {0x00, 0xf8, 0x08, 0x10, 0x30, 0x08, 0x88, 0x70, 0x00, 0x00}, /* 51T */ + {0x00, 0x10, 0x30, 0x50, 0x90, 0xf8, 0x10, 0x10, 0x00, 0x00}, /* 52T */ + {0x00, 0xf8, 0x80, 0xf0, 0x08, 0x08, 0x88, 0x70, 0x00, 0x00}, /* 53T */ + {0x00, 0x30, 0x40, 0x80, 0xf0, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 54T */ + {0x00, 0xf8, 0x08, 0x10, 0x10, 0x20, 0x40, 0x40, 0x00, 0x00}, /* 55T */ + {0x00, 0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 56T */ + {0x00, 0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0x60, 0x00, 0x00}, /* 57T */ + {0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x30, 0x00, 0x00}, /* 58T */ + {0x00, 0x00, 0x30, 0x30, 0x00, 0x00, 0x30, 0x10, 0x20, 0x00}, /* 59T */ + {0x00, 0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00}, /* 60T */ + {0x00, 0x00, 0x00, 0xf8, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00}, /* 61T */ + {0x00, 0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x00, 0x00}, /* 62T */ + {0x00, 0x70, 0x88, 0x10, 0x20, 0x20, 0x00, 0x20, 0x00, 0x00}, /* 63T */ + {0x10, 0x20, 0x00, 0xf8, 0x80, 0xf0, 0x80, 0xf8, 0x00, 0x00}, /* 64T */ + {0x00, 0x20, 0x50, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x00}, /* 65T */ + {0x00, 0xf0, 0x48, 0x48, 0x70, 0x48, 0x48, 0xf0, 0x00, 0x00}, /* 66T */ + {0x00, 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, 0x00}, /* 67T */ + {0x00, 0xf0, 0x48, 0x48, 0x48, 0x48, 0x48, 0xf0, 0x00, 0x00}, /* 68T */ + {0x00, 0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0xf8, 0x00, 0x00}, /* 69T */ + {0x00, 0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0x00, 0x00}, /* 70T */ + {0x00, 0x70, 0x88, 0x80, 0x80, 0x98, 0x88, 0x70, 0x00, 0x00}, /* 71T */ + {0x00, 0x88, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x88, 0x00, 0x00}, /* 72T */ + {0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00}, /* 73T */ + {0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, 0x00}, /* 74T */ + {0x00, 0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x00, 0x00}, /* 75T */ + {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0x00, 0x00}, /* 76T */ + {0x00, 0x88, 0x88, 0xd8, 0xa8, 0x88, 0x88, 0x88, 0x00, 0x00}, /* 77T */ + {0x00, 0x88, 0x88, 0xc8, 0xa8, 0x98, 0x88, 0x88, 0x00, 0x00}, /* 78T */ + {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 79T */ + {0x00, 0xf0, 0x88, 0x88, 0xf0, 0x80, 0x80, 0x80, 0x00, 0x00}, /* 80T */ + {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0xa8, 0x70, 0x08, 0x00}, /* 81T */ + {0x00, 0xf0, 0x88, 0x88, 0xf0, 0xa0, 0x90, 0x88, 0x00, 0x00}, /* 82T */ + {0x00, 0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, 0x00}, /* 83T */ + {0x00, 0xf8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00}, /* 84T */ + {0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 85T */ + {0x00, 0x88, 0x88, 0x88, 0x50, 0x50, 0x50, 0x20, 0x00, 0x00}, /* 86T */ + {0x00, 0x88, 0x88, 0x88, 0xa8, 0xa8, 0xd8, 0x88, 0x00, 0x00}, /* 87T */ + {0x00, 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, 0x00}, /* 88T */ + {0x00, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00}, /* 89T */ + {0x00, 0xf8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xf8, 0x00, 0x00}, /* 90T */ + {0x50, 0x00, 0x70, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x00}, /* 91T */ + {0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 92T */ + {0x20, 0x50, 0x70, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x00}, /* 93T */ + {0x50, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 94T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00}, /* 95T */ + {0x10, 0x20, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x70, 0x00, 0x00}, /* 96T */ + {0x00, 0x00, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00}, /* 97T */ + {0x00, 0x80, 0x80, 0xf0, 0x88, 0x88, 0x88, 0xf0, 0x00, 0x00}, /* 98T */ + {0x00, 0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00, 0x00}, /* 99T */ + {0x00, 0x08, 0x08, 0x78, 0x88, 0x88, 0x88, 0x78, 0x00, 0x00}, /* 100T */ + {0x00, 0x00, 0x00, 0x70, 0x88, 0xf8, 0x80, 0x70, 0x00, 0x00}, /* 101T */ + {0x00, 0x30, 0x48, 0x40, 0xf0, 0x40, 0x40, 0x40, 0x00, 0x00}, /* 102T */ + {0x00, 0x00, 0x00, 0x78, 0x88, 0x88, 0x78, 0x08, 0x88, 0x70}, /* 103T */ + {0x00, 0x80, 0x80, 0xb0, 0xc8, 0x88, 0x88, 0x88, 0x00, 0x00}, /* 104T */ + {0x00, 0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00}, /* 105T */ + {0x00, 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x48, 0x48, 0x30}, /* 106T */ + {0x00, 0x80, 0x80, 0x88, 0x90, 0xe0, 0x90, 0x88, 0x00, 0x00}, /* 107T */ + {0x00, 0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00}, /* 108T */ + {0x00, 0x00, 0x00, 0xd0, 0xa8, 0xa8, 0xa8, 0x88, 0x00, 0x00}, /* 109T */ + {0x00, 0x00, 0x00, 0xb0, 0xc8, 0x88, 0x88, 0x88, 0x00, 0x00}, /* 110T */ + {0x00, 0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 111T */ + {0x00, 0x00, 0x00, 0xf0, 0x88, 0x88, 0x88, 0xf0, 0x80, 0x80}, /* 112T */ + {0x00, 0x00, 0x00, 0x78, 0x88, 0x88, 0x88, 0x78, 0x08, 0x08}, /* 113T */ + {0x00, 0x00, 0x00, 0xb0, 0xc8, 0x80, 0x80, 0x80, 0x00, 0x00}, /* 114T */ + {0x00, 0x00, 0x00, 0x70, 0x80, 0x70, 0x08, 0xf0, 0x00, 0x00}, /* 115T */ + {0x00, 0x40, 0x40, 0xf0, 0x40, 0x40, 0x48, 0x30, 0x00, 0x00}, /* 116T */ + {0x00, 0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, 0x00}, /* 117T */ + {0x00, 0x00, 0x00, 0x88, 0x88, 0x50, 0x50, 0x20, 0x00, 0x00}, /* 118T */ + {0x00, 0x00, 0x00, 0x88, 0x88, 0xa8, 0xa8, 0x50, 0x00, 0x00}, /* 119T */ + {0x00, 0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00, 0x00}, /* 120T */ + {0x00, 0x00, 0x00, 0x88, 0x88, 0x98, 0x68, 0x08, 0x88, 0x70}, /* 121T */ + {0x00, 0x00, 0x00, 0xf8, 0x10, 0x20, 0x40, 0xf8, 0x00, 0x00}, /* 122T */ + {0x00, 0x50, 0x00, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00}, /* 123T */ + {0x00, 0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 124T */ + {0x20, 0x50, 0x20, 0x70, 0x08, 0x78, 0x88, 0x78, 0x00, 0x00}, /* 125T */ + {0x00, 0x50, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00, 0x00}, /* 126T */ + {0x00, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0x00, 0x00}, /* 127T */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 0G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 1G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 2G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 3G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 4G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 5G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 6G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 7G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 8G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 9G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 10G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 11G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 12G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 13G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 14G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 15G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 16G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 17G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 18G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 19G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 20G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 21G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 22G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 23G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 24G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 25G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 26G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 27G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 28G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 29G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 30G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 31G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 32G */ + {0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 33G */ + {0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 34G */ + {0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 35G */ + {0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00}, /* 36G */ + {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00}, /* 37G */ + {0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00}, /* 38G */ + {0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00}, /* 39G */ + {0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00}, /* 40G */ + {0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00}, /* 41G */ + {0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00}, /* 42G */ + {0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00}, /* 43G */ + {0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00}, /* 44G */ + {0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00}, /* 45G */ + {0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00}, /* 46G */ + {0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00}, /* 47G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0}, /* 48G */ + {0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0}, /* 49G */ + {0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0}, /* 50G */ + {0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0}, /* 51G */ + {0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0}, /* 52G */ + {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0}, /* 53G */ + {0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0}, /* 54G */ + {0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0}, /* 55G */ + {0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0}, /* 56G */ + {0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0}, /* 57G */ + {0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0}, /* 58G */ + {0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0}, /* 59G */ + {0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0}, /* 60G */ + {0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0}, /* 61G */ + {0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0}, /* 62G */ + {0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0}, /* 63G */ + {0x10, 0x20, 0x00, 0xf8, 0x80, 0xf0, 0x80, 0xf8, 0x00, 0x00}, /* 64G */ + {0x00, 0x20, 0x50, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x00}, /* 65G */ + {0x00, 0xf0, 0x48, 0x48, 0x70, 0x48, 0x48, 0xf0, 0x00, 0x00}, /* 66G */ + {0x00, 0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00, 0x00}, /* 67G */ + {0x00, 0xf0, 0x48, 0x48, 0x48, 0x48, 0x48, 0xf0, 0x00, 0x00}, /* 68G */ + {0x00, 0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0xf8, 0x00, 0x00}, /* 69G */ + {0x00, 0xf8, 0x80, 0x80, 0xf0, 0x80, 0x80, 0x80, 0x00, 0x00}, /* 70G */ + {0x00, 0x70, 0x88, 0x80, 0x80, 0x98, 0x88, 0x70, 0x00, 0x00}, /* 71G */ + {0x00, 0x88, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x88, 0x00, 0x00}, /* 72G */ + {0x00, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00, 0x00}, /* 73G */ + {0x00, 0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00, 0x00}, /* 74G */ + {0x00, 0x88, 0x90, 0xa0, 0xc0, 0xa0, 0x90, 0x88, 0x00, 0x00}, /* 75G */ + {0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf8, 0x00, 0x00}, /* 76G */ + {0x00, 0x88, 0x88, 0xd8, 0xa8, 0x88, 0x88, 0x88, 0x00, 0x00}, /* 77G */ + {0x00, 0x88, 0x88, 0xc8, 0xa8, 0x98, 0x88, 0x88, 0x00, 0x00}, /* 78G */ + {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 79G */ + {0x00, 0xf0, 0x88, 0x88, 0xf0, 0x80, 0x80, 0x80, 0x00, 0x00}, /* 80G */ + {0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0xa8, 0x70, 0x08, 0x00}, /* 81G */ + {0x00, 0xf0, 0x88, 0x88, 0xf0, 0xa0, 0x90, 0x88, 0x00, 0x00}, /* 82G */ + {0x00, 0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00, 0x00}, /* 83G */ + {0x00, 0xf8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00}, /* 84G */ + {0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 85G */ + {0x00, 0x88, 0x88, 0x88, 0x50, 0x50, 0x50, 0x20, 0x00, 0x00}, /* 86G */ + {0x00, 0x88, 0x88, 0x88, 0xa8, 0xa8, 0xd8, 0x88, 0x00, 0x00}, /* 87G */ + {0x00, 0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00, 0x00}, /* 88G */ + {0x00, 0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20, 0x00, 0x00}, /* 89G */ + {0x00, 0xf8, 0x08, 0x10, 0x20, 0x40, 0x80, 0xf8, 0x00, 0x00}, /* 90G */ + {0x50, 0x00, 0x70, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x00}, /* 91G */ + {0x50, 0x00, 0x70, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 92G */ + {0x20, 0x50, 0x70, 0x88, 0x88, 0xf8, 0x88, 0x88, 0x00, 0x00}, /* 93G */ + {0x50, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00, 0x00}, /* 94G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00}, /* 95G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c}, /* 96G */ + {0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c}, /* 97G */ + {0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c}, /* 98G */ + {0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c}, /* 99G */ + {0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c}, /* 100G */ + {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c}, /* 101G */ + {0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c}, /* 102G */ + {0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c}, /* 103G */ + {0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, /* 104G */ + {0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, /* 105G */ + {0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, /* 106G */ + {0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c}, /* 107G */ + {0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c}, /* 108G */ + {0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c}, /* 109G */ + {0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c}, /* 110G */ + {0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c}, /* 111G */ + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc}, /* 112G */ + {0xe0, 0xe0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc}, /* 113G */ + {0x1c, 0x1c, 0x1c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc}, /* 114G */ + {0xfc, 0xfc, 0xfc, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc}, /* 115G */ + {0x00, 0x00, 0x00, 0xe0, 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc}, /* 116G */ + {0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc}, /* 117G */ + {0x1c, 0x1c, 0x1c, 0xe0, 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc}, /* 118G */ + {0xfc, 0xfc, 0xfc, 0xe0, 0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc}, /* 119G */ + {0x00, 0x00, 0x00, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc}, /* 120G */ + {0xe0, 0xe0, 0xe0, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc}, /* 121G */ + {0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc}, /* 122G */ + {0xfc, 0xfc, 0xfc, 0x1c, 0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc}, /* 123G */ + {0x00, 0x00, 0x00, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc}, /* 124G */ + {0xe0, 0xe0, 0xe0, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc}, /* 125G */ + {0x1c, 0x1c, 0x1c, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc}, /* 126G */ + {0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc}, /* 127G */ }; @@ -24,25 +24,23 @@ bool faketype; static int keyb_intack_fake(struct z80_irq *irq); static struct z80_irq *keyb_irq; -static struct z80_irq keyb_irq_80 = \ - IRQ(IRQ80_PIOA, NULL, NULL, NULL); -static struct z80_irq keyb_irq_fake = \ - IRQ(IRQ80_PIOA, keyb_intack_fake, NULL, NULL); -static struct z80_irq keyb_irq_800 = \ - IRQ(IRQ800_DARTB, NULL, NULL, NULL); +static struct z80_irq keyb_irq_80 = IRQ(IRQ80_PIOA, NULL, NULL, NULL); +static struct z80_irq keyb_irq_fake = +IRQ(IRQ80_PIOA, keyb_intack_fake, NULL, NULL); +static struct z80_irq keyb_irq_800 = IRQ(IRQ800_DARTB, NULL, NULL, NULL); static inline uint8_t abc800_mangle_port(uint8_t port) { - if ((port & 0xe0) == 0x00) - return port & 0xe7; - else if ((port & 0xf0) == 0x20) - return port & 0xf3; - else if ((port & 0xf8) == 0x28) - return port & 0xf9; - else if ((port & 0xc0) == 0x40) - return port & 0xe3; - else - return port; + if ((port & 0xe0) == 0x00) + return port & 0xe7; + else if ((port & 0xf0) == 0x20) + return port & 0xf3; + else if ((port & 0xf8) == 0x28) + return port & 0xf9; + else if ((port & 0xc0) == 0x40) + return port & 0xe3; + else + return port; } /* @@ -52,74 +50,74 @@ static inline uint8_t abc800_mangle_port(uint8_t port) */ static void abcbus_out(uint8_t port, uint8_t value) { - if (port == 1) { - abcbus_select = value & 0x3f; - return; - } - - switch (abcbus_select) { - case 36: /* HDx: */ - case 44: /* MFx: */ - case 45: /* MOx: */ - case 46: /* SFx: */ - disk_out(abcbus_select, port, value); - break; - - case 60: /* PRx: */ - printer_out(abcbus_select, port, value); - break; - - default: - break; - } + if (port == 1) { + abcbus_select = value & 0x3f; + return; + } + + switch (abcbus_select) { + case 36: /* HDx: */ + case 44: /* MFx: */ + case 45: /* MOx: */ + case 46: /* SFx: */ + disk_out(abcbus_select, port, value); + break; + + case 60: /* PRx: */ + printer_out(abcbus_select, port, value); + break; + + default: + break; + } } static void abc80_out(uint8_t port, uint8_t value) { - port &= 0x17; /* Only these bits decoded in ABC80 */ - - switch (port) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - abcbus_out(port, value); - break; - - case 6: /* sound */ - if (value == 131) { - putchar(7); /* beep */ - fflush(stdout); - } - break; + port &= 0x17; /* Only these bits decoded in ABC80 */ - case 7: /* Mikrodatorn 64K page switch port */ - abc80_mem_setmap(value & 3); - break; + switch (port) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + abcbus_out(port, value); + break; + + case 6: /* sound */ + if (value == 131) { + putchar(7); /* beep */ + fflush(stdout); + } + break; + + case 7: /* Mikrodatorn 64K page switch port */ + abc80_mem_setmap(value & 3); + break; + + case (57 & 0x17): /* Keyboard control port */ + if (!(value & 1)) { + keyb_irq->vector = value; + } + break; + + case (58 & 0x17): + case (59 & 0x17): + abc80_piob_out(port, value); + break; - case (57 & 0x17): /* Keyboard control port */ - if (!(value & 1)) { - keyb_irq->vector = value; + default: + break; } - break; - - case (58 & 0x17): - case (59 & 0x17): - abc80_piob_out(port, value); - break; - - default: - break; - } } static bool vsync; void abc802_vsync(void) { - vsync_screen(); - vsync = true; + vsync_screen(); + vsync = true; } static uint8_t dart_keyb_ctl[8]; @@ -127,171 +125,170 @@ static bool dart_keyb_vsync; static void dart_keyb_out(uint8_t port, uint8_t value) { - /* Keyboard DART control */ - uint8_t reg; + /* Keyboard DART control */ + uint8_t reg; - if ((port & 1) == 0) { - return; /* Data out - ignore for now */ - } + if ((port & 1) == 0) { + return; /* Data out - ignore for now */ + } - reg = dart_keyb_ctl[0] & 7; - dart_keyb_ctl[0] &= ~7; /* Restore register 0 */ + reg = dart_keyb_ctl[0] & 7; + dart_keyb_ctl[0] &= ~7; /* Restore register 0 */ - dart_keyb_ctl[reg] = value; - switch (reg) { - case 0: - switch ((value >> 3) & 7) { - case 2: - dart_keyb_vsync = vsync; - vsync = false; - break; - case 3: - memset(dart_keyb_ctl, 0, sizeof dart_keyb_ctl); - break; - case 4: - break; /* Allow IRQ to be enabled */ + dart_keyb_ctl[reg] = value; + switch (reg) { + case 0: + switch ((value >> 3) & 7) { + case 2: + dart_keyb_vsync = vsync; + vsync = false; + break; + case 3: + memset(dart_keyb_ctl, 0, sizeof dart_keyb_ctl); + break; + case 4: + break; /* Allow IRQ to be enabled */ + default: + break; + } + break; + case 5: + setmode40(! !(value & 2)); + abc802_set_mem(! !(value & 0x80)); + break; default: - break; + break; + } + + if ((dart_keyb_ctl[1] & 0x18) == 0) { + keyb_irq->vector = -1; + } else if (dart_keyb_ctl[1] & 0x04) { + /* Status affects vector */ + keyb_irq->vector = (dart_keyb_ctl[2] & ~0x0f) | 0x04; + } else { + /* Fixed vector */ + keyb_irq->vector = (dart_keyb_ctl[2] & ~0x01); } - break; - case 5: - setmode40(!!(value & 2)); - abc802_set_mem(!!(value & 0x80)); - break; - default: - break; - } - - if ((dart_keyb_ctl[1] & 0x18) == 0) { - keyb_irq->vector = -1; - } else if (dart_keyb_ctl[1] & 0x04) { - /* Status affects vector */ - keyb_irq->vector = (dart_keyb_ctl[2] & ~0x0f) | 0x04; - } else { - /* Fixed vector */ - keyb_irq->vector = (dart_keyb_ctl[2] & ~0x01); - } } /* Get the keyboard data, clearing the KEYB_NEW flag */ static unsigned int get_key(void) { - unsigned int rv, kbd; + unsigned int rv, kbd; - rv = kbd = keyb_data; - cmpxchg(&keyb_data, &kbd, kbd & ~KEYB_NEW); + rv = kbd = keyb_data; + cmpxchg(&keyb_data, &kbd, kbd & ~KEYB_NEW); - return rv; + return rv; } static int keyb_intack_fake(struct z80_irq *irq) { - unsigned int data = get_key(); + unsigned int data = get_key(); - keyb_fakedata = (data & 0x7f) | ((data & KEYB_NEW) ? 0x80 : 0x00); + keyb_fakedata = (data & 0x7f) | ((data & KEYB_NEW) ? 0x80 : 0x00); - return irq->vector; + return irq->vector; } static uint8_t dart_keyb_in(uint8_t port) { - uint8_t v, reg; + uint8_t v, reg; + + switch (port & 1) { + case 0: /* Data register */ + v = get_key(); + break; + + case 1: /* Control register */ + reg = dart_keyb_ctl[0] & 7; + dart_keyb_ctl[0] &= ~7; /* Restore register 0 */ + + switch (reg) { + case 0: + v = (keyb_data >> 8) + (1 << 2) + /* Transmit buffer empty */ + (dart_keyb_vsync << 4) + /* RI -> vsync */ + (1 << 5); /* CTS -> 60 Hz */ + break; + case 1: + v = (1 << 0); /* All sent */ + break; + case 2: + v = dart_keyb_ctl[2]; + break; + default: + v = 0; + break; + } + break; + } - switch (port & 1) { - case 0: /* Data register */ - v = get_key(); - break; + return v; +} - case 1: /* Control register */ - reg = dart_keyb_ctl[0] & 7; - dart_keyb_ctl[0] &= ~7; /* Restore register 0 */ +static void abc802_out(uint8_t port, uint8_t value) +{ + port = abc800_mangle_port(port); - switch (reg) { + switch (port) { case 0: - v = (keyb_data >> 8) + - (1 << 2) + /* Transmit buffer empty */ - (dart_keyb_vsync << 4) + /* RI -> vsync */ - (1 << 5); /* CTS -> 60 Hz */ - break; case 1: - v = (1 << 0); /* All sent */ - break; case 2: - v = dart_keyb_ctl[2]; - break; + case 3: + case 4: + case 5: + abcbus_out(port, value); + break; + + case 32: + case 33: + dart_pr_out(port, value); + break; + + case 34: + case 35: + dart_keyb_out(port, value); + break; + + case 54: + case 55: + abc806_rtc_out(port, value); + break; + + case 56: + case 57: + crtc_out(port, value); + break; + + case 66: + case 67: + abc800_sio_cas_out(port, value); + break; + + case 96: + case 97: + case 98: + case 99: + abc800_ctc_out(port, value); + break; + default: - v = 0; - break; + break; } - break; - } - - return v; -} - -static void abc802_out(uint8_t port, uint8_t value) -{ - port = abc800_mangle_port(port); - - switch (port) { - case 0: - case 1: - case 2: - case 3: - case 4: - case 5: - abcbus_out(port, value); - break; - - case 32: - case 33: - dart_pr_out(port, value); - break; - - case 34: - case 35: - dart_keyb_out(port, value); - break; - - case 54: - case 55: - abc806_rtc_out(port, value); - break; - - case 56: - case 57: - crtc_out(port, value); - break; - - case 66: - case 67: - abc800_sio_cas_out(port, value); - break; - - case 96: - case 97: - case 98: - case 99: - abc800_ctc_out(port, value); - break; - - default: - break; - } } -static void (*do_out)(uint8_t, uint8_t); +static void (*do_out) (uint8_t, uint8_t); void z80_out(int port, uint8_t value) { - if (tracing(TRACE_IO)) { - fprintf(tracef, "OUT: port 0x%02x (%3d) sel 0x%02x (%2d) " - "data 0x%02x (%3d) PC=%04x\n", - port, port, abcbus_select & 0xff, abcbus_select, - value, value, REG_PC); - } - - do_out(port, value); + if (tracing(TRACE_IO)) { + fprintf(tracef, "OUT: port 0x%02x (%3d) sel 0x%02x (%2d) " + "data 0x%02x (%3d) PC=%04x\n", + port, port, abcbus_select & 0xff, abcbus_select, + value, value, REG_PC); + } + + do_out(port, value); } /* @@ -299,188 +296,188 @@ void z80_out(int port, uint8_t value) */ static uint8_t abcbus_in(uint8_t port) { - if (port == 7) { - /* Reset all */ - abcbus_select = -1; - disk_reset(); - printer_reset(); - return 0xff; - } - - switch (abcbus_select) { - case 36: /* HDx: */ - case 44: /* MFx: */ - case 45: /* MOx: */ - case 46: /* SFx: */ - return disk_in(abcbus_select, port); - break; - - case 60: /* PRx: */ - return printer_in(abcbus_select, port); - break; - - case 55: /* RTC */ - return rtc_in(abcbus_select, port); - break; - - default: - return 0xff; - break; - } - } + if (port == 7) { + /* Reset all */ + abcbus_select = -1; + disk_reset(); + printer_reset(); + return 0xff; + } + + switch (abcbus_select) { + case 36: /* HDx: */ + case 44: /* MFx: */ + case 45: /* MOx: */ + case 46: /* SFx: */ + return disk_in(abcbus_select, port); + break; + + case 60: /* PRx: */ + return printer_in(abcbus_select, port); + break; + + case 55: /* RTC */ + return rtc_in(abcbus_select, port); + break; + + default: + return 0xff; + break; + } +} static uint8_t abc80_in(uint8_t port) { - uint8_t v = 0xff; + uint8_t v = 0xff; - port &= 0x17; + port &= 0x17; - switch (port) { - case 0: - case 1: - case 7: - v = abcbus_in(port); - break; + switch (port) { + case 0: + case 1: + case 7: + v = abcbus_in(port); + break; - case 3: - setmode40(1); - break; + case 3: + setmode40(1); + break; - case 4: - setmode40(0); - break; + case 4: + setmode40(0); + break; + + case (56 & 0x17): + if (faketype) { + v = keyb_fakedata; + keyb_fakedata &= ~0x80; + } else { + unsigned int kbd = keyb_data; + v = (kbd & 0x7f) | ((kbd & KEYB_DOWN) ? 0x80 : 0); + } + break; + + case (58 & 0x17): + v = abc80_piob_in(); + break; - case (56 & 0x17): - if (faketype) { - v = keyb_fakedata; - keyb_fakedata &= ~0x80; - } else { - unsigned int kbd = keyb_data; - v = (kbd & 0x7f) | ((kbd & KEYB_DOWN) ? 0x80 : 0); + default: + break; } - break; - - case (58 & 0x17): - v = abc80_piob_in(); - break; - default: - break; - } - - return v; + return v; } static uint8_t abc802_in(uint8_t port) { - uint8_t v = 0xff; - - port = abc800_mangle_port(port); - - switch (port) { - case 0: - case 1: - case 2: - case 7: - v = abcbus_in(port); - break; - - case 32: - case 33: - v = dart_pr_in(port); - break; - - case 34: - case 35: - v = dart_keyb_in(port); - break; - - case 54: - case 55: - v = abc806_rtc_in(port); - break; - - case 56: - case 57: - v = crtc_in(port); - break; - - case 66: - case 67: - v = abc800_sio_cas_in(port); - break; - - case 96: - case 97: - case 98: - case 99: - v = abc800_ctc_in(port); - break; - - default: - break; - } - - return v; + uint8_t v = 0xff; + + port = abc800_mangle_port(port); + + switch (port) { + case 0: + case 1: + case 2: + case 7: + v = abcbus_in(port); + break; + + case 32: + case 33: + v = dart_pr_in(port); + break; + + case 34: + case 35: + v = dart_keyb_in(port); + break; + + case 54: + case 55: + v = abc806_rtc_in(port); + break; + + case 56: + case 57: + v = crtc_in(port); + break; + + case 66: + case 67: + v = abc800_sio_cas_in(port); + break; + + case 96: + case 97: + case 98: + case 99: + v = abc800_ctc_in(port); + break; + + default: + break; + } + + return v; } -static uint8_t (*do_in)(uint8_t port); +static uint8_t(*do_in) (uint8_t port); int z80_in(int port) { - uint8_t sel, v; + uint8_t sel, v; - sel = abcbus_select; - v = do_in(port); + sel = abcbus_select; + v = do_in(port); - if (tracing(TRACE_IO)) { - fprintf(tracef, " IN: port 0x%02x (%3d) sel 0x%02x (%2d) " - "data 0x%02x (%3d) PC=%04x\n", - port, port, sel, (int8_t)sel, v, v, REG_PC); - } - return v; + if (tracing(TRACE_IO)) { + fprintf(tracef, " IN: port 0x%02x (%3d) sel 0x%02x (%2d) " + "data 0x%02x (%3d) PC=%04x\n", + port, port, sel, (int8_t) sel, v, v, REG_PC); + } + return v; } /* This is called in the event handler thread context! */ void keyboard_down(int sym) { - if (model == MODEL_ABC80) { - if (sym & ~127) - return; - } + if (model == MODEL_ABC80) { + if (sym & ~127) + return; + } - keyb_data = sym | KEYB_NEW | KEYB_DOWN; - z80_interrupt(keyb_irq); + keyb_data = sym | KEYB_NEW | KEYB_DOWN; + z80_interrupt(keyb_irq); } unsigned int keyboard_up(void) { - unsigned int rv, kbd; + unsigned int rv, kbd; - rv = kbd = keyb_data; - cmpxchg(&keyb_data, &kbd, kbd & ~KEYB_DOWN); + rv = kbd = keyb_data; + cmpxchg(&keyb_data, &kbd, kbd & ~KEYB_DOWN); - return rv; + return rv; } void io_init(void) { switch (model) { case MODEL_ABC80: - do_out = abc80_out; - do_in = abc80_in; - keyb_data = 0; - abc80_cas_init(); - keyb_irq = faketype ? &keyb_irq_fake : &keyb_irq_80; - break; + do_out = abc80_out; + do_in = abc80_in; + keyb_data = 0; + abc80_cas_init(); + keyb_irq = faketype ? &keyb_irq_fake : &keyb_irq_80; + break; case MODEL_ABC802: - do_out = abc802_out; - do_in = abc802_in; - keyb_data = 0xff; - abc800_cas_init(); - abc800_ctc_init(); - keyb_irq = &keyb_irq_800; - break; + do_out = abc802_out; + do_in = abc802_in; + keyb_data = 0xff; + abc800_cas_init(); + abc800_ctc_init(); + keyb_irq = &keyb_irq_800; + break; } z80_register_irq(keyb_irq); } @@ -57,7 +57,6 @@ extern void abc800_sio_cas_out(uint8_t port, uint8_t v); extern uint8_t abc800_sio_cas_in(uint8_t port); extern void abc800_cas_init(void); - /* * Z80 has fixed priorities based on the device daisy chain, but the vectors * can be different, so we identify interrupts by their priority level. @@ -78,7 +77,8 @@ enum abc800_irq { }; /* Directory and filenames */ -extern const char *fileop_path, *disk_path, *screen_path, *memdump_path, *cas_path; +extern const char *fileop_path, *disk_path, *screen_path, *memdump_path, + *cas_path; extern struct file_list cas_files; /* Program name for error messages */ @@ -10,14 +10,14 @@ uint8_t ram[MEMORY_SIZE]; -typedef void (*write_func)(uint8_t *p, uint8_t v); +typedef void (*write_func) (uint8_t * p, uint8_t v); struct mem_page { uint8_t *data; write_func write; }; -static void write_rom(uint8_t *p, uint8_t v); -#define write_ram NULL /* Optimized fast path */ +static void write_rom(uint8_t * p, uint8_t v); +#define write_ram NULL /* Optimized fast path */ #define write_screen write_ram #define PAGE_SHIFT 10 @@ -51,26 +51,26 @@ static inline const struct mem_page *get_page(uint16_t addr) */ struct mem_trace { uint16_t addr, data; - uint8_t size; - bool written; + uint8_t size; + bool written; }; #define MAX_TRACES 16 -static struct mem_trace mem_traces[MAX_TRACES+1]; +static struct mem_trace mem_traces[MAX_TRACES + 1]; static struct mem_trace *mem_trace_tail = mem_traces; static inline void mem_trace_record(uint16_t addr, uint16_t data, uint8_t size, bool written) { if (!tracing(TRACE_CPU)) - return; + return; if (mem_trace_tail <= &mem_traces[MAX_TRACES]) { - mem_trace_tail->addr = addr; - mem_trace_tail->data = data; - mem_trace_tail->size = size; - mem_trace_tail->written = written; - mem_trace_tail++; + mem_trace_tail->addr = addr; + mem_trace_tail->data = data; + mem_trace_tail->size = size; + mem_trace_tail->written = written; + mem_trace_tail++; } } @@ -83,24 +83,24 @@ void tracemem(void) int last_written = -1; if (!tracing(TRACE_CPU)) - return; + return; if (mem_trace_tail >= &mem_traces[MAX_TRACES]) { - mem_trace_tail--; - overflow = true; + mem_trace_tail--; + overflow = true; } for (mtp = mem_traces; mtp < mem_trace_tail; mtp++) { - fputc(' ', tracef); - if (mtp->addr != last_addr || mtp->written != last_written) - fprintf(tracef, "(%04X)%c", mtp->addr, mtp->written ? '=' : ':'); - fprintf(tracef, "%0*X", mtp->size*2, mtp->data); - last_addr = mtp->addr + mtp->size; - last_written = mtp->written; + fputc(' ', tracef); + if (mtp->addr != last_addr || mtp->written != last_written) + fprintf(tracef, "(%04X)%c", mtp->addr, mtp->written ? '=' : ':'); + fprintf(tracef, "%0*X", mtp->size * 2, mtp->data); + last_addr = mtp->addr + mtp->size; + last_written = mtp->written; } if (overflow) - fputs(" ...", tracef); + fputs(" ...", tracef); mem_trace_tail = mem_traces; } @@ -140,7 +140,7 @@ static inline uint16_t do_mem_read_word(uint16_t address) uint8_t b0, b1; b0 = do_mem_read(address); - b1 = do_mem_read(address+1); + b1 = do_mem_read(address + 1); return (b1 << 8) + b0; } @@ -161,11 +161,13 @@ uint16_t mem_fetch_word(uint16_t address) /* * Simple write operations */ -static void write_rom(uint8_t *p, uint8_t v) +static void write_rom(uint8_t * p, uint8_t v) { /* Do nothing */ - (void)p; (void) v; + (void)p; + (void)v; } + static void do_mem_write(uint16_t address, uint8_t value) { const struct mem_page *page; @@ -174,9 +176,9 @@ static void do_mem_write(uint16_t address, uint8_t value) page = get_page(address); p = &page->data[address & PAGE_MASK]; if (likely(!page->write)) - *p = value; + *p = value; else - page->write(p, value); + page->write(p, value); } void mem_write(uint16_t address, uint8_t value) @@ -189,7 +191,7 @@ void mem_write_word(uint16_t address, uint16_t value) { mem_trace_record(address, value, 2, true); do_mem_write(address, value); - do_mem_write(address+1, value >> 8); + do_mem_write(address + 1, value >> 8); } /* @@ -203,10 +205,11 @@ void abc80_mem_mode40(bool mode40) abc80_map = (abc80_map & ~1) | mode40; current_map[0] = current_map[1] = memmaps[abc80_map]; } + void abc80_mem_setmap(unsigned int map) { if (kilobytes < 64) - return; /* Only 64K models can remap memory */ + return; /* Only 64K models can remap memory */ abc80_map = ((map & 3) << 1) | (abc80_map & ~6); current_map[0] = current_map[1] = memmaps[abc80_map]; @@ -221,38 +224,37 @@ void abc802_set_mem(bool opened) current_map[1] = memmaps[opened ? 2 : 1]; } - #define K(x) ((x)*1024) #define ALL_MAPS ((1U << MEM_MAPS)-1) static void map_memory(unsigned int maps, size_t where, size_t size, - void *what, write_func wfunc) + void *what, write_func wfunc) { size_t m; - assert(((where|size) & PAGE_MASK) == 0); + assert(((where | size) & PAGE_MASK) == 0); assert((maps & ~ALL_MAPS) == 0); - for (m = 0; maps; m++, maps >>=1) { - struct mem_page *mp; - uint8_t *datap; - size_t npg; + for (m = 0; maps; m++, maps >>= 1) { + struct mem_page *mp; + uint8_t *datap; + size_t npg; - if (!(maps & 1)) - continue; + if (!(maps & 1)) + continue; - mp = &memmaps[m][where >> PAGE_SHIFT]; - datap = what; + mp = &memmaps[m][where >> PAGE_SHIFT]; + datap = what; - npg = size >> PAGE_SHIFT; + npg = size >> PAGE_SHIFT; - while (npg--) { - mp->data = datap; - mp->write = wfunc; - datap += PAGE_SIZE; - mp++; - } + while (npg--) { + mp->data = datap; + mp->write = wfunc; + datap += PAGE_SIZE; + mp++; + } } } @@ -269,31 +271,31 @@ static void load_memfile(const char *memfile) const unsigned int max_blocks = (K(30) >> 8) - 1; if (!memfile) - return; + return; rp = ram; hf = open_host_file(HF_BINARY, NULL, memfile, O_RDONLY); if (!hf) - goto exit; + goto exit; if (!map_file(hf, 0)) - goto exit; + goto exit; init_abcdata(&abc, hf->map, hf->flen); blk = 0; while (blk < max_blocks) { - bool done; - rp[0] = 0x53; - rp[1] = 0; - rp[2] = blk++; - done = get_abc_block(rp+3, &abc); - rp += 256; - if (done) - break; + bool done; + rp[0] = 0x53; + rp[1] = 0; + rp[2] = blk++; + done = get_abc_block(rp + 3, &abc); + rp += 256; + if (done) + break; } exit: - memset(rp, 0, 3); /* Avoid possible stray magic */ + memset(rp, 0, 3); /* Avoid possible stray magic */ close_file(&hf); } @@ -310,69 +312,69 @@ void mem_init(unsigned int flags, const char *memfile) switch (model) { case MODEL_ABC80: - /* 4 maps * 2 (40/80) */ - - if ((kilobytes < 1 || kilobytes > 32) && kilobytes != 64) { - fprintf(stderr, "%s: invalid ABC80 memory size %uK, using 64K\n", - program_name, kilobytes); - kilobytes = 64; - } - - /* Map 0: default (for < 64K, the only available map) */ - if (!(flags & MEMFL_NOBASIC)) { - map_memory(0x01, 0, K(16), - old_basic ? abc80bas80o : abc80bas80n, write_rom); - map_memory(0x02, 0, K(16), - old_basic ? abc80bas40o : abc80bas40n, write_rom); - } - if (!(flags & MEMFL_NODEV)) { - /* Hack: allow device ROMs to be written to */ - map_memory(0x03, K(16), K(16), abc80_devs, write_ram); - } - map_memory(0x01, K(29), K(1), &video_ram[K(0)], write_screen); - map_memory(0x03, K(31), K(1), &video_ram[K(1)], write_screen); - - if (kilobytes < 32) { - /* - * Simulate non-existing memory by filling it with FF - * and changing it to readonly. ABC80 RAM grows from - * top of memory downward toward 32K. - */ - memset(ram + K(32), 0xff, K(32-kilobytes)); - map_memory(0x03, K(32), K(32-kilobytes), &ram[K(32)], write_rom); - } - - /* Map 1: RAM over ROM areas */ - map_memory(0x04, K(30), K(2), &video_ram[K(0)], write_screen); - map_memory(0x08, K(31), K(1), &video_ram[K(1)], write_screen); - - /* Map 2: video RAM at the end */ - map_memory(0x10, K(62), K(2), &video_ram[K(0)], write_screen); - map_memory(0x20, K(63), K(1), &video_ram[K(1)], write_screen); - - /* Map 3: all RAM */ - - abc80_mem_setmap(0); /* Default to map 0 */ - break; + /* 4 maps * 2 (40/80) */ + + if ((kilobytes < 1 || kilobytes > 32) && kilobytes != 64) { + fprintf(stderr, "%s: invalid ABC80 memory size %uK, using 64K\n", + program_name, kilobytes); + kilobytes = 64; + } + + /* Map 0: default (for < 64K, the only available map) */ + if (!(flags & MEMFL_NOBASIC)) { + map_memory(0x01, 0, K(16), + old_basic ? abc80bas80o : abc80bas80n, write_rom); + map_memory(0x02, 0, K(16), + old_basic ? abc80bas40o : abc80bas40n, write_rom); + } + if (!(flags & MEMFL_NODEV)) { + /* Hack: allow device ROMs to be written to */ + map_memory(0x03, K(16), K(16), abc80_devs, write_ram); + } + map_memory(0x01, K(29), K(1), &video_ram[K(0)], write_screen); + map_memory(0x03, K(31), K(1), &video_ram[K(1)], write_screen); + + if (kilobytes < 32) { + /* + * Simulate non-existing memory by filling it with FF + * and changing it to readonly. ABC80 RAM grows from + * top of memory downward toward 32K. + */ + memset(ram + K(32), 0xff, K(32 - kilobytes)); + map_memory(0x03, K(32), K(32 - kilobytes), &ram[K(32)], write_rom); + } + + /* Map 1: RAM over ROM areas */ + map_memory(0x04, K(30), K(2), &video_ram[K(0)], write_screen); + map_memory(0x08, K(31), K(1), &video_ram[K(1)], write_screen); + + /* Map 2: video RAM at the end */ + map_memory(0x10, K(62), K(2), &video_ram[K(0)], write_screen); + map_memory(0x20, K(63), K(1), &video_ram[K(1)], write_screen); + + /* Map 3: all RAM */ + + abc80_mem_setmap(0); /* Default to map 0 */ + break; case MODEL_ABC802: - /* Map 0: normal execution */ + /* Map 0: normal execution */ - if (!(flags & MEMFL_NOBASIC)) - map_memory(0x01, 0, K(24), abc802rom, write_rom); + if (!(flags & MEMFL_NOBASIC)) + map_memory(0x01, 0, K(24), abc802rom, write_rom); - if (!(flags & MEMFL_NODEV)) - map_memory(0x01, K(24), K(8), &abc802rom[K(24)], write_rom); + if (!(flags & MEMFL_NODEV)) + map_memory(0x01, K(24), K(8), &abc802rom[K(24)], write_rom); - map_memory(0x01, K(30), K(2), video_ram, write_screen); + map_memory(0x01, K(30), K(2), video_ram, write_screen); - /* Map 1: execution in option ROM - RAM other than the ROM itself */ - map_memory(0x02, K(30), K(2), &abc802rom[K(30)], write_rom); + /* Map 1: execution in option ROM - RAM other than the ROM itself */ + map_memory(0x02, K(30), K(2), &abc802rom[K(30)], write_rom); - /* Map 2: MEM area open in its entirety */ + /* Map 2: MEM area open in its entirety */ - abc802_set_mem(false); /* On start, MEM area closed */ - break; + abc802_set_mem(false); /* On start, MEM area closed */ + break; } load_memfile(memfile); @@ -385,21 +387,20 @@ const char *memdump_path; void dump_memory(bool ramonly) { - const struct mem_page *map = - ramonly ? memmaps[7] : current_map[0]; + 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"); + ramonly ? "ram%04u.bin" : "mem%04u.bin"); if (!hf) - return; + return; for (i = 0; i < PAGE_COUNT; i++) - fwrite(map[i].data, 1, PAGE_SIZE, hf->f); + fwrite(map[i].data, 1, PAGE_SIZE, hf->f); if (!ferror(hf->f)) - keep_file(hf); /* It's good */ + keep_file(hf); /* It's good */ close_file(&hf); } @@ -16,20 +16,20 @@ const char *cas_path; * Cassette I/O */ struct cas_block { - uint8_t leadin[32]; /* 0x00 */ - uint8_t sync[3]; /* 0x16 */ - uint8_t stx; /* 0x02 */ - uint8_t blktype; /* 0x00 for data, 0xff for filename */ - uint8_t blkno[2]; /* Block number (littleendian) */ - uint8_t data[253]; /* Actual data */ - uint8_t etx; /* 0x03 */ - uint8_t csum[2]; /* Checksum */ + uint8_t leadin[32]; /* 0x00 */ + uint8_t sync[3]; /* 0x16 */ + uint8_t stx; /* 0x02 */ + uint8_t blktype; /* 0x00 for data, 0xff for filename */ + uint8_t blkno[2]; /* Block number (littleendian) */ + uint8_t data[253]; /* Actual data */ + uint8_t etx; /* 0x03 */ + uint8_t csum[2]; /* Checksum */ }; static struct host_file *hf; static struct cas_block block; -static unsigned int bitctr; /* Bit counter for ABC80 */ -static unsigned int bytectr; /* Byte counter for ABC800 */ +static unsigned int bitctr; /* Bit counter for ABC80 */ +static unsigned int bytectr; /* Byte counter for ABC800 */ static int block_nr = -1; static struct abcdata abc; @@ -56,15 +56,15 @@ static void cas_format_block(void) csumptr = (const uint8_t *)&block.blktype; csum = 0; for (i = 0; i < 257; i++) - csum += *csumptr++; + csum += *csumptr++; block.csum[0] = csum; block.csum[1] = csum >> 8; if (tracing(TRACE_CAS)) { - fprintf(tracef, "CAS: block %3d ready\n", block_nr); - trace_dump_data("CAS", &block.blktype, - sizeof block - offsetof(struct cas_block, blktype)); + fprintf(tracef, "CAS: block %3d ready\n", block_nr); + trace_dump_data("CAS", &block.blktype, + sizeof block - offsetof(struct cas_block, blktype)); } block_nr++; @@ -74,137 +74,138 @@ static void cas_format_block(void) static void cas_enable(bool enable) { if (tracing(TRACE_CAS)) - fprintf(tracef, "CAS: motor %s\n", enable ? "on" : "off"); + fprintf(tracef, "CAS: motor %s\n", enable ? "on" : "off"); /* Reset the cassette file position */ block_nr = -1; if (hf) { - if (tracing(TRACE_CAS)) - fprintf(tracef, "CAS: closing file %s\n", hf->filename); - close_file(&hf); + if (tracing(TRACE_CAS)) + fprintf(tracef, "CAS: closing file %s\n", hf->filename); + close_file(&hf); } if (!enable) - return; + return; memset(block.data, 0, 253); /* Do we have a filename list? */ while (!hf) { - /* Empty filename or file not found */ - char *casfile = filelist_pop(&cas_files); - if (!casfile) - break; /* Nothing more in the filename list */ - mangle_filename((char *)block.data, casfile); - hf = open_host_file(HF_BINARY, NULL, casfile, O_RDONLY); - if (tracing(TRACE_CAS)) { - fprintf(tracef, "CAS: listed file %s (%8.8s.%3.3s) %s\n", - casfile, block.data, block.data+8, hf ? "opened" : "not found"); - } - free(casfile); + /* Empty filename or file not found */ + char *casfile = filelist_pop(&cas_files); + if (!casfile) + break; /* Nothing more in the filename list */ + mangle_filename((char *)block.data, casfile); + hf = open_host_file(HF_BINARY, NULL, casfile, O_RDONLY); + if (tracing(TRACE_CAS)) { + fprintf(tracef, "CAS: listed file %s (%8.8s.%3.3s) %s\n", + casfile, block.data, block.data + 8, + hf ? "opened" : "not found"); + } + free(casfile); } if (!hf) { - /* - * HACK: if a specific filename has been given, try to snoop memory - * to figure out what file the user wanted. - */ - char casfile[64]; - uint16_t fnaddr; - int i; - - switch (model) { - case MODEL_ABC80: - /* ABC80: a pointer to the filename can be found at (SP+4) */ - fnaddr = mem_fetch_word(REG_SP + 4); - break; - - case MODEL_ABC802: - /* - * ABC800: a pointer to the filename can (apparently?) - * be found at DE - */ - fnaddr = REG_DE; - break; - - default: - fnaddr = -1; - break; - } - - for (i = 0; i < 11; i++) { - uint8_t c = mem_fetch(fnaddr++); - if (fnaddr == 0 || - (c != ' ' && (c < '0' || c > '9') && (c < 'A' || c > ']'))) { - /* - * Invalid character for an ABC filename or memory wraparound - * - we must be off in the weeds - */ - block.data[0] = ' '; /* Make the test below fail */ - break; - } - block.data[i] = c; - } - block.data[11] = '\0'; - - if (block.data[0] != ' ') { - bool isbac; - - /* Successfully snooped a non-empty filename */ - unmangle_filename(casfile, (char *)block.data); - isbac = !memcmp(block.data+8, "BAC", 3); - - for (;;) { - hf = open_host_file(HF_BINARY, cas_path, casfile, O_RDONLY); - if (tracing(TRACE_CAS)) { - fprintf(tracef, "CAS: snooped file %s (%8.8s.%3.3s) %s\n", - casfile, block.data, block.data+8, - hf ? "opened" : "not found"); - } - - if (hf) - break; - - if (!isbac) - break; - - block.data[10] = 'S'; /* BAC -> BAS */ - unmangle_filename(casfile, (char *)block.data); - /* - * We have to tell ABC that the filename is .bac, - * or it won't be able to find it on cassette; - * unlike how it works on disk. - */ - block.data[10] = 'C'; /* BAS -> BAC */ - isbac = false; - } - } + /* + * HACK: if a specific filename has been given, try to snoop memory + * to figure out what file the user wanted. + */ + char casfile[64]; + uint16_t fnaddr; + int i; + + switch (model) { + case MODEL_ABC80: + /* ABC80: a pointer to the filename can be found at (SP+4) */ + fnaddr = mem_fetch_word(REG_SP + 4); + break; + + case MODEL_ABC802: + /* + * ABC800: a pointer to the filename can (apparently?) + * be found at DE + */ + fnaddr = REG_DE; + break; + + default: + fnaddr = -1; + break; + } + + for (i = 0; i < 11; i++) { + uint8_t c = mem_fetch(fnaddr++); + if (fnaddr == 0 || + (c != ' ' && (c < '0' || c > '9') && (c < 'A' || c > ']'))) { + /* + * Invalid character for an ABC filename or memory wraparound + * - we must be off in the weeds + */ + block.data[0] = ' '; /* Make the test below fail */ + break; + } + block.data[i] = c; + } + block.data[11] = '\0'; + + if (block.data[0] != ' ') { + bool isbac; + + /* Successfully snooped a non-empty filename */ + unmangle_filename(casfile, (char *)block.data); + isbac = !memcmp(block.data + 8, "BAC", 3); + + for (;;) { + hf = open_host_file(HF_BINARY, cas_path, casfile, O_RDONLY); + if (tracing(TRACE_CAS)) { + fprintf(tracef, "CAS: snooped file %s (%8.8s.%3.3s) %s\n", + casfile, block.data, block.data + 8, + hf ? "opened" : "not found"); + } + + if (hf) + break; + + if (!isbac) + break; + + block.data[10] = 'S'; /* BAC -> BAS */ + unmangle_filename(casfile, (char *)block.data); + /* + * We have to tell ABC that the filename is .bac, + * or it won't be able to find it on cassette; + * unlike how it works on disk. + */ + block.data[10] = 'C'; /* BAS -> BAC */ + isbac = false; + } + } } if (!hf) { - if (tracing(TRACE_CAS)) - fprintf(tracef, "CAS: no more files\n"); - return; + if (tracing(TRACE_CAS)) + fprintf(tracef, "CAS: no more files\n"); + return; } map_file(hf, 0); if (hf->map) { - /* - * ABC-klubben standard: block count encoded in the header - */ - unsigned int blks = init_abcdata(&abc, hf->map, hf->flen); - block.data[251] = blks; - block.data[252] = blks >> 8; - if (tracing(TRACE_CAS)) { - fprintf(tracef, "CAS: file is a %s file, %u blocks\n", - abc.is_text ? "text" : "binary", blks); - } + /* + * ABC-klubben standard: block count encoded in the header + */ + unsigned int blks = init_abcdata(&abc, hf->map, hf->flen); + block.data[251] = blks; + block.data[252] = blks >> 8; + if (tracing(TRACE_CAS)) { + fprintf(tracef, "CAS: file is a %s file, %u blocks\n", + abc.is_text ? "text" : "binary", blks); + } } else { - close_file(&hf); - if (tracing(TRACE_CAS)) - fprintf(tracef, "CAS: file mapping failed\n"); - return; + close_file(&hf); + if (tracing(TRACE_CAS)) + fprintf(tracef, "CAS: file mapping failed\n"); + return; } cas_format_block(); @@ -213,14 +214,14 @@ static void cas_enable(bool enable) static void cas_next_block(void) { if (!hf) { - block_nr = -1; /* Finished EOF block, cassette idle */ + block_nr = -1; /* Finished EOF block, cassette idle */ } else { - if (get_abc_block(block.data, &abc)) { - /* If get_abc_block() returned true, this is the last block */ - close_file(&hf); - } + if (get_abc_block(block.data, &abc)) { + /* If get_abc_block() returned true, this is the last block */ + close_file(&hf); + } - cas_format_block(); + cas_format_block(); } } @@ -233,33 +234,32 @@ static bool cas_edge(void) bc = bitctr++; if (cas_idle()) { - if (tracing(TRACE_CAS)) - fprintf(tracef, "CAS: reading with nothing, bit %4u\n", bc); - return false; + if (tracing(TRACE_CAS)) + fprintf(tracef, "CAS: reading with nothing, bit %4u\n", bc); + return false; } b = ((const uint8_t *)&block)[bc >> 4]; bit = ((b >> ((bc >> 1) & 7)) | ~bc) & 1; if (tracing(TRACE_CAS)) { - char bstr[4]; - if (b >= 32 && b <= 126) { - bstr[0] = bstr[2] = '\''; - bstr[1] = b; - bstr[3] = '\0'; - } else { - snprintf(bstr, sizeof bstr, "%3u", b); - } - - fprintf(tracef, "CAS: block %3d byte %3d = %02x %s %s %u = %u\n", - block_nr-1, (bc >> 4) - (int)offsetof(struct cas_block, data), - b, bstr, (bc & 1) ? "bit" : "clk", - (bc >> 1) & 7, bit); + char bstr[4]; + if (b >= 32 && b <= 126) { + bstr[0] = bstr[2] = '\''; + bstr[1] = b; + bstr[3] = '\0'; + } else { + snprintf(bstr, sizeof bstr, "%3u", b); + } + + fprintf(tracef, "CAS: block %3d byte %3d = %02x %s %s %u = %u\n", + block_nr - 1, (bc >> 4) - (int)offsetof(struct cas_block, data), + b, bstr, (bc & 1) ? "bit" : "clk", (bc >> 1) & 7, bit); } - if (bitctr >= 16*sizeof block) { - /* End of data, read another block */ - cas_next_block(); + if (bitctr >= 16 * sizeof block) { + /* End of data, read another block */ + cas_next_block(); } return bit; @@ -305,12 +305,12 @@ static void pio_check_interrupt(struct pio *pio) masked &= pio->irqmask; trigger = (pio->irqctl & 0x80) && (pio->mode == 3) && - (pio->irqctl & 0x40) ? (masked == pio->irqmask) : (masked != 0); + (pio->irqctl & 0x40) ? (masked == pio->irqmask) : (masked != 0); if (trigger) - z80_interrupt(&pio->irq); + z80_interrupt(&pio->irq); else - z80_clear_interrupt(&pio->irq); + z80_clear_interrupt(&pio->irq); } static int pio_eoi(struct z80_irq *irq) @@ -323,46 +323,46 @@ static void pio_control(struct pio *pio, uint8_t v) { switch (pio->ctlstate) { case pcs_init: - switch (v & 15) { - case 0xf: - pio->mode = v >> 6; - switch (pio->mode) { - case 0: /* All output */ - pio->mask = 0xff; - break; - case 1: /* All input */ - case 2: /* Bidir, treat as input */ - pio->mask = 0; - break; - case 3: /* Programmable */ - pio->ctlstate = pcs_mask; - break; - } - break; - case 0x07: - pio->irqctl = v; - if (pio->irqctl & 0x10) - pio->ctlstate = pcs_irqmask; - break; - case 0x03: - pio->irqctl = (pio->irqctl & 0x7f) | (v & 0x80); - break; - default: - if ((v & 1) == 0) - pio->irq.vector = v; - break; - } - break; + switch (v & 15) { + case 0xf: + pio->mode = v >> 6; + switch (pio->mode) { + case 0: /* All output */ + pio->mask = 0xff; + break; + case 1: /* All input */ + case 2: /* Bidir, treat as input */ + pio->mask = 0; + break; + case 3: /* Programmable */ + pio->ctlstate = pcs_mask; + break; + } + break; + case 0x07: + pio->irqctl = v; + if (pio->irqctl & 0x10) + pio->ctlstate = pcs_irqmask; + break; + case 0x03: + pio->irqctl = (pio->irqctl & 0x7f) | (v & 0x80); + break; + default: + if ((v & 1) == 0) + pio->irq.vector = v; + break; + } + break; case pcs_mask: - pio->mask = ~v; /* We use 1 = output, PIO is opposite */ - pio->ctlstate = pcs_init; - break; + pio->mask = ~v; /* We use 1 = output, PIO is opposite */ + pio->ctlstate = pcs_init; + break; case pcs_irqmask: - pio->irqmask = ~v; - pio->ctlstate = pcs_init; - break; + pio->irqmask = ~v; + pio->ctlstate = pcs_init; + break; } } @@ -371,32 +371,32 @@ void abc80_piob_out(uint8_t port, uint8_t v) uint8_t old = pio_readval(&portb); switch (port & 1) { - case 0: /* Data port */ - portb.out = v; - - /* Cassette relay */ - if ((v ^ old) & portb.mask & 0x20) - cas_enable(v & portb.mask & 0x20); - - /* Clear edge (input inverted!) */ - if (~v & portb.mask & 0x40) { - portb.in |= 0x80; - } else if (~old & v & portb.mask & 0x40) { - /* 0->1 transition */ - if (cas_edge()) - portb.in &= ~0x80; - } - break; - - case 1: /* Control port */ - { - uint8_t oldirqctl = portb.irqctl; - pio_control(&portb, v); - /* Hack to resynchronize with bitstream */ - if (~oldirqctl & portb.irqctl & 0x80) - bitctr &= ~1; /* Next bit will be a clock bit */ - break; - } + case 0: /* Data port */ + portb.out = v; + + /* Cassette relay */ + if ((v ^ old) & portb.mask & 0x20) + cas_enable(v & portb.mask & 0x20); + + /* Clear edge (input inverted!) */ + if (~v & portb.mask & 0x40) { + portb.in |= 0x80; + } else if (~old & v & portb.mask & 0x40) { + /* 0->1 transition */ + if (cas_edge()) + portb.in &= ~0x80; + } + break; + + case 1: /* Control port */ + { + uint8_t oldirqctl = portb.irqctl; + pio_control(&portb, v); + /* Hack to resynchronize with bitstream */ + if (~oldirqctl & portb.irqctl & 0x80) + bitctr &= ~1; /* Next bit will be a clock bit */ + break; + } } pio_check_interrupt(&portb); @@ -428,22 +428,23 @@ static int sio_cas_eoi(struct z80_irq *irq); static uint8_t sio_cas_ctl[8]; static bool cas_first_rx_armed = true; -static struct z80_irq sio_cas_irq = - IRQ(IRQ800_SIOB, NULL, sio_cas_eoi, NULL); +static struct z80_irq sio_cas_irq = IRQ(IRQ800_SIOB, NULL, sio_cas_eoi, NULL); static inline bool cas_have_sync(void) { return !cas_idle() && (sio_cas_ctl[3] && 1); } + static inline bool cas_have_data(void) { return cas_have_sync() && !(sio_cas_ctl[3] & 0x10); } + static inline bool cas_rx_interrupt(bool huntok) { return cas_have_sync() && (huntok || !(sio_cas_ctl[3] & 0x10)) && - ((sio_cas_ctl[1] & 0x10) || - ((sio_cas_ctl[1] & 0x08) && cas_first_rx_armed)); + ((sio_cas_ctl[1] & 0x10) || + ((sio_cas_ctl[1] & 0x08) && cas_first_rx_armed)); } static void cas_poll_interrupt(void); @@ -459,12 +460,12 @@ static int sio_cas_eoi(struct z80_irq *irq) static void cas_poll_interrupt(void) { if (!cas_rx_interrupt(true)) { - z80_clear_interrupt(&sio_cas_irq); - return; + z80_clear_interrupt(&sio_cas_irq); + return; } /* Actually signal a receive data interrupt */ - sio_cas_ctl[3] &= ~0x10; /* Not hunting anymore */ + sio_cas_ctl[3] &= ~0x10; /* Not hunting anymore */ cas_first_rx_armed = false; sio_cas_irq.vector = (sio_cas_ctl[2] & ~0x0f) | 0x04; z80_interrupt(&sio_cas_irq); @@ -475,56 +476,54 @@ void abc800_sio_cas_out(uint8_t port, uint8_t v) uint8_t r; switch (port & 1) { - case 0: /* Data port */ - break; /* Ignore for now */ + case 0: /* Data port */ + break; /* Ignore for now */ case 1: - r = sio_cas_ctl[0] & 7; - sio_cas_ctl[0] &= ~7; - sio_cas_ctl[r] = v; - - switch (r) { - case 0: - switch ((v >> 3) & 7) { - case 3: - memset(sio_cas_ctl, 0, sizeof sio_cas_ctl); - cas_first_rx_armed = true; - break; - case 4: - cas_first_rx_armed = true; - break; - default: - break; - } - break; - case 3: - if (v & 0x10) { - /* Entering hunt mode; skip to next sync */ - if (bytectr) - cas_next_block(); - bytectr = 0; - } - break; - case 5: - if ((v & 0x80) && cas_idle()) - cas_enable(true); - break; - default: - break; - } - if (tracing(TRACE_CAS)) { - fprintf(tracef, "CAS: SIO ctl %02x %02x %02x %02x - " - "%02x %02x %02x %02x\n", - sio_cas_ctl[0], - sio_cas_ctl[1], - sio_cas_ctl[2], - sio_cas_ctl[3], - sio_cas_ctl[4], - sio_cas_ctl[5], - sio_cas_ctl[6], - sio_cas_ctl[7]); - } - break; + r = sio_cas_ctl[0] & 7; + sio_cas_ctl[0] &= ~7; + sio_cas_ctl[r] = v; + + switch (r) { + case 0: + switch ((v >> 3) & 7) { + case 3: + memset(sio_cas_ctl, 0, sizeof sio_cas_ctl); + cas_first_rx_armed = true; + break; + case 4: + cas_first_rx_armed = true; + break; + default: + break; + } + break; + case 3: + if (v & 0x10) { + /* Entering hunt mode; skip to next sync */ + if (bytectr) + cas_next_block(); + bytectr = 0; + } + break; + case 5: + if ((v & 0x80) && cas_idle()) + cas_enable(true); + break; + default: + break; + } + if (tracing(TRACE_CAS)) { + fprintf(tracef, "CAS: SIO ctl %02x %02x %02x %02x - " + "%02x %02x %02x %02x\n", + sio_cas_ctl[0], + sio_cas_ctl[1], + sio_cas_ctl[2], + sio_cas_ctl[3], + sio_cas_ctl[4], + sio_cas_ctl[5], sio_cas_ctl[6], sio_cas_ctl[7]); + } + break; } cas_poll_interrupt(); @@ -535,63 +534,63 @@ uint8_t abc800_sio_cas_in(uint8_t port) uint8_t r, v = 0xff; switch (port & 1) { - case 0: /* Data port */ - if (cas_have_data()) { - if (!bytectr) { - /* Mark that this block has been read from */ - bytectr = offsetof(struct cas_block, blktype); - } - v = ((const uint8_t *)&block)[bytectr]; - if (tracing(TRACE_CAS)) { - fprintf(tracef, "CAS: block %3d byte %3d = %02x ", - block_nr-1, bytectr, v); - if (v < ' ' || v > '~') - fprintf(tracef, "%3u\n", v); - else - fprintf(tracef, "\'%c\'\n", v); - } - bytectr++; - if (bytectr >= sizeof block) { - cas_next_block(); - sio_cas_ctl[3] |= 0x10; - } - } - break; - case 1: /* Control port */ - r = sio_cas_ctl[0] & 7; - sio_cas_ctl[0] &= ~7; - - switch (r) { - case 0: - v = sio_cas_ctl[3] & 0x10; /* Hunting */ - v |= 0x20; /* CTS = 1? */ - v |= 0x04; /* Transmit buffer empty */ - if (cas_have_sync()) { - /* Rx enabled */ - if (cas_have_data()) { - v |= 1; /* Data available */ - } else { - /* In hunt mode, establish "sync" */ - if (bytectr) - cas_next_block(); - sio_cas_ctl[3] &= ~0x10; /* Not hunting anymore */ - } - } - break; - - case 1: - v = 0x01; /* Transmit buffer empty */ - break; - - case 2: - v = (sio_cas_ctl[2] & ~0x0e) | - (cas_rx_interrupt(false) ? 0x04 : 0x06); - break; - - default: - v = 0xff; - break; - } + case 0: /* Data port */ + if (cas_have_data()) { + if (!bytectr) { + /* Mark that this block has been read from */ + bytectr = offsetof(struct cas_block, blktype); + } + v = ((const uint8_t *)&block)[bytectr]; + if (tracing(TRACE_CAS)) { + fprintf(tracef, "CAS: block %3d byte %3d = %02x ", + block_nr - 1, bytectr, v); + if (v < ' ' || v > '~') + fprintf(tracef, "%3u\n", v); + else + fprintf(tracef, "\'%c\'\n", v); + } + bytectr++; + if (bytectr >= sizeof block) { + cas_next_block(); + sio_cas_ctl[3] |= 0x10; + } + } + break; + case 1: /* Control port */ + r = sio_cas_ctl[0] & 7; + sio_cas_ctl[0] &= ~7; + + switch (r) { + case 0: + v = sio_cas_ctl[3] & 0x10; /* Hunting */ + v |= 0x20; /* CTS = 1? */ + v |= 0x04; /* Transmit buffer empty */ + if (cas_have_sync()) { + /* Rx enabled */ + if (cas_have_data()) { + v |= 1; /* Data available */ + } else { + /* In hunt mode, establish "sync" */ + if (bytectr) + cas_next_block(); + sio_cas_ctl[3] &= ~0x10; /* Not hunting anymore */ + } + } + break; + + case 1: + v = 0x01; /* Transmit buffer empty */ + break; + + case 2: + v = (sio_cas_ctl[2] & ~0x0e) | + (cas_rx_interrupt(false) ? 0x04 : 0x06); + break; + + default: + v = 0xff; + break; + } } cas_poll_interrupt(); diff --git a/clib/asprintf.c b/clib/asprintf.c index cb55411..1afbc7b 100644 --- a/clib/asprintf.c +++ b/clib/asprintf.c @@ -14,19 +14,19 @@ int asprintf(char **strp, const char *fmt, ...) len = vsnprintf(NULL, 0, fmt, ap); va_end(ap); if (len < 0) - return -1; + return -1; - buf = malloc(len+1); + buf = malloc(len + 1); if (!buf) - return -1; + return -1; va_start(ap, fmt); - out = vsnprintf(buf, len+1, fmt, ap); + out = vsnprintf(buf, len + 1, fmt, ap); if (out < 0 || out >= len) { - /* Size of output changed behind our back?! */ - free(buf); - errno = EAGAIN; /* You can try again if you want... */ - return -1; + /* Size of output changed behind our back?! */ + free(buf); + errno = EAGAIN; /* You can try again if you want... */ + return -1; } va_end(ap); diff --git a/clib/inttypes.h b/clib/inttypes.h index e353aa9..5063d06 100644 --- a/clib/inttypes.h +++ b/clib/inttypes.h @@ -18,18 +18,18 @@ /* Some old versions of gcc <limits.h> omit LLONG_MAX */ #ifndef LLONG_MAX -# ifdef __LONG_LONG_MAX__ -# define LLONG_MAX __LONG_LONG_MAX__ -# else -# define LLONG_MAX 0 /* Assume long long is unusable */ -# endif +#ifdef __LONG_LONG_MAX__ +#define LLONG_MAX __LONG_LONG_MAX__ +#else +#define LLONG_MAX 0 /* Assume long long is unusable */ +#endif #endif #if LONG_MAX == 9223372036854775807L /* long is 64 bits */ -typedef signed long int64_t; -typedef unsigned long uint64_t; +typedef signed long int64_t; +typedef unsigned long uint64_t; #define _scn64 "l" #define _pri64 "l" #define INT64_C(x) x ## L @@ -38,8 +38,8 @@ typedef unsigned long uint64_t; #elif LLONG_MAX == 9223372036854775807LL /* long long is 64 bits */ -typedef signed long long int64_t; -typedef unsigned long long uint64_t; +typedef signed long long int64_t; +typedef unsigned long long uint64_t; #define _scn64 "ll" #define _pri64 "ll" #define INT64_C(x) x ## LL @@ -56,8 +56,8 @@ typedef unsigned long long uint64_t; #if INT_MAX == 2147483647 /* int is 32 bits */ -typedef signed int int32_t; -typedef unsigned int uint32_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; #define _scn32 "" #define _pri32 "" #define INT32_C(x) x @@ -66,8 +66,8 @@ typedef unsigned int uint32_t; #elif LONG_MAX == 2147483647L /* long is 32 bits */ -typedef signed long int32_t; -typedef unsigned long uint32_t; +typedef signed long int32_t; +typedef unsigned long uint32_t; #define _scn32 "l" #define _pri32 "l" #define INT32_C(x) x ## L @@ -84,8 +84,8 @@ typedef unsigned long uint32_t; #if INT_MAX == 32767 /* int is 16 bits */ -typedef signed int int16_t; -typedef unsigned int uint16_t; +typedef signed int int16_t; +typedef unsigned int uint16_t; #define _scn16 "" #define _pri16 "" #define INT16_C(x) x @@ -94,8 +94,8 @@ typedef unsigned int uint16_t; #elif SHRT_MAX == 32767 /* short is 16 bits */ -typedef signed short int16_t; -typedef unsigned short uint16_t; +typedef signed short int16_t; +typedef unsigned short uint16_t; #define _scn16 "h" #define _pri16 "" #define INT16_C(x) x @@ -112,8 +112,8 @@ typedef unsigned short uint16_t; #if SCHAR_MAX == 127 /* char is 8 bits */ -typedef signed char int8_t; -typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; #define _scn8 "hh" #define _pri8 "" #define INT8_C(x) x @@ -14,10 +14,10 @@ static struct abctimer *ctc_timer[4]; * Initialize the time for next event */ struct abctimer { - uint64_t period; /* Period in ns */ - uint64_t last; /* Last checkpoint in ns */ - uint64_t ltst; /* TSTATE value for last checkpoint */ - void (*func)(void); + uint64_t period; /* Period in ns */ + uint64_t last; /* Last checkpoint in ns */ + uint64_t ltst; /* TSTATE value for last checkpoint */ + void (*func) (void); }; #define MAX_TIMERS 2 @@ -26,21 +26,21 @@ static int ntimers; #define MS(x) ((x) * INT64_C(1000000)) -static struct abctimer *create_timer(uint64_t period, void (*func)(void)) +static struct abctimer *create_timer(uint64_t period, void (*func) (void)) { - struct abctimer *t; + struct abctimer *t; - if (ntimers >= MAX_TIMERS) - abort(); + if (ntimers >= MAX_TIMERS) + abort(); - t = &timers[ntimers++]; + t = &timers[ntimers++]; - t->period = period; - t->func = func; - t->last = 0; - t->ltst = 0; + t->period = period; + t->func = func; + t->last = 0; + t->ltst = 0; - return t; + return t; } static unsigned int poll_tstate_period; @@ -48,70 +48,70 @@ static unsigned int poll_tstate_period; void timer_init(void) { - nstime_init(); - - /* Limit polling to once every μs simulated time */ - poll_tstate_period = 1000*ns_per_tstate; - if (!limit_speed || poll_tstate_period > MAX_TSTATE_PERIOD) - poll_tstate_period = MAX_TSTATE_PERIOD; - - switch (model) { - case MODEL_ABC80: - /* 20 ms = 50 Hz */ - create_timer(MS(20), abc80_clock_tick); - break; - case MODEL_ABC802: - /* 10.67 ms = 93.75 Hz */ - ctc_timer[3] = create_timer(10666667, abc800_clock_tick); - - /* 20 ms = 50 Hz */ - create_timer(MS(20), abc802_vsync); - break; - } + nstime_init(); + + /* Limit polling to once every μs simulated time */ + poll_tstate_period = 1000 * ns_per_tstate; + if (!limit_speed || poll_tstate_period > MAX_TSTATE_PERIOD) + poll_tstate_period = MAX_TSTATE_PERIOD; + + switch (model) { + case MODEL_ABC80: + /* 20 ms = 50 Hz */ + create_timer(MS(20), abc80_clock_tick); + break; + case MODEL_ABC802: + /* 10.67 ms = 93.75 Hz */ + ctc_timer[3] = create_timer(10666667, abc800_clock_tick); + + /* 20 ms = 50 Hz */ + create_timer(MS(20), abc802_vsync); + break; + } } 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 - 1))) - return false; - - tmr->last += tmr->period; - if (unlikely((now - tmr->last) >= tmr->period)) { - /* Missed tick(s), advance clock to skip missed */ - tmr->last = now - ((now - tmr->last) % tmr->period); - } + /* This expression: a) will overflow safely, b) will never trigger for 0 */ + if (likely((now - tmr->last) <= (tmr->period - 1))) + return false; + + tmr->last += tmr->period; + if (unlikely((now - tmr->last) >= tmr->period)) { + /* Missed tick(s), advance clock to skip missed */ + tmr->last = now - ((now - tmr->last) % tmr->period); + } - return true; + return true; } /* See if it is time to slow down a bit */ static void consider_napping(uint64_t now, uint64_t next) { - uint64_t when; - int64_t ahead, behind; - static uint64_t ref_time, ref_tstate; - - if (unlikely(now <= ref_time || TSTATE <= ref_tstate)) - goto weird; - - when = ref_time + (TSTATE - ref_tstate) * ns_per_tstate; - behind = now - when; - ahead = when - next; - - /* Sanity range check: 100 ms behind or 100 ms ahead of schedule */ - if (unlikely(behind >= MS(200) || ahead >= MS(100))) - goto weird; - - /* If we are ahead of the next event, hold off and wait for it */ - if (ahead >= 0) - mynssleep(next, now); - return; - - weird: - /* We fell too far behind, got suspended, or the clock jumped... */ - ref_time = now; - ref_tstate = TSTATE; + uint64_t when; + int64_t ahead, behind; + static uint64_t ref_time, ref_tstate; + + if (unlikely(now <= ref_time || TSTATE <= ref_tstate)) + goto weird; + + when = ref_time + (TSTATE - ref_tstate) * ns_per_tstate; + behind = now - when; + ahead = when - next; + + /* Sanity range check: 100 ms behind or 100 ms ahead of schedule */ + if (unlikely(behind >= MS(200) || ahead >= MS(100))) + goto weird; + + /* If we are ahead of the next event, hold off and wait for it */ + if (ahead >= 0) + mynssleep(next, now); + return; + +weird: + /* We fell too far behind, got suspended, or the clock jumped... */ + ref_time = now; + ref_tstate = TSTATE; } /* Poll for timers - these the only external event we look for */ @@ -119,56 +119,56 @@ volatile bool z80_quit; bool z80_poll_external(void) { - uint64_t now; - static uint64_t next = 0; - int i; - bool sleepy = limit_speed; - static uint64_t next_check_tstate; - - if (z80_quit) - return true; /* Terminate CPU loop */ - - if (likely(TSTATE < next_check_tstate)) - return false; - - now = nstime(); - - if (unlikely(now >= next)) { - next = UINT64_MAX; - - for (i = 0; i < ntimers; i++) { - struct abctimer *t = &timers[i]; - if (t->period) { - uint64_t tnext = t->last + t->period; - if (unlikely(now >= tnext)) { - t->last += t->period; - if (unlikely(now >= tnext)) { - /* Missed tick(s), advance to skip missed */ - t->last = now - (now - t->last) % t->period; - tnext = t->last + t->period; - } - /* TSTATE value corresponding to t->last */ - t->ltst = TSTATE - (now - t->last)*tstate_per_ns; - t->func(); - sleepy = false; /* Just in case "now" is too far behind now */ - } - if (next > tnext) - next = tnext; /* The next event is closer than you thought */ - } + uint64_t now; + static uint64_t next = 0; + int i; + bool sleepy = limit_speed; + static uint64_t next_check_tstate; + + if (z80_quit) + return true; /* Terminate CPU loop */ + + if (likely(TSTATE < next_check_tstate)) + return false; + + now = nstime(); + + if (unlikely(now >= next)) { + next = UINT64_MAX; + + for (i = 0; i < ntimers; i++) { + struct abctimer *t = &timers[i]; + if (t->period) { + uint64_t tnext = t->last + t->period; + if (unlikely(now >= tnext)) { + t->last += t->period; + if (unlikely(now >= tnext)) { + /* Missed tick(s), advance to skip missed */ + t->last = now - (now - t->last) % t->period; + tnext = t->last + t->period; + } + /* TSTATE value corresponding to t->last */ + t->ltst = TSTATE - (now - t->last) * tstate_per_ns; + t->func(); + sleepy = false; /* Just in case "now" is too far behind now */ + } + if (next > tnext) + next = tnext; /* The next event is closer than you thought */ + } + } } - } - next_check_tstate = TSTATE + poll_tstate_period; - if (limit_speed) { - uint64_t next_ev = TSTATE + (next - now) * tstate_per_ns; - if (next_ev < next_check_tstate) - next_check_tstate = next_ev; - } + next_check_tstate = TSTATE + poll_tstate_period; + if (limit_speed) { + uint64_t next_ev = TSTATE + (next - now) * tstate_per_ns; + if (next_ev < next_check_tstate) + next_check_tstate = next_ev; + } - if (sleepy) - consider_napping(now, next); + if (sleepy) + consider_napping(now, next); - return false; + return false; } /* @@ -176,16 +176,15 @@ bool z80_poll_external(void) */ static void abc80_clock_tick(void) { - vsync_screen(); /* Also vertical retrace */ - z80_nmi(); + vsync_screen(); /* Also vertical retrace */ + z80_nmi(); } /* * ABC800: Clock interrupt through the CTC */ static uint8_t ctc_ctl[4], ctc_div[4]; -static struct z80_irq ctc_irq[4] = -{ +static struct z80_irq ctc_irq[4] = { IRQ(IRQ800_CTC0, NULL, NULL, NULL), IRQ(IRQ800_CTC1, NULL, NULL, NULL), IRQ(IRQ800_CTC2, NULL, NULL, NULL), @@ -195,7 +194,7 @@ static struct z80_irq ctc_irq[4] = static void abc800_clock_tick(void) { if ((ctc_ctl[3] & 0xc0) == 0x80) - z80_interrupt(&ctc_irq[3]); + z80_interrupt(&ctc_irq[3]); } /* @@ -203,56 +202,56 @@ static void abc800_clock_tick(void) */ void abc800_ctc_out(uint8_t port, uint8_t v) { - port &= 3; /* Get channel */ + port &= 3; /* Get channel */ - if (ctc_ctl[port] & 4) { - ctc_div[port] = v; - ctc_ctl[port] &= ~4; - return; - } + if (ctc_ctl[port] & 4) { + ctc_div[port] = v; + ctc_ctl[port] &= ~4; + return; + } - if ((v & 1) == 0) { - int i; - v &= ~7; - for (i = 0; i <= 3; i++) - ctc_irq[i].vector = v | (i << 1); - return; - } + if ((v & 1) == 0) { + int i; + v &= ~7; + for (i = 0; i <= 3; i++) + ctc_irq[i].vector = v | (i << 1); + return; + } - if (v & 2) - v = 1; /* Reset channel */ + if (v & 2) + v = 1; /* Reset channel */ - ctc_ctl[port] = v; + ctc_ctl[port] = v; } uint8_t abc800_ctc_in(uint8_t port) { - uint8_t v, div; - const struct abctimer *t; - - port &= 3; - t = ctc_timer[port]; - div = ctc_div[port]; - - if (!t) - return -1; - - if (limit_speed) { - /* Interpolate based on TSTATEs (virtual time) */ - v = ((int64_t)t->period - - (int64_t)(((TSTATE - t->ltst)*ns_per_tstate)) * div) / - t->period; - } else { - /* Interpolate based on nanoseconds (real time) */ - v = ((t->period - (nstime() - t->last)) * div) / t->period; - } - - return v; + uint8_t v, div; + const struct abctimer *t; + + port &= 3; + t = ctc_timer[port]; + div = ctc_div[port]; + + if (!t) + return -1; + + if (limit_speed) { + /* Interpolate based on TSTATEs (virtual time) */ + v = ((int64_t) t->period - + (int64_t) (((TSTATE - t->ltst) * ns_per_tstate)) * div) / + t->period; + } else { + /* Interpolate based on nanoseconds (real time) */ + v = ((t->period - (nstime() - t->last)) * div) / t->period; + } + + return v; } void abc800_ctc_init(void) { int i; for (i = 0; i < 4; i++) - z80_register_irq(&ctc_irq[i]); + z80_register_irq(&ctc_irq[i]); } @@ -6,18 +6,18 @@ #define COMPILER_H #ifdef HAVE_CONFIG_H -# include "config/config.h" +#include "config/config.h" #else -# error "Need compiler-specific hacks here" +#error "Need compiler-specific hacks here" #endif /* On Microsoft platforms we support multibyte character sets in filenames */ #define _MBCS 1 #ifdef HAVE_INTTYPES_H -# include <inttypes.h> +#include <inttypes.h> #else -# include "clib/inttypes.h" /* Ersatz header file */ +#include "clib/inttypes.h" /* Ersatz header file */ #endif /* These header files should pretty much always be included... */ @@ -31,51 +31,51 @@ #include <time.h> #ifdef HAVE_FCNTL_H -# include <fcntl.h> +#include <fcntl.h> #endif #ifdef HAVE_SYS_STAT_H -# include <sys/stat.h> +#include <sys/stat.h> #endif #ifdef HAVE_UNISTD_H -# include <unistd.h> +#include <unistd.h> #endif #ifdef HAVE_SYS_TYPES_H -# include <sys/types.h> +#include <sys/types.h> #endif #ifdef HAVE_DIRENT_H -# include <dirent.h> +#include <dirent.h> #endif #ifdef HAVE_VFORK_H -# include <vfork.h> +#include <vfork.h> #endif #ifdef HAVE_PATHS_H -# include <paths.h> +#include <paths.h> #endif #ifdef HAVE_IO_H -# include <io.h> +#include <io.h> #endif #ifdef HAVE_WINDOWS_H -# include <windows.h> +#include <windows.h> #endif #ifdef HAVE_DIRECT_H -# include <direct.h> +#include <direct.h> #endif -#include <SDL.h> /* This includes endian definitions */ +#include <SDL.h> /* This includes endian definitions */ #define WORDS_LITTLEENDIAN (SDL_BYTEORDER == SDL_LIL_ENDIAN) #define WORDS_BIGENDIAN (SDL_BYTEORDER == SDL_BIG_ENDIAN) -#ifndef __cplusplus /* C++ has false, true, bool as keywords */ -# ifdef HAVE_STDBOOL_H -# include <stdbool.h> -# else +#ifndef __cplusplus /* C++ has false, true, bool as keywords */ +#ifdef HAVE_STDBOOL_H +#include <stdbool.h> +#else /* This is sort of dangerous, since casts will behave different than casting to the standard boolean type. Always use !!, not (bool). */ typedef enum bool { false, true } bool; -# endif +#endif #endif /* @@ -107,29 +107,29 @@ typedef int mode_t; * Hack to support external-linkage inline functions */ #ifndef HAVE_STDC_INLINE -# ifdef __GNUC__ -# ifdef __GNUC_STDC_INLINE__ -# define HAVE_STDC_INLINE -# else -# define HAVE_GNU_INLINE -# endif -# elif defined(__GNUC_GNU_INLINE__) +#ifdef __GNUC__ +#ifdef __GNUC_STDC_INLINE__ +#define HAVE_STDC_INLINE +#else +#define HAVE_GNU_INLINE +#endif +#elif defined(__GNUC_GNU_INLINE__) /* Some other compiler implementing only GNU inline semantics? */ -# define HAVE_GNU_INLINE -# elif defined(__STDC_VERSION__) -# if __STDC_VERSION__ >= 199901L -# define HAVE_STDC_INLINE -# endif -# endif +#define HAVE_GNU_INLINE +#elif defined(__STDC_VERSION__) +#if __STDC_VERSION__ >= 199901L +#define HAVE_STDC_INLINE +#endif +#endif #endif #ifdef HAVE_STDC_INLINE -# define extern_inline inline +#define extern_inline inline #elif defined(HAVE_GNU_INLINE) -# define extern_inline extern inline -# define inline_prototypes +#define extern_inline extern inline +#define inline_prototypes #else -# define inline_prototypes +#define inline_prototypes #endif /* @@ -137,34 +137,34 @@ typedef int mode_t; * less likely to be taken. */ #if HAVE___BUILTIN_EXPECT -# define likely(x) __builtin_expect(!!(x), 1) -# define unlikely(x) __builtin_expect(!!(x), 0) +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) #else -# define likely(x) (!!(x)) -# define unlikely(x) (!!(x)) +#define likely(x) (!!(x)) +#define unlikely(x) (!!(x)) #endif /* * How to tell the compiler that a function doesn't return */ #ifdef HAVE_STDNORETURN_H -# include <stdnoreturn.h> -# define no_return noreturn void +#include <stdnoreturn.h> +#define no_return noreturn void #elif defined(HAVE_FUNC_ATTRIBUTE_NORETURN) -# define no_return void __attribute__((noreturn)) +#define no_return void __attribute__((noreturn)) #elif defined(_MSC_VER) -# define no_return __declspec(noreturn) void +#define no_return __declspec(noreturn) void #else -# define no_return void +#define no_return void #endif /* * How to tell the compiler that a function is pure arithmetic */ #ifdef HAVE_FUNC_ATTRIBUTE_CONST -# define const_func __attribute__((const)) +#define const_func __attribute__((const)) #else -# define const_func +#define const_func #endif /* @@ -174,68 +174,66 @@ typedef int mode_t; * by a pointer argument are *NOT* considered pure. */ #ifdef HAVE_FUNC_ATTRIBUTE_PURE -# define pure_func __attribute__((pure)) +#define pure_func __attribute__((pure)) #else -# define pure_func +#define pure_func #endif /* Determine probabilistically if something is a compile-time constant */ #ifdef HAVE___BUILTIN_CONSTANT_P -# define is_constant(x) __builtin_constant_p(x) +#define is_constant(x) __builtin_constant_p(x) #else -# define is_constant(x) false +#define is_constant(x) false #endif /* Simple atomic operations */ #ifdef __GNUC__ -# define atomic_load(p) __atomic_load_n((p), __ATOMIC_ACQUIRE) -# define atomic_store(p,v) __atomic_store_n((p), (v), __ATOMIC_RELEASE) -# define cmpxchg(p, e, d) \ +#define atomic_load(p) __atomic_load_n((p), __ATOMIC_ACQUIRE) +#define atomic_store(p,v) __atomic_store_n((p), (v), __ATOMIC_RELEASE) +#define cmpxchg(p, e, d) \ likely(__atomic_compare_exchange_n((p), (e), (d), false, \ __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) -# define xchg(p, v) \ +#define xchg(p, v) \ __atomic_exchange_n((p), (v), __ATOMIC_ACQ_REL) -# define barrier() __atomic_thread_fence(__ATOMIC_ACQ_REL) +#define barrier() __atomic_thread_fence(__ATOMIC_ACQ_REL) -# if defined(__i386__) || defined(__x86_64__) -static inline bool -atomic_test_set_bit(volatile unsigned int *p, unsigned int v) +#if defined(__i386__) || defined(__x86_64__) +static inline bool atomic_test_set_bit(volatile unsigned int *p, unsigned int v) { - bool b; - asm volatile("lock btsl %2,%0" - : "+m" (*p), "=@ccc" (b) - : "rN" (v) - : "memory"); - return b; + bool b; + asm volatile ("lock btsl %2,%0":"+m" (*p), "=@ccc"(b) + :"rN"(v) + :"memory"); + return b; } + static inline bool atomic_test_clear_bit(volatile unsigned int *p, unsigned int v) { - bool b; - asm volatile("lock btrl %2,%0" - : "+m" (*p), "=@ccc" (b) - : "rN" (v) - : "memory"); - return b; + bool b; + asm volatile ("lock btrl %2,%0":"+m" (*p), "=@ccc"(b) + :"rN"(v) + :"memory"); + return b; } -# else -static inline bool -atomic_test_set_bit(volatile unsigned int *p, unsigned int v) +#else +static inline bool atomic_test_set_bit(volatile unsigned int *p, unsigned int v) { - return (__atomic_fetch_or(p, 1U << v, __ATOMIC_ACQ_REL) >> v) & 1; + return (__atomic_fetch_or(p, 1U << v, __ATOMIC_ACQ_REL) >> v) & 1; } + static inline bool atomic_test_clear_bit(volatile unsigned int *p, unsigned int v) { - return (__atomic_fetch_and(p, ~(1U << v), __ATOMIC_ACQ_REL) >> v) & 1; + return (__atomic_fetch_and(p, ~(1U << v), __ATOMIC_ACQ_REL) >> v) & 1; } -# endif +#endif #define atomic_set_bit(p,v) ((void)atomic_test_set_bit(p,v)) #define atomic_clear_bit(p,v) ((void)atomic_test_clear_bit(p,v)) #else /* __GNUC__ */ -# error "Define atomic operations for your compiler here" +#error "Define atomic operations for your compiler here" #endif #endif /* COMPILER_H */ @@ -7,7 +7,7 @@ #include "console.h" #ifndef O_TEXT -# define O_TEXT 0 +#define O_TEXT 0 #endif static int redirect_stdio(const char *in, const char *out) @@ -18,39 +18,39 @@ static int redirect_stdio(const char *in, const char *out) fflush(NULL); - infd = open(in, O_RDWR|O_TEXT); + infd = open(in, O_RDWR | O_TEXT); if (infd >= 0) { - if (!out) - outfd = infd; + if (!out) + outfd = infd; } else { - infd = open(in, O_RDONLY|O_TEXT); + infd = open(in, O_RDONLY | O_TEXT); } if (infd < 0) { - err = -1; + err = -1; } else { - dup2(infd, STDIN_FILENO); + dup2(infd, STDIN_FILENO); } if (outfd < 0) { - out = out ? out : in; - outfd = open(out, O_RDWR|O_TEXT); - if (outfd < 0) - outfd = open(out, O_WRONLY|O_TEXT); + out = out ? out : in; + outfd = open(out, O_RDWR | O_TEXT); + if (outfd < 0) + outfd = open(out, O_WRONLY | O_TEXT); } if (outfd < 0) { - err = -1; + err = -1; } else { - dup2(outfd, STDOUT_FILENO); - dup2(outfd, STDERR_FILENO); + dup2(outfd, STDOUT_FILENO); + dup2(outfd, STDERR_FILENO); } if (infd > STDERR_FILENO) - close(infd); + close(infd); if (outfd != infd && outfd > STDERR_FILENO) - close(outfd); + close(outfd); return err; } @@ -63,10 +63,10 @@ void attach_console(void) atexit(detach_console); if (!AttachConsole(ATTACH_PARENT_PROCESS)) - return; /* Attach failed */ + return; /* Attach failed */ if (redirect_stdio("CONIN$", "CONOUT$")) - detach_console(); + detach_console(); /* We are probably displaying a command prompt, so start with a newline */ putchar('\n'); @@ -74,7 +74,7 @@ void attach_console(void) void detach_console(void) { - redirect_stdio("\\Device\\Null", NULL); + redirect_stdio("\\Device\\Null", NULL); FreeConsole(); } @@ -85,13 +85,13 @@ void attach_console(void) /* Do nothing */ } -# ifndef _PATH_DEVNULL -# define _PATH_DEVNULL "/dev/null" -# endif +#ifndef _PATH_DEVNULL +#define _PATH_DEVNULL "/dev/null" +#endif -# ifndef HAVE_SETSID -# define setsid() ((void)0) -# endif +#ifndef HAVE_SETSID +#define setsid() ((void)0) +#endif void detach_console(void) { @@ -102,9 +102,9 @@ void detach_console(void) pid = fork(); if (pid < 0) - return; + return; else if (pid > 0) - _exit(0); + _exit(0); setsid(); } @@ -16,313 +16,313 @@ const char *disk_path = "abcdisk"; /* This is the interpretation of an "out" command */ enum out_state { - disk_need_init, - disk_k0, - disk_k1, - disk_k2, - disk_k3, - disk_upload, - disk_download + disk_need_init, + disk_k0, + disk_k1, + disk_k2, + disk_k3, + disk_upload, + disk_download }; struct ctl_state { - enum out_state state; - uint8_t k[4]; - unsigned int secperclust; - unsigned int sectors; - uint8_t ilmsk, ilfac; /* Interlacing parameters */ - uint8_t new; /* "New addressing" */ - const char name[3]; - int out_ptr; /* Pointer within buffer for out data */ - int in_ptr; /* Pointer within buffer for in data */ - int status; /* Primary status */ - int aux_status; /* Auxilliary status */ - int notready_ctr; /* How many times are we not ready? */ - struct host_file *files[8]; /* File for this unit */ - unsigned char buf[4][256]; /* 4 buffers @ 256 bytes */ + enum out_state state; + uint8_t k[4]; + unsigned int secperclust; + unsigned int sectors; + uint8_t ilmsk, ilfac; /* Interlacing parameters */ + uint8_t new; /* "New addressing" */ + const char name[3]; + int out_ptr; /* Pointer within buffer for out data */ + int in_ptr; /* Pointer within buffer for in data */ + int status; /* Primary status */ + int aux_status; /* Auxilliary status */ + int notready_ctr; /* How many times are we not ready? */ + struct host_file *files[8]; /* File for this unit */ + unsigned char buf[4][256]; /* 4 buffers @ 256 bytes */ }; -static struct ctl_state mo_state = - { +static struct ctl_state mo_state = { .secperclust = 1, - .sectors = 40*1*16, + .sectors = 40 * 1 * 16, #if INTERLEAVE - .ilmsk = 15, - .ilfac = 7, + .ilmsk = 15, + .ilfac = 7, #endif - .name = "mo" - }; -static struct ctl_state mf_state = - { + .name = "mo" +}; + +static struct ctl_state mf_state = { .secperclust = 4, - .sectors = 80*2*16, - .name = "mf" - }; -static struct ctl_state sf_state = - { + .sectors = 80 * 2 * 16, + .name = "mf" +}; + +static struct ctl_state sf_state = { .secperclust = 4, - .sectors = (77*2-1)*26, /* Spår 0, sida 0 används ej */ - .name = "sf" - }; -static struct ctl_state hd_state = - { + .sectors = (77 * 2 - 1) * 26, /* Spår 0, sida 0 används ej */ + .name = "sf" +}; + +static struct ctl_state hd_state = { .secperclust = 32, - .new = 1, /* Actually irrelevant when secperclust = 32 */ - .sectors = 238*8*32, - .name = "hd" - }; + .new = 1, /* Actually irrelevant when secperclust = 32 */ + .sectors = 238 * 8 * 32, + .name = "hd" +}; -static struct ctl_state * const sel_to_state[64] = - { +static struct ctl_state *const sel_to_state[64] = { [36] = &hd_state, [44] = &mf_state, [45] = &mo_state, [46] = &sf_state, - }; +}; static inline unsigned int cur_sector(struct ctl_state *state) { - uint8_t k2 = state->k[2], k3 = state->k[3]; + uint8_t k2 = state->k[2], k3 = state->k[3]; - if (state->new) - return (k2 << 8) + k3; - else - return (((k2 << 3) + (k3 >> 5))*state->secperclust) + (k3 & 31); + if (state->new) + return (k2 << 8) + k3; + else + return (((k2 << 3) + (k3 >> 5)) * state->secperclust) + (k3 & 31); } static inline int file_pos_valid(struct ctl_state *state) { - return cur_sector(state) < state->sectors; + return cur_sector(state) < state->sectors; } static inline int file_pos(struct ctl_state *state) { - unsigned int ilmsk = state->ilmsk; - unsigned int sector = cur_sector(state); + unsigned int ilmsk = state->ilmsk; + unsigned int sector = cur_sector(state); - sector = (sector & ~ilmsk) | ((sector*state->ilfac) & ilmsk); + sector = (sector & ~ilmsk) | ((sector * state->ilfac) & ilmsk); - return sector << 8; + return sector << 8; } static void disk_reset_state(struct ctl_state *state) { - int i; + int i; - state->state = disk_k0; - state->status = state->aux_status = 0; - state->in_ptr = -1; - state->out_ptr = 0; - state->notready_ctr = 4; + state->state = disk_k0; + state->status = state->aux_status = 0; + state->in_ptr = -1; + state->out_ptr = 0; + state->notready_ctr = 4; - for (i = 0; i < 8; i++) - flush_file(state->files[i]); + for (i = 0; i < 8; i++) + flush_file(state->files[i]); } static void disk_init(struct ctl_state *state) { - char devname[4]; - int i; - - /* If any of these don't exist we simply report device not ready */ - 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'; - /* Try open RDWR first, then RDONLY, but don't create */ - state->files[i] = - open_host_file(HF_BINARY|HF_RETRY, disk_path, devname, O_RDWR); - - /* Try to memory-map the file */ - map_file(state->files[i], state->sectors << 8); + char devname[4]; + int i; + + /* If any of these don't exist we simply report device not ready */ + 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'; + /* Try open RDWR first, then RDONLY, but don't create */ + state->files[i] = + open_host_file(HF_BINARY | HF_RETRY, disk_path, devname, + O_RDWR); + + /* Try to memory-map the file */ + map_file(state->files[i], state->sectors << 8); + } } - } - disk_reset_state(state); + disk_reset_state(state); } static void do_next_command(struct ctl_state *state) { - struct host_file *hf = state->files[state->k[1] & 7]; - uint8_t *buf = state->buf[state->k[1] >> 6]; /* If applicable */ - - if ( state->k[0] & 0x01 ) { - /* READ SECTOR */ - if (hf->map) { - memcpy(buf, hf->map + file_pos(state), 256); - } else { - fseek(hf->f, file_pos(state), SEEK_SET); - fread(buf, 1, 256, hf->f); + struct host_file *hf = state->files[state->k[1] & 7]; + uint8_t *buf = state->buf[state->k[1] >> 6]; /* If applicable */ + + if (state->k[0] & 0x01) { + /* READ SECTOR */ + if (hf->map) { + memcpy(buf, hf->map + file_pos(state), 256); + } else { + fseek(hf->f, file_pos(state), SEEK_SET); + fread(buf, 1, 256, hf->f); + } + state->k[0] &= ~0x01; /* Command done */ } - state->k[0] &= ~0x01; /* Command done */ - } - if ( state->k[0] & 0x02 ) { - /* SECTOR TO HOST */ - state->in_ptr = 0; - state->state = disk_download; - state->k[0] &= ~0x02; /* Command done */ - return; - } - if ( state->k[0] & 0x04 ) { - /* SECTOR FROM HOST */ - state->state = disk_upload; - state->out_ptr = 0; - state->k[0] &= ~0x04; /* Command done */ - return; - } - if ( state->k[0] & 0x08 ) { - /* WRITE SECTOR */ - if (!file_wrok(hf)) { - state->status = 0x80; /* Error */ - state->aux_status = 0x40; /* Write protect */ - } else if (hf->map) { - memcpy(hf->map + file_pos(state), buf, 256); - } else { - clearerr(hf->f); - fseek(hf->f, file_pos(state), SEEK_SET); - fwrite(state->buf[state->k[1] >> 6], 1, 256, hf->f); - if (ferror(hf->f)) { - state->status = 0x08; /* Error */ - state->aux_status = 0x40; /* Write protect */ - } + if (state->k[0] & 0x02) { + /* SECTOR TO HOST */ + state->in_ptr = 0; + state->state = disk_download; + state->k[0] &= ~0x02; /* Command done */ + return; } - state->k[0] &= ~0x08; /* Command done */ - } - state->state = disk_k0; + if (state->k[0] & 0x04) { + /* SECTOR FROM HOST */ + state->state = disk_upload; + state->out_ptr = 0; + state->k[0] &= ~0x04; /* Command done */ + return; + } + if (state->k[0] & 0x08) { + /* WRITE SECTOR */ + if (!file_wrok(hf)) { + state->status = 0x80; /* Error */ + state->aux_status = 0x40; /* Write protect */ + } else if (hf->map) { + memcpy(hf->map + file_pos(state), buf, 256); + } else { + clearerr(hf->f); + fseek(hf->f, file_pos(state), SEEK_SET); + fwrite(state->buf[state->k[1] >> 6], 1, 256, hf->f); + if (ferror(hf->f)) { + state->status = 0x08; /* Error */ + state->aux_status = 0x40; /* Write protect */ + } + } + state->k[0] &= ~0x08; /* Command done */ + } + state->state = disk_k0; } void disk_reset(void) { - int i; - struct ctl_state *state; - for (i = 0; i < 64; i++) { - state = sel_to_state[i]; - if (state && state->state != disk_need_init) - disk_reset_state(state); - } + int i; + struct ctl_state *state; + for (i = 0; i < 64; i++) { + state = sel_to_state[i]; + if (state && state->state != disk_need_init) + disk_reset_state(state); + } } void disk_out(int sel, int port, int value) { - struct ctl_state *state = sel_to_state[sel]; - - if (!state) - return; /* Not a disk drive */ - - if ( state->state == disk_need_init ) - disk_init(state); - - switch ( port ) { - case 0: - switch ( state->state ) { - case disk_k0: - case disk_k1: - case disk_k2: - state->status = state->aux_status = 0; - state->k[state->state - disk_k0] = value; - state->state++; - break; - case disk_k3: - state->status = state->aux_status = 0; - state->k[3] = value; - state->state = disk_k0; - - if (tracing(TRACE_DISK)) { - fprintf(tracef, "%s%d: command %02X %02X %02X %02X\n", - state->name, state->k[1] & 7, - state->k[0], state->k[1], state->k[2], state->k[3]); - fprintf(tracef, "PC = %04X BC = %04X DE = %04X HL = %04X\n", - REG_PC, REG_BC, REG_DE, REG_HL); - } - - /* Bad drive/sector? */ - if ( !state->files[state->k[1] & 7] ) { - state->status = 0x08; /* Error */ - state->aux_status = 0x80; /* Device not ready */ - } else if ( !file_pos_valid(state) ) { - state->status = 0x08; /* Error */ - state->aux_status = 0x10; /* Seek error */ - } else { - do_next_command(state); - } - break; - case disk_upload: - state->buf[state->k[1] >> 6][state->out_ptr++] = value; - if (tracing(TRACE_DISK)) - fprintf(tracef, "%02X", value); - if ( state->out_ptr >= 256 ) { - if (tracing(TRACE_DISK)) - fprintf(tracef, "\nPC = %04X BC = %04X DE = %04X HL = %04X\n", - REG_PC, REG_BC, REG_DE, REG_HL); - do_next_command(state); - } - break; - case disk_download: - break; - case disk_need_init: - abort(); /* Should never happen */ - break; + struct ctl_state *state = sel_to_state[sel]; + + if (!state) + return; /* Not a disk drive */ + + if (state->state == disk_need_init) + disk_init(state); + + switch (port) { + case 0: + switch (state->state) { + case disk_k0: + case disk_k1: + case disk_k2: + state->status = state->aux_status = 0; + state->k[state->state - disk_k0] = value; + state->state++; + break; + case disk_k3: + state->status = state->aux_status = 0; + state->k[3] = value; + state->state = disk_k0; + + if (tracing(TRACE_DISK)) { + fprintf(tracef, "%s%d: command %02X %02X %02X %02X\n", + state->name, state->k[1] & 7, + state->k[0], state->k[1], state->k[2], state->k[3]); + fprintf(tracef, "PC = %04X BC = %04X DE = %04X HL = %04X\n", + REG_PC, REG_BC, REG_DE, REG_HL); + } + + /* Bad drive/sector? */ + if (!state->files[state->k[1] & 7]) { + state->status = 0x08; /* Error */ + state->aux_status = 0x80; /* Device not ready */ + } else if (!file_pos_valid(state)) { + state->status = 0x08; /* Error */ + state->aux_status = 0x10; /* Seek error */ + } else { + do_next_command(state); + } + break; + case disk_upload: + state->buf[state->k[1] >> 6][state->out_ptr++] = value; + if (tracing(TRACE_DISK)) + fprintf(tracef, "%02X", value); + if (state->out_ptr >= 256) { + if (tracing(TRACE_DISK)) + fprintf(tracef, + "\nPC = %04X BC = %04X DE = %04X HL = %04X\n", + REG_PC, REG_BC, REG_DE, REG_HL); + do_next_command(state); + } + break; + case disk_download: + break; + case disk_need_init: + abort(); /* Should never happen */ + break; + } + break; + + case 2: /* Start command */ + case 4: /* Reset */ + if (tracing(TRACE_DISK)) { + fprintf(tracef, "OUT %d/%d : ", sel, port); + fprintf(tracef, "PC = %04X BC = %04X DE = %04X HL = %04X\n", + REG_PC, REG_BC, REG_DE, REG_HL); + } + disk_reset(); + break; + + default: + /* Nothing */ + break; } - break; - - case 2: /* Start command */ - case 4: /* Reset */ - if (tracing(TRACE_DISK)) { - fprintf(tracef, "OUT %d/%d : ", sel, port); - fprintf(tracef, "PC = %04X BC = %04X DE = %04X HL = %04X\n", - REG_PC, REG_BC, REG_DE, REG_HL); - } - disk_reset(); - break; - - default: - /* Nothing */ - break; - } } int disk_in(int sel, int port) { - struct ctl_state *state = sel_to_state[sel]; - uint8_t v = 0xff; - - if (!state) - return 0xff; /* Not a disk drive */ - - if ( state->state == disk_need_init ) - disk_init(state); - - switch ( port ) { - case 0: - if ( state->in_ptr >= 0 ) { - v = state->buf[state->k[1] >> 6][state->in_ptr++]; - if ( state->in_ptr >= 256 ) { - state->in_ptr = -1; - do_next_command(state); - } - } else { - v = state->aux_status; + struct ctl_state *state = sel_to_state[sel]; + uint8_t v = 0xff; + + if (!state) + return 0xff; /* Not a disk drive */ + + if (state->state == disk_need_init) + disk_init(state); + + switch (port) { + case 0: + if (state->in_ptr >= 0) { + v = state->buf[state->k[1] >> 6][state->in_ptr++]; + if (state->in_ptr >= 256) { + state->in_ptr = -1; + do_next_command(state); + } + } else { + v = state->aux_status; + } + break; + + case 1: /* Controller status */ + if (state->notready_ctr) { + state->notready_ctr--; + v = 0x80; + } else { + v = 0x01 | state->status | ((state->state == disk_k0) ? 0x80 : 0); + } + break; + + default: + break; } - break; - - case 1: /* Controller status */ - if (state->notready_ctr) { - state->notready_ctr--; - v = 0x80; - } else { - v = 0x01 | state->status | ((state->state == disk_k0) ? 0x80 : 0); + + if (tracing(TRACE_DISK)) { + fprintf(tracef, "IN %d/%d: %02X : ", sel, port, v); + fprintf(tracef, "PC = %04X BC = %04X DE = %04X HL = %04X\n", + REG_PC, REG_BC, REG_DE, REG_HL); } - break; - - default: - break; - } - - if (tracing(TRACE_DISK)) { - fprintf(tracef, "IN %d/%d: %02X : ", sel, port, v); - fprintf(tracef, "PC = %04X BC = %04X DE = %04X HL = %04X\n", - REG_PC, REG_BC, REG_DE, REG_HL); - } - return v; + return v; } @@ -12,14 +12,14 @@ static int filelist_add(struct file_list *list, char *name) node = malloc(sizeof *node); if (!node) - return -1; + return -1; node->name = name; node->next = NULL; if (list->last) - list->last->next = node; + list->last->next = node; else - list->first = node; + list->first = node; list->last = node; return 0; @@ -30,10 +30,10 @@ void filelist_add_file(struct file_list *list, const char *filename) char *name = strdup(filename); if (!name) - return; + return; if (filelist_add(list, name)) - free(name); + free(name); } void filelist_add_list(struct file_list *list, const char *listfile) @@ -45,31 +45,31 @@ void filelist_add_list(struct file_list *list, const char *listfile) listpath = strdup(listfile); if (!listpath) - return; + return; p = (char *)host_strip_path(listpath); - *p = '\0'; /* Remove the actual filename */ + *p = '\0'; /* Remove the actual filename */ dirsep = ""; - if (p > listpath && !is_path_separator(p[-1])) - dirsep = "/"; + if (p > listpath && !is_path_separator(p[-1])) + dirsep = "/"; f = fopen(listfile, "rt"); if (!f) { - free(listpath); - return; + free(listpath); + return; } while (fgets(linebuf, sizeof linebuf, f)) { - p = strchr(linebuf, '\n'); - if (p) - *p = '\0'; + p = strchr(linebuf, '\n'); + if (p) + *p = '\0'; - asprintf(&p, "%s%s%s", listpath, dirsep, linebuf); - if (!p) - continue; + asprintf(&p, "%s%s%s", listpath, dirsep, linebuf); + if (!p) + continue; - if (filelist_add(list, p)) - free(p); + if (filelist_add(list, p)) + free(p); } fclose(f); @@ -81,9 +81,9 @@ void filelist_free(struct file_list *list) struct file_node *node, *nx; for (node = list->first; node; node = nx) { - nx = node->next; - free(node->name); - free(node); + nx = node->next; + free(node->name); + free(node); } list->first = list->last = NULL; } @@ -94,11 +94,11 @@ char *filelist_pop(struct file_list *list) struct file_node *node = list->first; if (node) { - filename = node->name; - list->first = node->next; - if (list->last == node) - list->last = NULL; - free(node); + filename = node->name; + list->first = node->next; + if (list->last == node) + list->last = NULL; + free(node); } return filename; @@ -8,242 +8,242 @@ const char *fileop_path = "abcdir"; #define BUF_SIZE 512 static enum { - st_op, /* Receiving command */ + st_op, /* Receiving command */ st_open, st_read, - st_print, /* Before data */ - st_print2, /* After data */ + st_print, /* Before data */ + st_print2, /* After data */ st_seek, st_rename, st_delete, st_pread, - st_pwrite, /* Before data */ - st_pwrite2, /* After data */ + st_pwrite, /* Before data */ + st_pwrite2, /* After data */ st_blksize } state = st_op; struct file { - struct host_file *hf; - bool binary; + struct host_file *hf; + bool binary; }; -static struct file filemap[65536]; /* Massive waste of space, yes... */ +static struct file filemap[65536]; /* Massive waste of space, yes... */ -static unsigned int blksize; /* System block size */ +static unsigned int blksize; /* System block size */ static inline bool file_open(uint16_t ix) { - return !!filemap[ix].hf; + return ! !filemap[ix].hf; } static inline bool file_binary(uint16_t ix) { - return filemap[ix].binary; + return filemap[ix].binary; } static inline enum host_file_mode file_mode(uint16_t ix) { - return filemap[ix].hf->mode; + return filemap[ix].hf->mode; } static unsigned int byte_count = 4; static unsigned char cmd[4]; static unsigned char *bytep = cmd; -static unsigned char data[65536+2]; +static unsigned char data[65536 + 2]; static void trace_data(const void *data, size_t len, const char *pfx) { - size_t i; - const uint8_t *dp = data; + size_t i; + const uint8_t *dp = data; - if (!tracing(TRACE_PR)) - return; + if (!tracing(TRACE_PR)) + return; - fprintf(tracef, "PR: %-5s: ", pfx); + fprintf(tracef, "PR: %-5s: ", pfx); - for (i = 0; i < 16; i++) { - if (i >= len) - fprintf(tracef, " "); - else - fprintf(tracef, "%02x", dp[i]); + for (i = 0; i < 16; i++) { + if (i >= len) + fprintf(tracef, " "); + else + fprintf(tracef, "%02x", dp[i]); - putc(i == 8 ? '-' : ' ', tracef); - } + putc(i == 8 ? '-' : ' ', tracef); + } - fprintf(tracef, "%c [", (len > 16) ? '+' : ' '); + fprintf(tracef, "%c [", (len > 16) ? '+' : ' '); - for (i = 0; i < 16; i++) { - char c; + for (i = 0; i < 16; i++) { + char c; - c = (i >= len) ? ' ' : dp[i]; - if (c < 32 || c > 126) - c = '.'; + c = (i >= len) ? ' ' : dp[i]; + if (c < 32 || c > 126) + c = '.'; - putc(c, tracef); - } - putc(']', tracef); - if (len > 16) - fprintf(tracef, "+ (%lu bytes)", (unsigned long)len); - putc('\n', tracef); + putc(c, tracef); + } + putc(']', tracef); + if (len > 16) + fprintf(tracef, "+ (%lu bytes)", (unsigned long)len); + putc('\n', tracef); } static void pr_send(const void *buf, size_t len) { - trace_data(buf, len, "SEND"); - abcprint_send(buf, len); + trace_data(buf, len, "SEND"); + abcprint_send(buf, len); } static void send_reply(int status) { - unsigned char reply[4]; + unsigned char reply[4]; - reply[0] = 0xff; - reply[1] = cmd[0]; - reply[2] = cmd[1]; - reply[3] = status; + reply[0] = 0xff; + reply[1] = cmd[0]; + reply[2] = cmd[1]; + reply[3] = status; - pr_send(reply, 4); + pr_send(reply, 4); } /* Returns the status code, use send_reply(do_close(ix)) if reply desired */ static int do_close(uint16_t ix) { - if (file_open(ix)) { - close_file(&filemap[ix].hf); - return 0; - } else { - return 128+45; /* "Fel logiskt filnummer" */ - } + if (file_open(ix)) { + close_file(&filemap[ix].hf); + return 0; + } else { + return 128 + 45; /* "Fel logiskt filnummer" */ + } } static void do_closeall(bool reply) { - int ix; + int ix; - for (ix = 0; ix <= 65535; ix++) - if (file_open(ix)) - do_close(ix); + for (ix = 0; ix <= 65535; ix++) + if (file_open(ix)) + do_close(ix); - if (reply) - send_reply(0); + if (reply) + send_reply(0); } static void do_open(uint16_t ix, char *name) { - int err; - char path_buf[64]; - int openflags; - enum host_file_mode mode; - struct host_file *hf; - - if (!fileop_path) { - send_reply(128+42); /* Skivan ej klar */ - return; - } - - do_close(ix); - - unmangle_filename(path_buf, name); - - if (!path_buf[0]) { - /* Empty filename (readdir) */ - - mode = ((cmd[0] & 3) == 0) ? HF_DIRECTORY : HF_FAIL; - openflags = 0; - } else { - /* Actual filename */ - - mode = HF_BINARY; - mode |= (cmd[0] & 2) ? 0 : HF_RETRY; - openflags = (cmd[0] & 2) ? (O_RDWR|O_TRUNC|O_CREAT) : O_RDWR; - } - - hf = open_host_file(mode, fileop_path, path_buf, openflags); - filemap[ix].hf = hf; - filemap[ix].binary = cmd[0] & 1; - - switch (errno) { -#if 0 /* Enable this? */ - case EACCES: - err = 128+39; - break; - case EROFS: - err = 128+43; - break; - case EIO: - case ENOTDIR: - err = 128+48; - break; + int err; + char path_buf[64]; + int openflags; + enum host_file_mode mode; + struct host_file *hf; + + if (!fileop_path) { + send_reply(128 + 42); /* Skivan ej klar */ + return; + } + + do_close(ix); + + unmangle_filename(path_buf, name); + + if (!path_buf[0]) { + /* Empty filename (readdir) */ + + mode = ((cmd[0] & 3) == 0) ? HF_DIRECTORY : HF_FAIL; + openflags = 0; + } else { + /* Actual filename */ + + mode = HF_BINARY; + mode |= (cmd[0] & 2) ? 0 : HF_RETRY; + openflags = (cmd[0] & 2) ? (O_RDWR | O_TRUNC | O_CREAT) : O_RDWR; + } + + hf = open_host_file(mode, fileop_path, path_buf, openflags); + filemap[ix].hf = hf; + filemap[ix].binary = cmd[0] & 1; + + switch (errno) { +#if 0 /* Enable this? */ + case EACCES: + err = 128 + 39; + break; + case EROFS: + err = 128 + 43; + break; + case EIO: + case ENOTDIR: + err = 128 + 48; + break; #endif - default: - err = 128+21; - break; - } + default: + err = 128 + 21; + break; + } - send_reply(hf ? 0 : err); + send_reply(hf ? 0 : err); } static void do_read_block(uint16_t ix, uint16_t len) { - struct host_file *hf = filemap[ix].hf; - int err; - int dlen; - - if (!file_open(ix)) { - send_reply(128+45); - return; - } - if (file_mode(ix) == HF_DIRECTORY) { - send_reply(128+37); /* Felaktigt recordformat */ - return; - } - - clearerr(hf->f); - dlen = fread(data+2, 1, len, hf->f); - if (dlen == 0) { - if (ferror(hf->f)) { - switch (errno) { - case EBADF: - err = 128+44; /* Logisk fil ej öppen */ - break; - case EIO: - err = 128+35; /* Checksummafel vid läsning */ - break; - default: - err = 128+48; /* Fel i biblioteket */ - break; - } - } else { - /* EOF */ - err = 128+34; /* Slut på filen */ + struct host_file *hf = filemap[ix].hf; + int err; + int dlen; + + if (!file_open(ix)) { + send_reply(128 + 45); + return; + } + if (file_mode(ix) == HF_DIRECTORY) { + send_reply(128 + 37); /* Felaktigt recordformat */ + return; + } + + clearerr(hf->f); + dlen = fread(data + 2, 1, len, hf->f); + if (dlen == 0) { + if (ferror(hf->f)) { + switch (errno) { + case EBADF: + err = 128 + 44; /* Logisk fil ej öppen */ + break; + case EIO: + err = 128 + 35; /* Checksummafel vid läsning */ + break; + default: + err = 128 + 48; /* Fel i biblioteket */ + break; + } + } else { + /* EOF */ + err = 128 + 34; /* Slut på filen */ + } + send_reply(err); + return; } - send_reply(err); - return; - } - send_reply(0); + send_reply(0); - data[0] = len; - data[1] = len >> 8; - pr_send(data, len+2); + data[0] = len; + data[1] = len >> 8; + pr_send(data, len + 2); } /* Common routine for all commands which need seek */ static int seeker(uint16_t ix, uint64_t pos) { - struct host_file *hf = filemap[ix].hf; - int err; - - if (!file_open(ix)) { - err = 128+45; /* Fel logiskt filnummer */ - } else if (file_mode(ix) == HF_DIRECTORY) { - err = 128+37; /* Felaktigt recordformat */ - } else if (fseek(hf->f, pos, SEEK_SET) == -1) { - err = 128+38; /* Recordnummer utanför filen */ - } else { - err = 0; - } - - return err; + struct host_file *hf = filemap[ix].hf; + int err; + + if (!file_open(ix)) { + err = 128 + 45; /* Fel logiskt filnummer */ + } else if (file_mode(ix) == HF_DIRECTORY) { + err = 128 + 37; /* Felaktigt recordformat */ + } else if (fseek(hf->f, pos, SEEK_SET) == -1) { + err = 128 + 38; /* Recordnummer utanför filen */ + } else { + err = 0; + } + + return err; } static void do_seek(uint16_t ix, uint64_t pos) @@ -257,159 +257,159 @@ static void do_pread(uint16_t ix, uint16_t blk) err = seeker(ix, blksize * (long)blk); if (err) - send_reply(err); + send_reply(err); else - do_read_block(ix, blksize); + do_read_block(ix, blksize); } static void do_input(uint16_t ix) { - struct host_file *hf = filemap[ix].hf; - int err; - char data1[255+2]; /* Max number of bytes to return + 2 */ - char *p, *q, c; - int dlen; - struct dirent *de; - struct stat st; - - if (!file_open(ix)) { - send_reply(128+45); - return; - } - - if (file_mode(ix) != HF_DIRECTORY) { - clearerr(hf->f); - if (!fgets((char *)data, sizeof data, hf->f)) { - if (ferror(hf->f)) { - switch (errno) { - case EBADF: - err = 128+44; /* Logisk fil ej öppen */ - break; - case EIO: - err = 128+35; /* Checksummafel vid läsning */ - break; - default: - err = 128+48; /* Fel i biblioteket */ - break; - } - } else { - /* EOF */ - err = 128+34; /* Slut på filen */ - } + struct host_file *hf = filemap[ix].hf; + int err; + char data1[255 + 2]; /* Max number of bytes to return + 2 */ + char *p, *q, c; + int dlen; + struct dirent *de; + struct stat st; + + if (!file_open(ix)) { + send_reply(128 + 45); + return; + } + + if (file_mode(ix) != HF_DIRECTORY) { + clearerr(hf->f); + if (!fgets((char *)data, sizeof data, hf->f)) { + if (ferror(hf->f)) { + switch (errno) { + case EBADF: + err = 128 + 44; /* Logisk fil ej öppen */ + break; + case EIO: + err = 128 + 35; /* Checksummafel vid läsning */ + break; + default: + err = 128 + 48; /* Fel i biblioteket */ + break; + } + } else { + /* EOF */ + err = 128 + 34; /* Slut på filen */ + } + } else { + /* Strip CR and change LF -> CR LF */ + if (!file_binary(ix)) { + for (p = (char *)data, q = data1 + 2; (c = *p); p++) { + if (q == &data1[sizeof data1]) + break; + switch (c) { + case '\r': + break; + case '\n': + *q++ = '\r'; + /* fall through */ + default: + *q++ = c; + break; + } + } + dlen = q - (data1 + 2); + } else { + dlen = strnlen(data1 + 2, sizeof data1 - 2); + } + err = 0; + } + } else if (hf->d) { + while ((de = readdir(hf->d))) { + if (de->d_name[0] != '.' && + (dlen = mangle_for_readdir(data1 + 2, de->d_name))) { + if (!stat_file(fileop_path, de->d_name, &st) && + S_ISREG(st.st_mode)) + break; + } + } + if (de) { + unsigned long blocks, pad; + blocks = (st.st_size + blksize - 1) / blksize; + pad = blksize * blocks - st.st_size; + /* pad = unused bytes in the last block */ + dlen += sprintf(data1 + 2 + dlen, ",%lu,%lu\r\n", blocks, pad); + err = 0; + } else { + err = 128 + 34; + } } else { - /* Strip CR and change LF -> CR LF */ - if (!file_binary(ix)) { - for (p = (char *)data, q = data1+2 ; (c = *p) ; p++) { - if (q == &data1[sizeof data1]) - break; - switch (c) { - case '\r': - break; - case '\n': - *q++ = '\r'; - /* fall through */ - default: - *q++ = c; - break; - } - } - dlen = q - (data1+2); - } else { - dlen = strnlen(data1+2, sizeof data1-2); - } - err = 0; + err = 128 + 44; + } + + send_reply(err); + if (!err) { + data1[0] = dlen; + data1[1] = dlen >> 8; + pr_send(data1, dlen + 2); } - } else if (hf->d) { - while ( (de = readdir(hf->d)) ) { - if (de->d_name[0] != '.' && - (dlen = mangle_for_readdir(data1+2, de->d_name))) { - if (!stat_file(fileop_path, de->d_name, &st) && - S_ISREG(st.st_mode)) - break; - } - } - if (de) { - unsigned long blocks, pad; - blocks = (st.st_size + blksize - 1)/blksize; - pad = blksize*blocks - st.st_size; - /* pad = unused bytes in the last block */ - dlen += sprintf(data1+2+dlen, ",%lu,%lu\r\n", blocks, pad); - err = 0; - } else { - err = 128+34; - } - } else { - err = 128+44; - } - - send_reply(err); - if (!err) { - data1[0] = dlen; - data1[1] = dlen >> 8; - pr_send(data1, dlen+2); - } } static void do_print(uint16_t ix, uint16_t len, bool eolcvt) { - struct host_file *hf = filemap[ix].hf; - int err; + struct host_file *hf = filemap[ix].hf; + int err; #ifdef __WIN32__ - /* ABC sends CR LF as line endings, which matches Windows */ - eolcvt = false; + /* ABC sends CR LF as line endings, which matches Windows */ + eolcvt = false; #endif - if (!file_open(ix)) { - err = 128+45; - } else if (file_mode(ix) == HF_DIRECTORY) { - err = 128+39; /* Directories are readonly */ - } else { - clearerr(hf->f); - if (len) { - if (eolcvt && !file_binary(ix)) { - int i; - for (i = 0; i < len-1; i++) { - char c = data[i]; - if (c == '\r') - continue; /* CR LF -> LF */ - else - putc(c, hf->f); - } - putc(data[len-1], hf->f); /* Last char is always verbatim */ - } else { - fwrite(data, 1, len, hf->f); - } - fflush(hf->f); - } - - if (!ferror(hf->f)) { - err = 0; + if (!file_open(ix)) { + err = 128 + 45; + } else if (file_mode(ix) == HF_DIRECTORY) { + err = 128 + 39; /* Directories are readonly */ } else { - switch (errno) { - case EACCES: - err = 128+39; /* Filen skrivskyddad */ - break; - case ENOSPC: - case EFBIG: - err = 128+41; /* Skivan full */ - break; - case EROFS: - err = 128+43; /* Skivan skrivskyddad */ - break; - case EBADF: - err = 128+44; /* Logisk fil ej öppen */ - break; - case EIO: - err = 128+36; /* Checksummafel vid skrivning */ - break; - default: - err = 128+48; /* Fel i biblioteket */ - break; - } + clearerr(hf->f); + if (len) { + if (eolcvt && !file_binary(ix)) { + int i; + for (i = 0; i < len - 1; i++) { + char c = data[i]; + if (c == '\r') + continue; /* CR LF -> LF */ + else + putc(c, hf->f); + } + putc(data[len - 1], hf->f); /* Last char is always verbatim */ + } else { + fwrite(data, 1, len, hf->f); + } + fflush(hf->f); + } + + if (!ferror(hf->f)) { + err = 0; + } else { + switch (errno) { + case EACCES: + err = 128 + 39; /* Filen skrivskyddad */ + break; + case ENOSPC: + case EFBIG: + err = 128 + 41; /* Skivan full */ + break; + case EROFS: + err = 128 + 43; /* Skivan skrivskyddad */ + break; + case EBADF: + err = 128 + 44; /* Logisk fil ej öppen */ + break; + case EIO: + err = 128 + 36; /* Checksummafel vid skrivning */ + break; + default: + err = 128 + 48; /* Fel i biblioteket */ + break; + } + } } - } - send_reply(err); + send_reply(err); } static void do_pwrite(uint16_t ix, uint16_t blk) @@ -418,305 +418,303 @@ static void do_pwrite(uint16_t ix, uint16_t blk) err = seeker(ix, blksize * (long)blk); if (err) - send_reply(err); + send_reply(err); else - do_print(ix, blksize, false); + do_print(ix, blksize, false); } static void do_rename(const char *files) { - char old_name[64], new_name[64]; - int err; + char old_name[64], new_name[64]; + int err; - unmangle_filename(old_name, files); - unmangle_filename(new_name, files+11); + unmangle_filename(old_name, files); + unmangle_filename(new_name, files + 11); - if (!rename(old_name, new_name)) { - err = 0; - } else { - switch (errno) { - case EACCES: - err = 128+39; /* Filen skrivskyddad */ - break; - case EROFS: - err = 128+43; /* Skivan skrivskyddad */ - break; - case ENOENT: - err = 128+21; /* Hittar ej filen */ - break; - case ENOSPC: - err = 128+41; /* Skivan full */ - break; - case EISDIR: - err = 128+40; /* Filen raderingsskyddad */ - break; - case EIO: - err = 128+36; /* Checksummafel vid skrivning */ - break; - default: - err = 128+48; /* Fel i biblioteket */ - break; + if (!rename(old_name, new_name)) { + err = 0; + } else { + switch (errno) { + case EACCES: + err = 128 + 39; /* Filen skrivskyddad */ + break; + case EROFS: + err = 128 + 43; /* Skivan skrivskyddad */ + break; + case ENOENT: + err = 128 + 21; /* Hittar ej filen */ + break; + case ENOSPC: + err = 128 + 41; /* Skivan full */ + break; + case EISDIR: + err = 128 + 40; /* Filen raderingsskyddad */ + break; + case EIO: + err = 128 + 36; /* Checksummafel vid skrivning */ + break; + default: + err = 128 + 48; /* Fel i biblioteket */ + break; + } } - } - send_reply(err); + send_reply(err); } static void do_delete(const char *file) { - char path_buf[64]; - int err; + char path_buf[64]; + int err; - unmangle_filename(path_buf, file); + unmangle_filename(path_buf, file); - if (!remove(path_buf)) { - err = 0; - } else { - switch (errno) { - case EROFS: - err = 128+43; /* Skivan skrivskyddad */ - break; - case ENOENT: - err = 128+21; /* Hittar ej filen */ - break; - case ENOSPC: - err = 128+41; /* Skivan full */ - break; - case EISDIR: - case EPERM: - case EACCES: - err = 128+40; /* Filen raderingsskyddad */ - break; - case EIO: - err = 128+36; /* Checksummafel vid skrivning */ - break; - default: - err = 128+48; /* Fel i biblioteket */ - break; + if (!remove(path_buf)) { + err = 0; + } else { + switch (errno) { + case EROFS: + err = 128 + 43; /* Skivan skrivskyddad */ + break; + case ENOENT: + err = 128 + 21; /* Hittar ej filen */ + break; + case ENOSPC: + err = 128 + 41; /* Skivan full */ + break; + case EISDIR: + case EPERM: + case EACCES: + err = 128 + 40; /* Filen raderingsskyddad */ + break; + case EIO: + err = 128 + 36; /* Checksummafel vid skrivning */ + break; + default: + err = 128 + 48; /* Fel i biblioteket */ + break; + } } - } - send_reply(err); + send_reply(err); } typedef union argbuf { - uint8_t b[32]; - char c[32]; - uint64_t q; + uint8_t b[32]; + char c[32]; + uint64_t q; } argbuf; -static inline uint64_t get_qword(const argbuf *v) +static inline uint64_t get_qword(const argbuf * v) { #ifdef WORDS_LITTLEENDIAN - return v->q; + return v->q; #else - return v->b[0] + - ((uint64_t)v->b[1] << 8) + - ((uint64_t)v->b[2] << 16) + - ((uint64_t)v->b[3] << 24) + - ((uint64_t)v->b[4] << 32) + - ((uint64_t)v->b[5] << 40) + - ((uint64_t)v->b[6] << 48) + - ((uint64_t)v->b[7] << 56); + return v->b[0] + + ((uint64_t) v->b[1] << 8) + + ((uint64_t) v->b[2] << 16) + + ((uint64_t) v->b[3] << 24) + + ((uint64_t) v->b[4] << 32) + + ((uint64_t) v->b[5] << 40) + + ((uint64_t) v->b[6] << 48) + ((uint64_t) v->b[7] << 56); #endif } bool file_op(unsigned char c) { - static argbuf argbuf; - static unsigned int datalen = 0; - uint16_t ix; - uint64_t arg; - - *bytep++ = c; - if (--byte_count) - return true; /* More to do... */ - - /* Otherwise, we have a full deck of *something* */ - ix = (cmd[3] << 8) + cmd[2]; - arg = get_qword(&argbuf); - bytep = argbuf.b; - - switch (state) { - case st_op: - switch (cmd[0]) { - case 0xA0: /* OPEN TEXT */ - case 0xA1: /* OPEN BINARY */ - case 0xA2: /* PREPARE TEXT */ - case 0xA3: /* PREPARE BINARY */ - byte_count = 11; - state = st_open; - break; - - case 0xA4: /* INPUT */ - do_input(ix); - break; - - case 0xA5: /* READ BLOCK */ - byte_count = 2; - state = st_read; - break; - - case 0xA6: /* PRINT */ - case 0xB9: /* PUT */ - byte_count = 2; - state = st_print; - break; - - case 0xA7: /* CLOSE */ - send_reply(do_close(ix)); - break; - - case 0xA8: /* CLOSEALL */ - do_closeall(true); - break; - - case 0xA9: /* INIT */ - blksize = 253; - do_closeall(false); - break; - - case 0xAE: /* SET BLOCK SIZE */ - case 0xAF: /* INITSZ */ - byte_count = 2; - state = st_blksize; - break; - - case 0xAA: /* RENAME */ - byte_count = 22; - state = st_rename; - break; - - case 0xAB: /* DELETE */ - byte_count = 11; - state = st_delete; - break; - - case 0xAC: /* PREAD */ - byte_count = 2; - state = st_pread; - break; - - case 0xAD: /* PWRITE */ - byte_count = 2; - state = st_pwrite; - break; - - case 0xB0: /* SEEK0 == REWIND */ - do_seek(ix, 0); - break; - - case 0xB1: /* SEEK1 */ - case 0xB2: /* SEEK2 */ - case 0xB3: /* SEEK3 */ - case 0xB4: /* SEEK4 */ - case 0xB5: /* SEEK5 */ - case 0xB6: /* SEEK6 */ - case 0xB7: /* SEEK7 */ - case 0xB8: /* SEEK8 */ - byte_count = cmd[0] - 0xb0; - state = st_seek; - break; - - default: - /* Unknown command */ - send_reply(128+11); - break; + static argbuf argbuf; + static unsigned int datalen = 0; + uint16_t ix; + uint64_t arg; + + *bytep++ = c; + if (--byte_count) + return true; /* More to do... */ + + /* Otherwise, we have a full deck of *something* */ + ix = (cmd[3] << 8) + cmd[2]; + arg = get_qword(&argbuf); + bytep = argbuf.b; + + switch (state) { + case st_op: + switch (cmd[0]) { + case 0xA0: /* OPEN TEXT */ + case 0xA1: /* OPEN BINARY */ + case 0xA2: /* PREPARE TEXT */ + case 0xA3: /* PREPARE BINARY */ + byte_count = 11; + state = st_open; + break; + + case 0xA4: /* INPUT */ + do_input(ix); + break; + + case 0xA5: /* READ BLOCK */ + byte_count = 2; + state = st_read; + break; + + case 0xA6: /* PRINT */ + case 0xB9: /* PUT */ + byte_count = 2; + state = st_print; + break; + + case 0xA7: /* CLOSE */ + send_reply(do_close(ix)); + break; + + case 0xA8: /* CLOSEALL */ + do_closeall(true); + break; + + case 0xA9: /* INIT */ + blksize = 253; + do_closeall(false); + break; + + case 0xAE: /* SET BLOCK SIZE */ + case 0xAF: /* INITSZ */ + byte_count = 2; + state = st_blksize; + break; + + case 0xAA: /* RENAME */ + byte_count = 22; + state = st_rename; + break; + + case 0xAB: /* DELETE */ + byte_count = 11; + state = st_delete; + break; + + case 0xAC: /* PREAD */ + byte_count = 2; + state = st_pread; + break; + + case 0xAD: /* PWRITE */ + byte_count = 2; + state = st_pwrite; + break; + + case 0xB0: /* SEEK0 == REWIND */ + do_seek(ix, 0); + break; + + case 0xB1: /* SEEK1 */ + case 0xB2: /* SEEK2 */ + case 0xB3: /* SEEK3 */ + case 0xB4: /* SEEK4 */ + case 0xB5: /* SEEK5 */ + case 0xB6: /* SEEK6 */ + case 0xB7: /* SEEK7 */ + case 0xB8: /* SEEK8 */ + byte_count = cmd[0] - 0xb0; + state = st_seek; + break; + + default: + /* Unknown command */ + send_reply(128 + 11); + break; + } + if (tracing(TRACE_PR)) { + static const char *const cmdnames[0x20] = { + "OPEN A", "OPEN B", "PREP A", "PREP B", + "INPUT", "GET", "PRINT", "CLOSE", + "CALL", "CALLNR", "RENAME", "DELETE", + "PREAD", "PWRITE", "BLKSIZ", "INITSZ", + "REWIND", "SEEK1", "SEEK2", "SEEK3", + "SEEK4", "SEEK5", "SEEK6", "SEEK7", + "SEEK8", "PUT", NULL, NULL, + NULL, NULL, NULL, NULL + }; + int cnum = cmd[0] - 0xa0; + const char *cmdname = (cnum >= 0x20) ? NULL : cmdnames[cnum]; + + fprintf(tracef, "PR: CMD : %-6s %02x %02x %04x <need %u bytes>\n", + cmdname ? cmdname : "???", cmd[0], cmd[1], ix, byte_count); + } + break; + + case st_open: + trace_data(argbuf.b, 11, "OPEN"); + do_open(ix, argbuf.c); + break; + + case st_read: + trace_data(argbuf.b, 2, "READ"); + do_read_block(ix, arg); + break; + + case st_print: + trace_data(argbuf.b, 2, "WRTE"); + bytep = data; + byte_count = arg; + state = st_print2; + break; + + case st_print2: + trace_data(data, datalen, "DATA"); + do_print(ix, datalen, cmd[0] == 0xA6); + break; + + case st_pwrite: + trace_data(argbuf.b, 2, "PWRT"); + bytep = data; + byte_count = 253; + state = st_pwrite2; + break; + + case st_pwrite2: + trace_data(data, datalen, "DATA"); + do_pwrite(ix, arg); + break; + + case st_pread: + trace_data(argbuf.b, 2, "PRED"); + do_pread(ix, arg); + break; + + case st_seek: + trace_data(argbuf.b, cmd[0] - 0xb0, "SEEK"); + do_seek(ix, arg); + break; + + case st_rename: + trace_data(data, 11, "REN1"); + trace_data(data + 11, 11, "REN2"); + do_rename(argbuf.c); + break; + + case st_delete: + trace_data(data, 11, "DEL "); + do_delete(argbuf.c); + break; + + case st_blksize: + trace_data(data, 2, "SIZE"); + blksize = arg; + if (cmd[0] == 0xAF) + do_closeall(false); + break; } - if (tracing(TRACE_PR)) { - static const char * const cmdnames[0x20] = - { - "OPEN A", "OPEN B", "PREP A", "PREP B", - "INPUT", "GET", "PRINT", "CLOSE", - "CALL", "CALLNR", "RENAME", "DELETE", - "PREAD", "PWRITE", "BLKSIZ", "INITSZ", - "REWIND", "SEEK1", "SEEK2", "SEEK3", - "SEEK4", "SEEK5", "SEEK6", "SEEK7", - "SEEK8", "PUT", NULL, NULL, - NULL, NULL, NULL, NULL - }; - int cnum = cmd[0] - 0xa0; - const char *cmdname = (cnum >= 0x20) ? NULL : cmdnames[cnum]; - - fprintf(tracef, "PR: CMD : %-6s %02x %02x %04x <need %u bytes>\n", - cmdname ? cmdname : "???", cmd[0], cmd[1], ix, byte_count); + + datalen = byte_count; + if (bytep == argbuf.b) + memset(&argbuf, 0, sizeof argbuf); + + if (byte_count) { + return true; + } else { + /* back to command mode */ + bytep = cmd; + byte_count = 4; + state = st_op; + return false; } - break; - - case st_open: - trace_data(argbuf.b, 11, "OPEN"); - do_open(ix, argbuf.c); - break; - - case st_read: - trace_data(argbuf.b, 2, "READ"); - do_read_block(ix, arg); - break; - - case st_print: - trace_data(argbuf.b, 2, "WRTE"); - bytep = data; - byte_count = arg; - state = st_print2; - break; - - case st_print2: - trace_data(data, datalen, "DATA"); - do_print(ix, datalen, cmd[0] == 0xA6); - break; - - case st_pwrite: - trace_data(argbuf.b, 2, "PWRT"); - bytep = data; - byte_count = 253; - state = st_pwrite2; - break; - - case st_pwrite2: - trace_data(data, datalen, "DATA"); - do_pwrite(ix, arg); - break; - - case st_pread: - trace_data(argbuf.b, 2, "PRED"); - do_pread(ix, arg); - break; - - case st_seek: - trace_data(argbuf.b, cmd[0] - 0xb0, "SEEK"); - do_seek(ix, arg); - break; - - case st_rename: - trace_data(data, 11, "REN1"); - trace_data(data+11, 11, "REN2"); - do_rename(argbuf.c); - break; - - case st_delete: - trace_data(data, 11, "DEL "); - do_delete(argbuf.c); - break; - - case st_blksize: - trace_data(data, 2, "SIZE"); - blksize = arg; - if (cmd[0] == 0xAF) - do_closeall(false); - break; - } - - datalen = byte_count; - if (bytep == argbuf.b) - memset(&argbuf, 0, sizeof argbuf); - - if (byte_count) { - return true; - } else { - /* back to command mode */ - bytep = cmd; - byte_count = 4; - state = st_op; - return false; - } } @@ -6,7 +6,7 @@ #include "hostfile.h" #ifdef HAVE_SYS_MMAN_H -# include <sys/mman.h> +#include <sys/mman.h> #endif static inline enum host_file_mode mode_type(enum host_file_mode mode) @@ -19,31 +19,31 @@ static inline enum host_file_mode mode_type(enum host_file_mode mode) #define DIR_MODE (FILE_MODE|S_IXUSR|S_IXGRP|S_IXOTH) #ifdef HAVE__MKDIR -# define make_dir(x) _mkdir(x) +#define make_dir(x) _mkdir(x) #else -# define make_dir(x) mkdir((x), DIR_MODE) +#define make_dir(x) mkdir((x), DIR_MODE) #endif #ifndef O_BINARY -# define O_BINARY 0 +#define O_BINARY 0 #endif #ifndef O_TEXT -# define O_TEXT 0 +#define O_TEXT 0 #endif #if defined(__WIN32__) && defined(_O_U16TEXT) -# define UNICODE_O_FLAGS _O_U16TEXT +#define UNICODE_O_FLAGS _O_U16TEXT #else -# define UNICODE_O_FLAGS O_TEXT +#define UNICODE_O_FLAGS O_TEXT #endif #ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 +#define O_NOFOLLOW 0 #endif #ifndef O_SHORT_LIVED -# define O_SHORT_LIVED 0 +#define O_SHORT_LIVED 0 #endif #ifndef O_DIRECTORY -# define O_DIRECTORY 0 +#define O_DIRECTORY 0 #endif /* List of all host files */ @@ -56,33 +56,33 @@ static inline int mode_openflags(enum host_file_mode mode) { switch (mode_type(mode)) { case HF_BINARY: - return O_BINARY; + return O_BINARY; case HF_TEXT: - return O_TEXT; + return O_TEXT; case HF_UNICODE: - return UNICODE_O_FLAGS; + return UNICODE_O_FLAGS; case HF_DIRECTORY: - return O_DIRECTORY; + return O_DIRECTORY; default: - return 0; + return 0; } } #ifndef HAVE__SETMODE -# define _setmode(x,y) ((void)(x), (void)(y)) +#define _setmode(x,y) ((void)(x), (void)(y)) #endif static inline bool filename_is_absolute(const char *name) { - if (*name == '/') - return true; + if (*name == '/') + return true; #ifdef __WIN32__ - if (*name == '\\' || strchr(name, ':')) - return true; + if (*name == '\\' || strchr(name, ':')) + return true; #endif - return false; + return false; } int stat_file(const char *dir, const char *filename, struct stat *st) @@ -92,14 +92,14 @@ int stat_file(const char *dir, const char *filename, struct stat *st) int rv, err; if (!dir) - dir = ""; + dir = ""; dl = strlen(dir); asprintf(&path, "%s%s%s", dir, - (dl && !is_path_separator(dir[dl-1])) ? "/" : "", - filename ? filename : "."); + (dl && !is_path_separator(dir[dl - 1])) ? "/" : "", + filename ? filename : "."); if (!path) - return -1; + return -1; rv = stat(path, st); err = errno; @@ -114,24 +114,24 @@ int stat_file(const char *dir, const char *filename, struct stat *st) * and a file name */ struct host_file *open_host_file(enum host_file_mode mode, const char *dir, - const char *filename, int openflags) + const char *filename, int openflags) { size_t dl, fl; char *p; struct host_file *hf; if (!dir) - dir = ""; + dir = ""; if (!filename) { - filename = "."; - if (mode_type(mode) != HF_DIRECTORY) - mode = HF_FAIL; + filename = "."; + if (mode_type(mode) != HF_DIRECTORY) + mode = HF_FAIL; } if (mode & HF_FAIL) { - errno = ENOENT; - return NULL; + errno = ENOENT; + return NULL; } dl = strlen(dir); @@ -139,35 +139,35 @@ struct host_file *open_host_file(enum host_file_mode mode, const char *dir, hf = calloc(sizeof *hf + dl + fl + 1, 1); if (!hf) - return NULL; + return NULL; - hf->fd = -1; - hf->mode = mode; + hf->fd = -1; + hf->mode = mode; hf->openflags = openflags | mode_openflags(mode); - hf->nuke = !!(openflags & O_EXCL); + hf->nuke = ! !(openflags & O_EXCL); p = hf->filename; if (dl > 0 && !filename_is_absolute(filename)) { - p = mempcpy(p, dir, dl); - if (!is_path_separator(p[-1])) - *p++ = '/'; + p = mempcpy(p, dir, dl); + if (!is_path_separator(p[-1])) + *p++ = '/'; } - p = mempcpy(p, filename, fl+1); + p = mempcpy(p, filename, fl + 1); hf->namelen = p - hf->filename; if (mode_type(mode) == HF_DIRECTORY) { - hf->d = opendir(hf->filename); + hf->d = opendir(hf->filename); } else { - mode_t filemode = (mode & HF_PRIVATE) ? PRIV_MODE : FILE_MODE; - for (;;) { - hf->fd = open(hf->filename, hf->openflags, filemode); - if (hf->fd >= 0 || !(mode & HF_RETRY)) - break; - - hf->openflags = (hf->openflags & ~O_ACCMODE) | O_RDONLY; - hf->openflags &= ~(O_CREAT|O_EXCL|O_APPEND); - mode &= ~HF_RETRY; - } + mode_t filemode = (mode & HF_PRIVATE) ? PRIV_MODE : FILE_MODE; + for (;;) { + hf->fd = open(hf->filename, hf->openflags, filemode); + if (hf->fd >= 0 || !(mode & HF_RETRY)) + break; + + hf->openflags = (hf->openflags & ~O_ACCMODE) | O_RDONLY; + hf->openflags &= ~(O_CREAT | O_EXCL | O_APPEND); + mode &= ~HF_RETRY; + } } return finish_host_file(hf); @@ -176,33 +176,33 @@ struct host_file *open_host_file(enum host_file_mode mode, const char *dir, /* * Create a numbered dump file for writing (only) */ -struct host_file * -dump_file(enum host_file_mode mode, const char *dir, const char *pattern) +struct host_file *dump_file(enum host_file_mode mode, const char *dir, + const char *pattern) { int err; unsigned int n; struct host_file *hf; char *filename; - const int openflags = O_WRONLY|O_CREAT|O_EXCL|O_NOFOLLOW; + const int openflags = O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW; if (!dir) - dir = ""; + dir = ""; /* If it is a directory name, try to create it if it doesn't exist */ if (dir[0]) - make_dir(dir); + make_dir(dir); for (n = 1; n <= 9999; n++) { - asprintf(&filename, pattern, n); - if (!filename) - return NULL; - hf = open_host_file(mode, dir, filename, openflags); - err = errno; - free(filename); - errno = err; - - if (hf || err != EEXIST) - return hf; + asprintf(&filename, pattern, n); + if (!filename) + return NULL; + hf = open_host_file(mode, dir, filename, openflags); + err = errno; + free(filename); + errno = err; + + if (hf || err != EEXIST) + return hf; } return hf; @@ -218,16 +218,16 @@ struct host_file *temp_file(enum host_file_mode mode, const char *prefix) mode |= HF_PRIVATE; if (!prefix) - prefix = ""; + prefix = ""; pfxlen = strlen(prefix); hf = calloc(sizeof *hf + pfxlen + 6, 1); if (!hf) - return NULL; + return NULL; hf->mode = mode; - hf->openflags = O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_SHORT_LIVED; + hf->openflags = O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_SHORT_LIVED; hf->nuke = true; hf->namelen = pfxlen + 6; memcpy(hf->filename, prefix, pfxlen); @@ -235,8 +235,8 @@ struct host_file *temp_file(enum host_file_mode mode, const char *prefix) hf->fd = mkstemp(hf->filename); if (hf->fd < 0) { - free(hf); - return NULL; + free(hf); + return NULL; } _setmode(hf->fd, mode_openflags(mode)); @@ -248,7 +248,7 @@ struct host_file *temp_file(enum host_file_mode mode, const char *prefix) /* Hack it with tmpnam() */ #ifndef TMP_MAX -# define TMP_MAX 65536 +#define TMP_MAX 65536 #endif struct host_file *temp_file(enum host_file_mode mode) @@ -257,18 +257,19 @@ struct host_file *temp_file(enum host_file_mode mode) int err; int attempts = TMP_MAX; size_t namelen; - const int openflags = O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_SHORT_LIVED; + const int openflags = + O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_SHORT_LIVED; mode |= HF_PRIVATE; do { - filename = tempnam(NULL, TEMPFILE_PREFIX); - if (!filename) - return NULL; + filename = tempnam(NULL, TEMPFILE_PREFIX); + if (!filename) + return NULL; - hf = open_host_file(mode, NULL, filename, openflags); - err = errno; - free(filename); + hf = open_host_file(mode, NULL, filename, openflags); + err = errno; + free(filename); } while (!hf && err == EEXIST && --attempts); errno = err; @@ -283,7 +284,7 @@ static int update_filesize(struct host_file *hf) struct stat st; if (fstat(hf->fd, &st)) - return -1; + return -1; hf->filesize = st.st_size; return 0; @@ -295,40 +296,40 @@ static struct host_file *finish_host_file(struct host_file *hf) const char *opt; if (!hf) - return NULL; + return NULL; if (hf->mode == HF_DIRECTORY) { - if (!hf->d) - goto err; + if (!hf->d) + goto err; } else { - if (hf->fd < 0) - goto err; - - if (update_filesize(hf)) - goto err; - - switch (hf->openflags & O_ACCMODE) { - case O_RDONLY: - opt = "r"; - break; - case O_WRONLY: - opt = (hf->openflags & O_APPEND) ? "a" : "w"; - break; - default: - opt = (hf->openflags & O_APPEND) ? "a+" : - (hf->openflags & (O_CREAT|O_TRUNC)) ? "w+" : "r+"; - break; - } - - hf->f = fdopen(hf->fd, opt); - if (!hf->f) - goto err; + if (hf->fd < 0) + goto err; + + if (update_filesize(hf)) + goto err; + + switch (hf->openflags & O_ACCMODE) { + case O_RDONLY: + opt = "r"; + break; + case O_WRONLY: + opt = (hf->openflags & O_APPEND) ? "a" : "w"; + break; + default: + opt = (hf->openflags & O_APPEND) ? "a+" : + (hf->openflags & (O_CREAT | O_TRUNC)) ? "w+" : "r+"; + break; + } + + hf->f = fdopen(hf->fd, opt); + if (!hf->f) + goto err; } - hf->next = list; + hf->next = list; hf->prevp = &list; if (list) - list->prevp = &hf->next; + list->prevp = &hf->next; list = hf; return hf; @@ -358,20 +359,21 @@ static inline size_t page_size(void) #elif defined(PAGE_SIZE) return PAGE_SIZE; #else - return 1; /* Bogus, but maybe good enough */ + return 1; /* Bogus, but maybe good enough */ #endif } #ifdef HAVE_FTRUNCATE -# define set_file_size(fd,size) ftruncate(fd,size) +#define set_file_size(fd,size) ftruncate(fd,size) #elif defined(HAVE__CHSIZE_S) -# define set_file_size(fd,size) _chsize_s(fd,size) +#define set_file_size(fd,size) _chsize_s(fd,size) #elif defined(HAVE__CHSIZE) -# define set_file_size(fd,size) _chsize(fd,size) +#define set_file_size(fd,size) _chsize(fd,size) #else static int set_file_size(int fd, size_t size) { - (void)fd; (void)size; + (void)fd; + (void)size; return -1; } #endif @@ -398,7 +400,7 @@ static void *do_map_file(struct host_file *hf) */ map = mmap(NULL, mlen, prot, MAP_SHARED, fileno(hf->f), 0); if (map == MAP_FAILED) - return NULL; + return NULL; /* * If the file is smaller than we wanted (due to being readonly, @@ -406,8 +408,8 @@ static void *do_map_file(struct host_file *hf) * over the rest of the mapping to avoid SIGBUS. */ if (flen < mlen) - mmap(map + flen, mlen - flen, prot, - MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0); + mmap(map + flen, mlen - flen, prot, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0); return hf->map = map; } @@ -415,7 +417,7 @@ static void *do_map_file(struct host_file *hf) static void do_unmap_file(struct host_file *hf) { if (!hf->map) - return; + return; munmap(hf->map, hf->mlen); hf->map = NULL; @@ -425,7 +427,7 @@ static void do_msync_file(struct host_file *hf) { #ifdef HAVE_MSYNC if (!hf->map || !file_wrok(hf)) - return; + return; msync(hf->map, hf->mlen, MS_SYNC); #else @@ -437,36 +439,36 @@ static void do_msync_file(struct host_file *hf) static void *do_map_file(struct host_file *hf) { - HANDLE hfile = (HANDLE)_get_osfhandle(fileno(hf->f)); + HANDLE hfile = (HANDLE) _get_osfhandle(fileno(hf->f)); HANDLE mapping; void *map; DWORD prot; mapping = - CreateFileMapping(hfile, NULL, - file_wrok(hf) ? PAGE_READWRITE : PAGE_READONLY, - (DWORD)((uint64_t)hf->mlen >> 32), - (DWORD)(hf->mlen), NULL); + CreateFileMapping(hfile, NULL, + file_wrok(hf) ? PAGE_READWRITE : PAGE_READONLY, + (DWORD) ((uint64_t) hf->mlen >> 32), + (DWORD) (hf->mlen), NULL); if (!mapping) - return NULL; + return NULL; prot = (file_rdok(hf) ? FILE_MAP_READ : 0) | - (file_wrok(hf) ? FILE_MAP_WRITE : 0); + (file_wrok(hf) ? FILE_MAP_WRITE : 0); map = MapViewOfFile(mapping, prot, 0, 0, hf->mlen); if (!map) { - CloseHandle(mapping); - return NULL; + CloseHandle(mapping); + return NULL; } - hf->maphandle = mapping; - return (hf->map = map); + hf->maphandle = mapping; + return (hf->map = map); } static void do_unmap_file(struct host_file *hf) { if (!hf->map) - return; + return; UnmapViewOfFile(hf->map); hf->map = NULL; @@ -477,12 +479,12 @@ static void do_unmap_file(struct host_file *hf) static void do_msync_file(struct host_file *hf) { if (!hf->map || !file_wrok(hf)) - return; + return; FlushViewOfFile(hf->map, hf->mlen); } -#else /* No memory mapping technique known */ +#else /* No memory mapping technique known */ static void *do_map_file(struct host_file *hf) { @@ -515,26 +517,26 @@ void *map_file(struct host_file *hf, size_t mlen) off_t mleno; if (!hf || !hf->f || mode_type(hf->mode) != HF_BINARY) - return NULL; /* Not a mappable file */ + return NULL; /* Not a mappable file */ if (hf->map) - return hf->map; /* Already mapped */ + return hf->map; /* Already mapped */ if (update_filesize(hf)) - return NULL; + return NULL; mleno = mlen; if (!mleno) - mleno = hf->filesize; - mleno = mlen = (mleno > MAX_MAP_FILE) ? MAX_MAP_FILE : (size_t)mleno; + mleno = hf->filesize; + mleno = mlen = (mleno > MAX_MAP_FILE) ? MAX_MAP_FILE : (size_t) mleno; if (hf->filesize < mleno && file_wrok(hf)) { - set_file_size(hf->fd, mleno); /* Try to extend file */ - if (update_filesize(hf)) - return NULL; + set_file_size(hf->fd, mleno); /* Try to extend file */ + if (update_filesize(hf)) + return NULL; } - hf->flen = (hf->filesize < mleno) ? (size_t)hf->filesize : mlen; + hf->flen = (hf->filesize < mleno) ? (size_t) hf->filesize : mlen; /* Round up to a size in pages */ page_mask = page_size() - 1; @@ -546,7 +548,7 @@ void *map_file(struct host_file *hf, size_t mlen) void flush_file(struct host_file *hf) { if (!hf || !hf->f || !file_wrok(hf)) - return; /* Nothing to sync */ + return; /* Nothing to sync */ fflush(hf->f); do_msync_file(hf); @@ -560,37 +562,37 @@ int close_file(struct host_file **filep) int err = 0; if (!filep || !(file = *filep)) - return 0; + return 0; if (file->prevp) { - *file->prevp = file->next; /* Remove from linked list */ - if (file->next) - file->next->prevp = 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)) - err = err ? err : errno; + if (closedir(file->d)) + err = err ? err : errno; } else { - flush_file(file); - do_unmap_file(file); - - if (file->f) { - if (fclose(file->f)) - err = err ? err : errno; - else - file->fd = -1; /* fclose() closes the file descriptor too */ - } - - if (file->fd >= 0) { - if (close(file->fd)) - err = err ? err : errno; - } - - if (file->nuke && file->fd >= 0 && file->filename[0]) { - if (remove(file->filename)) - err = err ? err : errno; - } + flush_file(file); + do_unmap_file(file); + + if (file->f) { + if (fclose(file->f)) + err = err ? err : errno; + else + file->fd = -1; /* fclose() closes the file descriptor too */ + } + + if (file->fd >= 0) { + if (close(file->fd)) + err = err ? err : errno; + } + + if (file->nuke && file->fd >= 0 && file->filename[0]) { + if (remove(file->filename)) + err = err ? err : errno; + } } free(file); @@ -604,8 +606,8 @@ static void hostfile_cleanup(void) { struct host_file *hf, *next; for (hf = list; hf; hf = next) { - next = hf->next; - close_file(&hf); + next = hf->next; + close_file(&hf); } } @@ -620,13 +622,13 @@ void hostfile_init(void) */ const char *host_strip_path(const char *path) { - const char *p; + const char *p; - p = strrchr(path, '\0'); - while (--p >= path) { - if (is_path_separator(*p)) - break; - } + p = strrchr(path, '\0'); + while (--p >= path) { + if (is_path_separator(*p)) + break; + } - return p+1; + return p + 1; } @@ -9,15 +9,15 @@ static inline bool is_stdio(const char *filename) } enum host_file_mode { - HF_BINARY = 0, /* Raw binary */ - HF_TEXT = 1, /* Text mode compatible with ASCII */ - HF_UNICODE = 2, /* Platform preferred Unicode encoding */ - HF_DIRECTORY = 3, /* opendir() on a directory */ + HF_BINARY = 0, /* Raw binary */ + HF_TEXT = 1, /* Text mode compatible with ASCII */ + HF_UNICODE = 2, /* Platform preferred Unicode encoding */ + HF_DIRECTORY = 3, /* opendir() on a directory */ HF_TYPE_MASK = 0x0f, - HF_PRIVATE = 0x10, /* Only user permissions */ - HF_RETRY = 0x20, /* If O_RDWR retry with O_RDONLY on failure */ - HF_FAIL = 0x40 /* Don't actually try to open, return ENOENT */ + HF_PRIVATE = 0x10, /* Only user permissions */ + HF_RETRY = 0x20, /* If O_RDWR retry with O_RDONLY on failure */ + HF_FAIL = 0x40 /* Don't actually try to open, return ENOENT */ }; struct host_file { @@ -30,11 +30,11 @@ struct host_file { int openflags; bool nuke; enum host_file_mode mode; - uint8_t *map; /* Memory-mapped contents */ - size_t mlen; /* Length of memory map */ - size_t flen; /* Length of true file in memory map */ + uint8_t *map; /* Memory-mapped contents */ + size_t mlen; /* Length of memory map */ + size_t flen; /* Length of true file in memory map */ #ifdef __WIN32__ - HANDLE maphandle; /* Special Windows drain bramage */ + HANDLE maphandle; /* Special Windows drain bramage */ #endif char filename[1]; }; @@ -53,42 +53,41 @@ static inline bool is_path_separator(char c) case ':': case '\\': #endif - return true; + return true; default: - return false; - } + return false; + } } #ifndef O_ACCMODE -# define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) /* Hope this works */ +#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) /* Hope this works */ #endif static inline bool file_rdok(struct host_file *hf) { - return (hf->openflags & O_ACCMODE) != O_WRONLY; + return (hf->openflags & O_ACCMODE) != O_WRONLY; } static inline bool file_wrok(struct host_file *hf) { - return (hf->openflags & O_ACCMODE) != O_RDONLY; + return (hf->openflags & O_ACCMODE) != O_RDONLY; } /* Open a host filesystem file */ -extern struct host_file * -open_host_file(enum host_file_mode mode, const char *dir, - const char *filename, int openflags); +extern struct host_file *open_host_file(enum host_file_mode mode, + const char *dir, const char *filename, + int openflags); /* Map (or read) the file contents into memory */ -extern void * -map_file(struct host_file *file, size_t len); +extern void *map_file(struct host_file *file, size_t len); /* Create a numbered dump file */ -extern struct host_file * -dump_file(enum host_file_mode mode, const char *dir, const char *pattern); +extern struct host_file *dump_file(enum host_file_mode mode, const char *dir, + const char *pattern); /* Create a temporary file */ -extern struct host_file * -temp_file(enum host_file_mode mode, const char *prefix); +extern struct host_file *temp_file(enum host_file_mode mode, + const char *prefix); /* Write contents back to disk if necessary */ extern void flush_file(struct host_file *file); @@ -9,7 +9,7 @@ #include "nstime.h" #ifdef HAVE_UNISTD_H -# include <unistd.h> +#include <unistd.h> #endif #include <SDL.h> @@ -17,25 +17,25 @@ #ifdef _POSIX_TIMERS #ifdef _POSIX_MONOTONIC_CLOCK -# define WHICHCLOCK CLOCK_MONOTONIC +#define WHICHCLOCK CLOCK_MONOTONIC #else -# define WHICHCLOCK CLOCK_REALTIME +#define WHICHCLOCK CLOCK_REALTIME #endif static time_t tv_sec_zero; uint64_t nstime(void) { - struct timespec ts; - clock_gettime(WHICHCLOCK, &ts); - return ((ts.tv_sec - tv_sec_zero) * UINT64_C(1000000000)) + ts.tv_nsec; + struct timespec ts; + clock_gettime(WHICHCLOCK, &ts); + return ((ts.tv_sec - tv_sec_zero) * UINT64_C(1000000000)) + ts.tv_nsec; } void nstime_init(void) { - struct timespec ts; - clock_gettime(WHICHCLOCK, &ts); - tv_sec_zero = ts.tv_sec; + struct timespec ts; + clock_gettime(WHICHCLOCK, &ts); + tv_sec_zero = ts.tv_sec; } #elif defined(__WIN32__) @@ -45,51 +45,53 @@ static HANDLE wait_timer; static inline uint64_t fromft(FILETIME ft) { - ULARGE_INTEGER q; + ULARGE_INTEGER q; - q.LowPart = ft.dwLowDateTime; - q.HighPart = ft.dwHighDateTime; - return q.QuadPart; + q.LowPart = ft.dwLowDateTime; + q.HighPart = ft.dwHighDateTime; + return q.QuadPart; } + static inline FILETIME toft(uint64_t t) { - FILETIME ft; - ULARGE_INTEGER q; + FILETIME ft; + ULARGE_INTEGER q; - q.QuadPart = t; - ft.dwLowDateTime = q.LowPart; - ft.dwHighDateTime = q.HighPart; - return ft; + q.QuadPart = t; + ft.dwLowDateTime = q.LowPart; + ft.dwHighDateTime = q.HighPart; + return ft; } uint64_t nstime(void) { - FILETIME ft; - uint64_t t; + FILETIME ft; + uint64_t t; - GetSystemTimeAsFileTime(&ft); - t = fromft(ft); - return (t - tzero) * UINT64_C(100); + GetSystemTimeAsFileTime(&ft); + t = fromft(ft); + return (t - tzero) * UINT64_C(100); } void nstime_init(void) { - FILETIME ft; + FILETIME ft; - GetSystemTimeAsFileTime(&ft); - tzero = fromft(ft); + GetSystemTimeAsFileTime(&ft); + tzero = fromft(ft); - wait_timer = CreateWaitableTimer(NULL, TRUE, NULL); + wait_timer = CreateWaitableTimer(NULL, TRUE, NULL); } void mynssleep(uint64_t until, uint64_t since) { - LARGE_INTEGER q; + LARGE_INTEGER q; - q.QuadPart = (until+99)/UINT64_C(100); - SetWaitableTimer(wait_timer, &q, 0, NULL, NULL, FALSE); - WaitForSingleObject(wait_timer, - (until-since+UINT64_C(1999999))/UINT64_C(1000000)); + q.QuadPart = (until + 99) / UINT64_C(100); + SetWaitableTimer(wait_timer, &q, 0, NULL, NULL, FALSE); + WaitForSingleObject(wait_timer, + (until - since + + UINT64_C(1999999)) / UINT64_C(1000000)); } #elif defined(HAVE_GETTIMEOFDAY) @@ -98,59 +100,59 @@ static time_t tv_sec_zero; uint64_t nstime(void) { - struct timeval tv; + struct timeval tv; - gettimeofday(&tv, NULL); - return ((tv.tv_sec - tv_sec_zero) * UINT64_C(1000000000)) - + (tv.tv_usec * UINT64_C(1000)); + gettimeofday(&tv, NULL); + return ((tv.tv_sec - tv_sec_zero) * UINT64_C(1000000000)) + + (tv.tv_usec * UINT64_C(1000)); } void nstime_init(void) { - struct timeval tv; + struct timeval tv; - gettimeofday(&tv, NULL); - tv_sec_zero = tv.tv_sec; + gettimeofday(&tv, NULL); + tv_sec_zero = tv.tv_sec; } #else -# error "Need to implement a different fine-grained timer function here" +#error "Need to implement a different fine-grained timer function here" #endif #if defined(WHICHCLOCK) && defined(HAVE_CLOCK_NANOSLEEP) void mynssleep(uint64_t until, uint64_t since) { - (void)since; - struct timespec req; + (void)since; + struct timespec req; - req.tv_sec = until / UINT64_C(1000000000) + tv_sec_zero; - req.tv_nsec = until % UINT64_C(1000000000); + req.tv_sec = until / UINT64_C(1000000000) + tv_sec_zero; + req.tv_nsec = until % UINT64_C(1000000000); - clock_nanosleep(WHICHCLOCK, TIMER_ABSTIME, &req, NULL); + clock_nanosleep(WHICHCLOCK, TIMER_ABSTIME, &req, NULL); } #elif defined(HAVE_NANOSLEEP) void mynssleep(uint64_t until, uint64_t since) { - struct timespec req; + struct timespec req; - until -= since; + until -= since; - req.tv_sec = until / UINT64_C(1000000000); - req.tv_nsec = until % UINT64_C(1000000000); + req.tv_sec = until / UINT64_C(1000000000); + req.tv_nsec = until % UINT64_C(1000000000); - nanosleep(&req, NULL); + nanosleep(&req, NULL); } #elif !defined(__WIN32__) void mynssleep(uint64_t until, uint64_t since) { - until -= since; + until -= since; - SDL_Delay((until + UINT64_C(999999))/UINT64_C(1000000)); + SDL_Delay((until + UINT64_C(999999)) / UINT64_C(1000000)); } #endif @@ -25,7 +25,8 @@ #include <locale.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 '*'"; #endif @@ -34,133 +35,133 @@ static struct host_file *hf; static void print_finish(void) { - const char *p; - char *cmd, *q; - size_t cmdlen, namelen; - - if (!hf) - return; - - fflush(hf->f); - - namelen = hf->namelen; - cmdlen = 0; - for (p = lpr_command; *p; p++) { - cmdlen += (*p == '*') ? namelen : 1; - } - cmd = malloc(cmdlen+1); - - if (cmd) { - for (p = lpr_command, q = cmd; *p; p++) { - if (*p == '*') { - memcpy(q, hf->filename, namelen); - q += namelen; - } else { - *q++ = *p; - } - } - *q = '\0'; + const char *p; + char *cmd, *q; + size_t cmdlen, namelen; + + if (!hf) + return; - system(cmd); - free(cmd); - } - close_file(&hf); + fflush(hf->f); + + namelen = hf->namelen; + cmdlen = 0; + for (p = lpr_command; *p; p++) { + cmdlen += (*p == '*') ? namelen : 1; + } + cmd = malloc(cmdlen + 1); + + if (cmd) { + for (p = lpr_command, q = cmd; *p; p++) { + if (*p == '*') { + memcpy(q, hf->filename, namelen); + q += namelen; + } else { + *q++ = *p; + } + } + *q = '\0'; + + system(cmd); + free(cmd); + } + close_file(&hf); } static void output(unsigned char c) { - static const char temp_prefix[] = "abcprint_tmp_"; - - static const wchar_t abc_to_unicode[256] = - L"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" - L"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" - L" !\"#¤%&\'()*+,-./0123456789:;<=>?" - L"ÉABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÅÜ_" - L"éabcdefghijklmnopqrstuvwxyzäöåü\x25a0" - L"\x20ac\x25a1\x201a\x0192\x201e\x2026\x2020\x2021" - L"\x02c6\x2030\x0160\x2039\x0152\x2190\x017d\x2192" - L"\x2191\x2018\x2019\x201c\x201d\x2022\x2013\x2014" - L"\x02dc\x2122\x0161\x203a\x0153\x2193\x017e\x0178" - L"\240\241\242\243$\245\246\247\250\251\252\253\254\255\256\257" - L"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" - L"\300\301\302\303[]\306\307\310@\312\313\314\315\316\317" - L"\320\321\322\323\324\325\\\327\330\331\332\333^\335\336\337" - L"\340\341\342\343{}\346\347\350`\352\353\354\355\356\357" - L"\360\361\362\363\364\365|\367\370\371\372\373~\375\376\377"; - - if (!hf) { - if (c < '\b' || (c > '\r' && c < 31)) - hf = temp_file(HF_BINARY, temp_prefix); - else - hf = temp_file(HF_UNICODE, temp_prefix); - } - - if (hf->mode == HF_BINARY) - putc(c, hf->f); - else if (c != '\r') - putwc(abc_to_unicode[c], hf->f); + static const char temp_prefix[] = "abcprint_tmp_"; + + static const wchar_t abc_to_unicode[256] = + L"\000\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" + L"\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" + L" !\"#¤%&\'()*+,-./0123456789:;<=>?" + L"ÉABCDEFGHIJKLMNOPQRSTUVWXYZÄÖÅÜ_" + L"éabcdefghijklmnopqrstuvwxyzäöåü\x25a0" + L"\x20ac\x25a1\x201a\x0192\x201e\x2026\x2020\x2021" + L"\x02c6\x2030\x0160\x2039\x0152\x2190\x017d\x2192" + L"\x2191\x2018\x2019\x201c\x201d\x2022\x2013\x2014" + L"\x02dc\x2122\x0161\x203a\x0153\x2193\x017e\x0178" + L"\240\241\242\243$\245\246\247\250\251\252\253\254\255\256\257" + L"\260\261\262\263\264\265\266\267\270\271\272\273\274\275\276\277" + L"\300\301\302\303[]\306\307\310@\312\313\314\315\316\317" + L"\320\321\322\323\324\325\\\327\330\331\332\333^\335\336\337" + L"\340\341\342\343{}\346\347\350`\352\353\354\355\356\357" + L"\360\361\362\363\364\365|\367\370\371\372\373~\375\376\377"; + + if (!hf) { + if (c < '\b' || (c > '\r' && c < 31)) + hf = temp_file(HF_BINARY, temp_prefix); + else + hf = temp_file(HF_UNICODE, temp_prefix); + } + + if (hf->mode == HF_BINARY) + putc(c, hf->f); + else if (c != '\r') + putwc(abc_to_unicode[c], hf->f); } enum input_state { - is_normal, /* Normal operation */ - is_ff, /* 0xFF received */ - is_file, /* File operation in progress */ - is_console /* Output to console */ + is_normal, /* Normal operation */ + is_ff, /* 0xFF received */ + is_file, /* File operation in progress */ + is_console /* Output to console */ }; static enum input_state is; FILE *console_file; void abcprint_init(void) { - is = is_normal; + is = is_normal; } void abcprint_recv(const void *data, size_t len) { - const unsigned char *dp = data; - unsigned char c; - - while (len--) { - c = *dp++; - - switch ( is ) { - case is_normal: - if ( c == 0xff ) - is = is_ff; - else - output(c); - break; - - case is_ff: - if (c == 0) { - /* End of job */ - print_finish(); - is = is_normal; - } else if (c >= 0xa0 && c <= 0xbf) { - /* Opcode range reserved for file ops */ - is = file_op(c) ? is_file : is_normal; - } else if (c == 0xc0) { - /* Output to console */ - is = is_console; - } else { - output(c); - is = is_normal; - } - break; - - case is_file: - is = file_op(c) ? is_file : is_normal; - break; - - case is_console: - if (c == 0) { - is = is_normal; - if (console_file) - fflush(console_file); - } else if (console_file) { - fputc(c, console_file); - } - break; + const unsigned char *dp = data; + unsigned char c; + + while (len--) { + c = *dp++; + + switch (is) { + case is_normal: + if (c == 0xff) + is = is_ff; + else + output(c); + break; + + case is_ff: + if (c == 0) { + /* End of job */ + print_finish(); + is = is_normal; + } else if (c >= 0xa0 && c <= 0xbf) { + /* Opcode range reserved for file ops */ + is = file_op(c) ? is_file : is_normal; + } else if (c == 0xc0) { + /* Output to console */ + is = is_console; + } else { + output(c); + is = is_normal; + } + break; + + case is_file: + is = file_op(c) ? is_file : is_normal; + break; + + case is_console: + if (c == 0) { + is = is_normal; + if (console_file) + fflush(console_file); + } else if (console_file) { + fputc(c, console_file); + } + break; + } } - } } @@ -4,14 +4,14 @@ #include <time.h> -static uint8_t bytes[8]; /* YY YY mm dd HH MM SS FF */ +static uint8_t bytes[8]; /* YY YY mm dd HH MM SS FF */ static int ptr; /* * ASCII string - will be converted to BCD * __ is a placeholder for the command phase */ -static uint8_t e05time[17*2]; /* __ HH MM dd mm YY ?? SS ?? */ +static uint8_t e05time[17 * 2]; /* __ HH MM dd mm YY ?? SS ?? */ static unsigned int e05bit; static uint8_t e05cmd; @@ -70,11 +70,11 @@ static void latch_time(void) sys_latch_time(); sprintf((char *)e05time, "__%02u%02u%02u%02u%02u??%02u??", - bytes[4], bytes[5], bytes[3], bytes[2], - bytes[1]/* ,??? */, bytes[6] /* ,??? */); + bytes[4], bytes[5], bytes[3], bytes[2], + bytes[1] /* ,??? */ , bytes[6] /* ,??? */ ); - ptr = 0; /* Reset pointer for bus clock */ - e05cmd = e05bit = 0; /* Reset pointer for E05-16 */ + ptr = 0; /* Reset pointer for bus clock */ + e05cmd = e05bit = 0; /* Reset pointer for E05-16 */ } /* This is the "fake" ABCbus-connected RTC */ @@ -86,16 +86,16 @@ int rtc_in(int sel, int port) switch (port) { case 0: - b = bytes[ptr]; - ptr = (ptr+1) & 7; - break; + b = bytes[ptr]; + ptr = (ptr + 1) & 7; + break; case 1: - latch_time(); - b = 0xd2; /* Presence check */ - break; + latch_time(); + b = 0xd2; /* Presence check */ + break; default: - b = 0xff; - break; + b = 0xff; + break; } return b; @@ -107,73 +107,74 @@ static uint8_t e05state; void abc806_rtc_out(uint8_t port, uint8_t val) { - uint8_t oldstate, reg, set, clr; - - if (port & 1) - return; /* No idea what this does */ - - reg = val & 7; - oldstate = e05state; - e05state = (val >> 7 << reg) | (e05state & ~(1 << reg)); - set = e05state & ~oldstate; - clr = ~e05state & oldstate; - - switch (reg) { - case 0: - /* "EME* = ? */ - break; - case 1: - /* Mode40 - set here? */ - break; - case 2: - /* Bit A8 on "7621/HRU11" = ? */ - break; - case 3: - /* INI# on "PROT" = ? */ - break; - case 4: - /* "TXOFF" = ? */ - break; - case 5: - /* RTC chip select */ - if (set) - latch_time(); - break; - case 6: - if (clr && (e05state & 0x20)) { - e05bit++; - if (e05bit == 5) - e05bit = ((e05cmd & 7) << 3) + 8; /* Pure guess */ - else if (e05bit >= 9*8) - e05bit = 8; - } - break; - case 7: - /* Data out (OC) must be 1 to read */ - if (e05bit < 4) { - e05cmd = (e05cmd & ~(1 << e05bit)) | (((uint8_t)~val >> 7) << e05bit); + uint8_t oldstate, reg, set, clr; + + if (port & 1) + return; /* No idea what this does */ + + reg = val & 7; + oldstate = e05state; + e05state = (val >> 7 << reg) | (e05state & ~(1 << reg)); + set = e05state & ~oldstate; + clr = ~e05state & oldstate; + + switch (reg) { + case 0: + /* "EME* = ? */ + break; + case 1: + /* Mode40 - set here? */ + break; + case 2: + /* Bit A8 on "7621/HRU11" = ? */ + break; + case 3: + /* INI# on "PROT" = ? */ + break; + case 4: + /* "TXOFF" = ? */ + break; + case 5: + /* RTC chip select */ + if (set) + latch_time(); + break; + case 6: + if (clr && (e05state & 0x20)) { + e05bit++; + if (e05bit == 5) + e05bit = ((e05cmd & 7) << 3) + 8; /* Pure guess */ + else if (e05bit >= 9 * 8) + e05bit = 8; + } + break; + case 7: + /* Data out (OC) must be 1 to read */ + if (e05bit < 4) { + e05cmd = + (e05cmd & ~(1 << e05bit)) | (((uint8_t) ~ val >> 7) << e05bit); + } + break; } - break; - } } uint8_t abc806_rtc_in(uint8_t port) { - uint8_t v; - unsigned int bp, by, bi; + uint8_t v; + unsigned int bp, by, bi; - if (!(port & 1)) - return 0xff; /* No idea */ + if (!(port & 1)) + return 0xff; /* No idea */ - /* D3:0 has something to do with "7621/HRU11" = ?; assume 1 for now */ - v = 0xff; + /* D3:0 has something to do with "7621/HRU11" = ?; assume 1 for now */ + v = 0xff; - /* D7 is RTC output */ - bp = e05bit ^ 7; - by = bp >> 2; - bi = (bp & 3) + 4; - if (e05state & 0x20) - v = (v & 0x7f) | ((e05time[by] << bi) & 0x80 & e05state); + /* D7 is RTC output */ + bp = e05bit ^ 7; + by = bp >> 2; + bi = (bp & 3) + 4; + if (e05state & 0x20) + v = (v & 0x7f) | ((e05time[by] << bi) & 0x80 & e05state); - return v; + return v; } @@ -5,14 +5,14 @@ #include <SDL.h> -extern void screen_init(bool, bool); -extern void screen_reset(void); -extern void screen_write(int, int); -extern void screen_flush(void); -extern void setmode40(bool); +extern void screen_init(bool, bool); +extern void screen_reset(void); +extern void screen_write(int, int); +extern void screen_flush(void); +extern void setmode40(bool); -extern void event_loop(void); -extern void key_check(void); +extern void event_loop(void); +extern void key_check(void); extern volatile int event_pending; Uint32 post_periodic(Uint32 interval, void *param); @@ -21,6 +21,6 @@ extern void crtc_out(uint8_t, uint8_t); extern uint8_t crtc_in(uint8_t); /* Pointer into video RAM */ -extern uint8_t * const video_ram; +extern uint8_t *const video_ram; #endif /* _SCREEN_H */ diff --git a/screenshot.c b/screenshot.c index ad14f85..6b76143 100644 --- a/screenshot.c +++ b/screenshot.c @@ -12,14 +12,14 @@ const char *screen_path; -static inline void *pixel_row(const SDL_Surface *surf, size_t y) +static inline void *pixel_row(const SDL_Surface * surf, size_t y) { - return (uint8_t *)surf->pixels + (y * surf->pitch); + return (uint8_t *) surf->pixels + (y * surf->pitch); } struct sort_pixel { - uint32_t pix; /* Pixel value */ - uint32_t pos; /* Position index */ + uint32_t pix; /* Pixel value */ + uint32_t pos; /* Position index */ }; static int sort_by_pixel(const void *vp1, const void *vp2) @@ -31,7 +31,7 @@ static int sort_by_pixel(const void *vp1, const void *vp2) return -(pix1 < pix2) | (pix1 > pix2); } -static inline bool get_pixels(SDL_Surface *surf, struct sort_pixel *ppp) +static inline bool get_pixels(SDL_Surface * surf, struct sort_pixel *ppp) { uint8_t *pvp; int x, y; @@ -41,98 +41,98 @@ static inline bool get_pixels(SDL_Surface *surf, struct sort_pixel *ppp) switch (bytes) { case 1: - for (y = 0; y < surf->h; y++) { - pvp = pixel_row(surf, y); - for (x = 0; x < surf->w; x++) { - andbits &= ppp->pix = *(uint8_t *)pvp; - pvp += bytes; - ppp->pos = pos++; - ppp++; - } - } - break; + for (y = 0; y < surf->h; y++) { + pvp = pixel_row(surf, y); + for (x = 0; x < surf->w; x++) { + andbits &= ppp->pix = *(uint8_t *) pvp; + pvp += bytes; + ppp->pos = pos++; + ppp++; + } + } + break; case 2: - for (y = 0; y < surf->h; y++) { - pvp = pixel_row(surf, y); - for (x = 0; x < surf->w; x++) { - andbits &= ppp->pix = *(uint16_t *)pvp; - pvp += bytes; - ppp->pos = pos++; - ppp++; - } - } - break; + for (y = 0; y < surf->h; y++) { + pvp = pixel_row(surf, y); + for (x = 0; x < surf->w; x++) { + andbits &= ppp->pix = *(uint16_t *) pvp; + pvp += bytes; + ppp->pos = pos++; + ppp++; + } + } + break; case 3: - for (y = 0; y < surf->h; y++) { - pvp = pixel_row(surf, y); - for (x = 0; x < surf->w; x++) { + for (y = 0; y < surf->h; y++) { + pvp = pixel_row(surf, y); + for (x = 0; x < surf->w; x++) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN - andbits &= ppp->pix = pvp[0] | (pvp[1] << 8) | (pvp[2] << 16); + andbits &= ppp->pix = pvp[0] | (pvp[1] << 8) | (pvp[2] << 16); #else - andbits &= ppp->pix = pvp[2] | (pvp[1] << 8) | (pvp[0] << 16); + andbits &= ppp->pix = pvp[2] | (pvp[1] << 8) | (pvp[0] << 16); #endif - pvp += bytes; - ppp->pos = pos++; - ppp++; - } - } - break; + pvp += bytes; + ppp->pos = pos++; + ppp++; + } + } + break; case 4: - for (y = 0; y < surf->h; y++) { - pvp = pixel_row(surf, y); - for (x = 0; x < surf->w; x++) { - andbits &= ppp->pix = *(uint32_t *)pvp; - pvp += bytes; - ppp->pos = pos++; - ppp++; - } - } - break; + for (y = 0; y < surf->h; y++) { + pvp = pixel_row(surf, y); + for (x = 0; x < surf->w; x++) { + andbits &= ppp->pix = *(uint32_t *) pvp; + pvp += bytes; + ppp->pos = pos++; + ppp++; + } + } + break; default: - abort(); - break; + abort(); + break; } /* Return true if we have a nontrivial alpha channel */ return !surf->format->palette && - (andbits & surf->format->Amask) != surf->format->Amask; + (andbits & surf->format->Amask) != surf->format->Amask; } #define MAX_PALETTE 256 /* Returns the number of indicies, or -1 on failure */ static int -make_indexed(SDL_Surface *surf, uint8_t **data, png_color **palettep, - uint8_t **apalettep) +make_indexed(SDL_Surface * surf, uint8_t ** data, png_color ** palettep, + uint8_t ** apalettep) { - struct sort_pixel *pixp = NULL; /* Pixel pointers */ - struct sort_pixel *ppp; /* Pixel pointer pointer */ - size_t np; /* Total number of pixels */ + struct sort_pixel *pixp = NULL; /* Pixel pointers */ + struct sort_pixel *ppp; /* Pixel pointer pointer */ + size_t np; /* Total number of pixels */ size_t i; - int last_index; /* Last allocated index */ - uint32_t last_pixel; /* Last equivalent pixel */ - SDL_PixelFormat *fmt; /* Cached for speed */ - bool surface_copy = false; /* We copied the surface */ - uint8_t *iimg = NULL; /* Actual indexed image */ - png_color *palette = NULL; /* Primary palette */ - uint8_t *apalette; /* Alpha palette */ + int last_index; /* Last allocated index */ + uint32_t last_pixel; /* Last equivalent pixel */ + SDL_PixelFormat *fmt; /* Cached for speed */ + bool surface_copy = false; /* We copied the surface */ + uint8_t *iimg = NULL; /* Actual indexed image */ + png_color *palette = NULL; /* Primary palette */ + uint8_t *apalette; /* Alpha palette */ bool hasalpha = false; /* This is kind of an idiotic algorithm, but it works and is kind of fun */ /* 1. Allocate arrays and initialize the position array */ - np = surf->w * surf->h; /* Total pixels */ + np = surf->w * surf->h; /* Total pixels */ iimg = malloc(np); if (!iimg) - goto err; + goto err; pixp = malloc(np * sizeof *pixp); if (!pixp) - goto err; + goto err; palette = calloc(MAX_PALETTE, (sizeof *palette + sizeof *apalette)); if (!palette) - goto err; + goto err; SDL_LockSurface(surf); fmt = surf->format; @@ -144,47 +144,46 @@ make_indexed(SDL_Surface *surf, uint8_t **data, png_color **palettep, /* 3. Create palette and index values */ ppp = pixp; - last_pixel = ~ppp->pix; /* Make sure we don't match on the first */ + last_pixel = ~ppp->pix; /* Make sure we don't match on the first */ last_index = -1; - apalette = (uint8_t *)&palette[MAX_PALETTE]; + apalette = (uint8_t *) & palette[MAX_PALETTE]; for (i = 0; i < np; i++) { - if (ppp->pix != last_pixel) { - last_pixel = ppp->pix; - last_index++; - if (last_index >= MAX_PALETTE) - goto err; - SDL_GetRGBA(last_pixel, fmt, - &palette[last_index].red, - &palette[last_index].green, - &palette[last_index].blue, - &apalette[last_index]); - - hasalpha |= apalette[last_index] != 0xff; - } - iimg[ppp->pos] = last_index; - ppp++; + if (ppp->pix != last_pixel) { + last_pixel = ppp->pix; + last_index++; + if (last_index >= MAX_PALETTE) + goto err; + SDL_GetRGBA(last_pixel, fmt, + &palette[last_index].red, + &palette[last_index].green, + &palette[last_index].blue, &apalette[last_index]); + + hasalpha |= apalette[last_index] != 0xff; + } + iimg[ppp->pos] = last_index; + ppp++; } /* Done! */ - last_index++; /* Convert to a count */ + last_index++; /* Convert to a count */ common_exit: *data = iimg; *palettep = palette; *apalettep = hasalpha ? apalette : NULL; if (pixp) - free(pixp); + free(pixp); if (surface_copy && surf) - SDL_FreeSurface(surf); + SDL_FreeSurface(surf); return last_index; err: if (palette) { - free(palette); - palette = NULL; + free(palette); + palette = NULL; } if (iimg) { - free(iimg); - iimg = NULL; + free(iimg); + iimg = NULL; } last_index = hasalpha ? -2 : -1; goto common_exit; @@ -205,61 +204,61 @@ static void my_png_warning(png_structp png, png_const_charp warnmsg) /* This is the pixel format that PNG uses in 8-bit RGB and RGBA modes */ static SDL_PixelFormat pngfmts[2] = { { - /* RGB format */ + /* RGB format */ - NULL, /* palette */ - 24, /* bits per pixel */ - 3, /* bytes per pixel */ - 0, 0, 0, 8, /* precision loss (8 = all alpha lost) */ + NULL, /* palette */ + 24, /* bits per pixel */ + 3, /* bytes per pixel */ + 0, 0, 0, 8, /* precision loss (8 = all alpha lost) */ #if SDL_BYTEORDER == SDL_LIL_ENDIAN - 0, /* Rshift */ - 8, /* Gshift */ - 16, /* Bshift */ - 0, /* Ashift */ - 0x000000ff, /* Rmask */ - 0x0000ff00, /* Gmask */ - 0x00ff0000, /* Bmask */ + 0, /* Rshift */ + 8, /* Gshift */ + 16, /* Bshift */ + 0, /* Ashift */ + 0x000000ff, /* Rmask */ + 0x0000ff00, /* Gmask */ + 0x00ff0000, /* Bmask */ #else - 16, /* Rshift */ - 8, /* Gshift */ - 0, /* Bshift */ - 0, /* Ashift */ - 0x00ff0000, /* Rmask */ - 0x0000ff00, /* Gmask */ - 0x000000ff, /* Bmask */ + 16, /* Rshift */ + 8, /* Gshift */ + 0, /* Bshift */ + 0, /* Ashift */ + 0x00ff0000, /* Rmask */ + 0x0000ff00, /* Gmask */ + 0x000000ff, /* Bmask */ #endif - 0x00000000, /* Amask */ - 0, /* No actual color key */ - 255 /* Completely opaque */ - }, { - /* RGBA format */ - - NULL, /* palette */ - 32, /* bits per pixel */ - 4, /* bytes per pixel */ - 0, 0, 0, 0, /* precision loss (none) */ + 0x00000000, /* Amask */ + 0, /* No actual color key */ + 255 /* Completely opaque */ + }, { + /* RGBA format */ + + NULL, /* palette */ + 32, /* bits per pixel */ + 4, /* bytes per pixel */ + 0, 0, 0, 0, /* precision loss (none) */ #if SDL_BYTEORDER == SDL_LIL_ENDIAN - 0, /* Rshift */ - 8, /* Gshift */ - 16, /* Bshift */ - 24, /* Ashift */ - 0x000000ff, /* Rmask */ - 0x0000ff00, /* Gmask */ - 0x00ff0000, /* Bmask */ - 0xff000000, /* Amask */ + 0, /* Rshift */ + 8, /* Gshift */ + 16, /* Bshift */ + 24, /* Ashift */ + 0x000000ff, /* Rmask */ + 0x0000ff00, /* Gmask */ + 0x00ff0000, /* Bmask */ + 0xff000000, /* Amask */ #else - 24, /* Rshift */ - 16, /* Gshift */ - 8, /* Bshift */ - 0, /* Ashift */ - 0xff000000, /* Rmask */ - 0x00ff0000, /* Gmask */ - 0x0000ff00, /* Bmask */ - 0x000000ff, /* Amask */ + 24, /* Rshift */ + 16, /* Gshift */ + 8, /* Bshift */ + 0, /* Ashift */ + 0xff000000, /* Rmask */ + 0x00ff0000, /* Gmask */ + 0x0000ff00, /* Bmask */ + 0x000000ff, /* Amask */ #endif - 0, /* No actual color key */ - 255 /* Completely opaque */ - } + 0, /* No actual color key */ + 255 /* Completely opaque */ + } }; /* @@ -268,17 +267,17 @@ static SDL_PixelFormat pngfmts[2] = { * we may have to deallocate or clean up. */ struct allocable { - uint8_t *img; /* Image data */ - SDL_Surface *rgbsurf; /* RGB converted surface */ - png_bytepp rowptrs; /* Array of row pointers */ - png_color *palette; /* Palette data */ - uint8_t *apalette; /* Alpha palette data (does not need freeing) */ - png_structp png; /* PNG write structure */ - png_infop png_info; /* PNG info structure */ - struct host_file *hf; /* Host file structure */ + uint8_t *img; /* Image data */ + SDL_Surface *rgbsurf; /* RGB converted surface */ + png_bytepp rowptrs; /* Array of row pointers */ + png_color *palette; /* Palette data */ + uint8_t *apalette; /* Alpha palette data (does not need freeing) */ + png_structp png; /* PNG write structure */ + png_infop png_info; /* PNG info structure */ + struct host_file *hf; /* Host file structure */ }; -static int do_screenshot(SDL_Surface *surf, struct allocable *a) +static int do_screenshot(SDL_Surface * surf, struct allocable *a) { uint8_t *row; size_t bytes_per_row; @@ -296,68 +295,68 @@ static int do_screenshot(SDL_Surface *surf, struct allocable *a) /* Allocate row pointers */ a->rowptrs = malloc(surf->h * sizeof *a->rowptrs); if (!a->rowptrs) - return -1; + return -1; /* First, try an indexed image */ npalette = make_indexed(surf, &a->img, &a->palette, &a->apalette); if (npalette > 0) { - color_type = PNG_COLOR_TYPE_PALETTE; - if (npalette <= 2) - depth = 1; - else if (npalette <= 4) - depth = 2; - else if (npalette <= 16) - depth = 4; - else - depth = 8; - - bytes_per_row = surf->w; - row = a->img; + color_type = PNG_COLOR_TYPE_PALETTE; + if (npalette <= 2) + depth = 1; + else if (npalette <= 4) + depth = 2; + else if (npalette <= 16) + depth = 4; + else + depth = 8; + + bytes_per_row = surf->w; + row = a->img; } else { - bool is_rgba = npalette == -2; - SDL_PixelFormat fmt = pngfmts[is_rgba]; - color_type = is_rgba ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB; - - a->rgbsurf = SDL_ConvertSurface(surf, &fmt, SDL_SWSURFACE); - if (!a->rgbsurf) - return -1; - - SDL_LockSurface(a->rgbsurf); - depth = 8; - bytes_per_row = a->rgbsurf->pitch; - row = a->rgbsurf->pixels; + bool is_rgba = npalette == -2; + SDL_PixelFormat fmt = pngfmts[is_rgba]; + color_type = is_rgba ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB; + + a->rgbsurf = SDL_ConvertSurface(surf, &fmt, SDL_SWSURFACE); + if (!a->rgbsurf) + return -1; + + SDL_LockSurface(a->rgbsurf); + depth = 8; + bytes_per_row = a->rgbsurf->pitch; + row = a->rgbsurf->pixels; } /* Generate row pointers */ rowptr = a->rowptrs; for (y = 0; y < surf->h; y++) { - *rowptr++ = row; - row += bytes_per_row; + *rowptr++ = row; + row += bytes_per_row; } /* Create a PNG write and info structures */ a->png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, - my_png_error, my_png_warning); + my_png_error, my_png_warning); if (!a->png) - return -1; + return -1; a->png_info = png_create_info_struct(a->png); if (!a->png_info) - return -1; + return -1; if (setjmp(png_jmpbuf(a->png))) - return -1; + return -1; /* Open screenshot file */ a->hf = dump_file(HF_BINARY, screen_path, "scrn%04u.png"); if (!a->hf) - return -1; + return -1; png_init_io(a->png, a->hf->f); /* IHDR configuration */ png_set_IHDR(a->png, a->png_info, surf->w, surf->h, depth, color_type, - PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); + PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); png_set_tIME(a->png, a->png_info, &png_now); @@ -365,30 +364,30 @@ static int do_screenshot(SDL_Surface *surf, struct allocable *a) png_set_compression_strategy(a->png, Z_FILTERED); if (npalette > 0) { - png_set_PLTE(a->png, a->png_info, a->palette, npalette); - if (a->apalette) { - int napalette = npalette; - while (napalette > 0) { - if (a->apalette[napalette-1] < 0xff) - break; - napalette--; - } - if (napalette) - png_set_tRNS(a->png, a->png_info, a->apalette, napalette, NULL); - } + png_set_PLTE(a->png, a->png_info, a->palette, npalette); + if (a->apalette) { + int napalette = npalette; + while (napalette > 0) { + if (a->apalette[napalette - 1] < 0xff) + break; + napalette--; + } + if (napalette) + png_set_tRNS(a->png, a->png_info, a->apalette, napalette, NULL); + } } png_set_rows(a->png, a->png_info, a->rowptrs); png_write_png(a->png, a->png_info, - (depth < 8) ? PNG_TRANSFORM_PACKING : PNG_TRANSFORM_IDENTITY, - NULL); + (depth < 8) ? PNG_TRANSFORM_PACKING : PNG_TRANSFORM_IDENTITY, + NULL); - keep_file(a->hf); /* We did it! */ + keep_file(a->hf); /* We did it! */ return 0; } -int screenshot(SDL_Surface *surf) +int screenshot(SDL_Surface * surf) { struct allocable a; int rv, err; @@ -398,17 +397,17 @@ int screenshot(SDL_Surface *surf) err = errno; if (a.rgbsurf) { - SDL_UnlockSurface(a.rgbsurf); - SDL_FreeSurface(a.rgbsurf); + SDL_UnlockSurface(a.rgbsurf); + SDL_FreeSurface(a.rgbsurf); } if (a.png) - png_destroy_write_struct(&a.png, &a.png_info); + png_destroy_write_struct(&a.png, &a.png_info); if (a.palette) - free(a.palette); + free(a.palette); if (a.img) - free(a.img); + free(a.img); if (a.rowptrs) - free(a.rowptrs); + free(a.rowptrs); close_file(&a.hf); @@ -25,7 +25,7 @@ #define FONT_XSIZE 6 #define FONT_YSIZE 10 -#define FONT_XDUP 2 /* For 80-column mode */ +#define FONT_XDUP 2 /* For 80-column mode */ #define FONT_YDUP 3 #define PX_WIDTH (TS_WIDTH*FONT_XSIZE*FONT_XDUP) @@ -37,15 +37,25 @@ static void trigger_refresh(void); #define NCOLORS 8 -static struct argb { uint8_t a, r, g, b; } rgbcolors[NCOLORS] = { - {0x00,0x00,0x00,0x00}, /* black */ - {0x00,0xff,0x00,0x00}, /* red */ - {0x00,0x00,0xff,0x00}, /* green */ - {0x00,0xff,0xff,0x00}, /* yellow */ - {0x00,0x00,0x00,0xff}, /* blue */ - {0x00,0xff,0x00,0xff}, /* purple */ - {0x00,0x00,0xff,0xff}, /* cyan */ - {0x00,0xff,0xff,0xff}, /* white */ +static struct argb { + uint8_t a, r, g, b; +} rgbcolors[NCOLORS] = { + { + 0x00, 0x00, 0x00, 0x00}, /* black */ + { + 0x00, 0xff, 0x00, 0x00}, /* red */ + { + 0x00, 0x00, 0xff, 0x00}, /* green */ + { + 0x00, 0xff, 0xff, 0x00}, /* yellow */ + { + 0x00, 0x00, 0x00, 0xff}, /* blue */ + { + 0x00, 0xff, 0x00, 0xff}, /* purple */ + { + 0x00, 0x00, 0xff, 0xff}, /* cyan */ + { + 0x00, 0xff, 0xff, 0xff}, /* white */ }; /* Mutex for interaction with the CPU thread */ @@ -55,25 +65,25 @@ static SDL_mutex *screen_mutex; #define VRAM_MASK (VRAM_SIZE-1) union crtc { - uint8_t regs[18]; - struct { - uint8_t htotal; /* Horizontal total characters */ - uint8_t hdisp; /* Horizontal displayed characters */ - uint8_t hsyncpos; /* Horizontal sync position (char units) */ - uint8_t hsyncwidth; /* Horizontal sync width (char units) */ - uint8_t vscantotal; /* Vertical total (char units) */ - uint8_t vadjust; /* Vertical adjust scan lines */ - uint8_t vdisplay; /* Displayed character rows */ - uint8_t vsyncpos; /* Vertical sync position */ - uint8_t interlace; /* Interlace mode */ - uint8_t maxscan; /* Maximum scan line address */ - uint8_t curstart; /* Cursor start line */ - uint8_t curend; /* Cursor end line */ - uint8_t starth; /* High half of start address */ - uint8_t startl; /* Low half of start address */ - uint8_t curh; /* High half of cursor address */ - uint8_t curl; /* Low half of cursor address */ - } r; + uint8_t regs[18]; + struct { + uint8_t htotal; /* Horizontal total characters */ + uint8_t hdisp; /* Horizontal displayed characters */ + uint8_t hsyncpos; /* Horizontal sync position (char units) */ + uint8_t hsyncwidth; /* Horizontal sync width (char units) */ + uint8_t vscantotal; /* Vertical total (char units) */ + uint8_t vadjust; /* Vertical adjust scan lines */ + uint8_t vdisplay; /* Displayed character rows */ + uint8_t vsyncpos; /* Vertical sync position */ + uint8_t interlace; /* Interlace mode */ + uint8_t maxscan; /* Maximum scan line address */ + uint8_t curstart; /* Cursor start line */ + uint8_t curend; /* Cursor end line */ + uint8_t starth; /* High half of start address */ + uint8_t startl; /* Low half of start address */ + uint8_t curh; /* High half of cursor address */ + uint8_t curl; /* Low half of cursor address */ + } r; }; /* @@ -82,39 +92,39 @@ union crtc { * generation. */ struct video_state { - union crtc crtc; - uint16_t startaddr; /* Position of the first character */ - uint16_t curaddr; /* Memory position of the CRTC cursor */ - bool mode40; - bool blink_on; - uint8_t vram[VRAM_SIZE]; + union crtc crtc; + uint16_t startaddr; /* Position of the first character */ + uint16_t curaddr; /* Memory position of the CRTC cursor */ + bool mode40; + bool blink_on; + uint8_t vram[VRAM_SIZE]; }; static struct video_state cpu, xfr, vdu; -uint8_t * const video_ram = cpu.vram; +uint8_t *const video_ram = cpu.vram; struct xy { - uint8_t x, y; + uint8_t x, y; }; static struct xy addr_to_xy_tbl[2][2048]; /* A local abstraction of a drawing surface */ struct surface { - SDL_Surface *surf; /* SDL_Surface object */ + SDL_Surface *surf; /* SDL_Surface object */ Uint32 colors[NCOLORS]; - int lock_count; /* Lock nesting count */ - uint64_t updated; /* Time stamp of last update */ + int lock_count; /* Lock nesting count */ + uint64_t updated; /* Time stamp of last update */ }; -static struct surface rscreen; /* The "physical" screen surface */ +static struct surface rscreen; /* The "physical" screen surface */ /* * Give the x,y coordinates for a given location in shadow video RAM */ -static inline struct xy addr_to_xy(const uint8_t *p) +static inline struct xy addr_to_xy(const uint8_t * p) { - uint16_t addr = p - vdu.vram; - addr = (addr - vdu.startaddr) & VRAM_MASK; - return addr_to_xy_tbl[vdu.mode40][addr]; + uint16_t addr = p - vdu.vram; + addr = (addr - vdu.startaddr) & VRAM_MASK; + return addr_to_xy_tbl[vdu.mode40][addr]; } /* @@ -124,20 +134,20 @@ static inline unsigned int screenoffs(uint8_t y, uint8_t x, bool m40) { size_t offs = -1; - switch (model) { - case MODEL_ABC80: - if (m40) - offs = 1024 + (((y >> 3)*5) << 3) + ((y & 7) << 7) + x; - else - offs = (((y >> 3)*5) << 4) + ((y & 7) << 8) + x; - break; - - case MODEL_ABC802: - offs = (y * 80) + (x << m40); - break; - } + switch (model) { + case MODEL_ABC80: + if (m40) + offs = 1024 + (((y >> 3) * 5) << 3) + ((y & 7) << 7) + x; + else + offs = (((y >> 3) * 5) << 4) + ((y & 7) << 8) + x; + break; + + case MODEL_ABC802: + offs = (y * 80) + (x << m40); + break; + } - return offs; + return offs; } /* @@ -145,7 +155,7 @@ static inline unsigned int screenoffs(uint8_t y, uint8_t x, bool m40) */ static inline uint8_t screendata(uint8_t y, uint8_t x) { - return vdu.vram[(screenoffs(y,x,vdu.mode40) + vdu.startaddr) & VRAM_MASK]; + return vdu.vram[(screenoffs(y, x, vdu.mode40) + vdu.startaddr) & VRAM_MASK]; } /* @@ -153,18 +163,18 @@ static inline uint8_t screendata(uint8_t y, uint8_t x) */ static void lock_screen(struct surface *s) { - if (!s->lock_count++) - SDL_LockSurface(s->surf); + if (!s->lock_count++) + SDL_LockSurface(s->surf); } static void unlock_screen(struct surface *s) { - if (s->lock_count > 0) - SDL_UnlockSurface(s->surf); - else if (unlikely(s->lock_count < 0)) - abort(); /* SHOULD NEVER HAPPEN */ + if (s->lock_count > 0) + SDL_UnlockSurface(s->surf); + else if (unlikely(s->lock_count < 0)) + abort(); /* SHOULD NEVER HAPPEN */ - s->lock_count--; + s->lock_count--; } /* @@ -173,84 +183,83 @@ static void unlock_screen(struct surface *s) * yet... */ - static void put_screen(struct surface *s, unsigned int tx, unsigned int ty, bool blink) { - const unsigned char *fontp; - unsigned int voffs; - unsigned char v, vv; - uint32_t *pixelp, *pixelpp, fgp, bgp; - unsigned int x, xx, y, yy, gx; - uint32_t curmask; - unsigned char gmode, fg, bg; - unsigned char cc, invmask; - unsigned int xdup = FONT_XDUP << vdu.mode40; - - if (tx >= (unsigned int)(TS_WIDTH >> vdu.mode40) || - ty >= (unsigned int)TS_HEIGHT) - return; - - bg = 0; /* XXX: handle NWBG */ - fg = 7; - - gmode = 0; - for ( gx = 0 ; gx < tx ; gx++ ) { - cc = screendata(ty,gx); - if ( (cc & 0x68) == 0 ) { - gmode = (cc & 0x10) << 3; - fg = (cc & 0x07); + const unsigned char *fontp; + unsigned int voffs; + unsigned char v, vv; + uint32_t *pixelp, *pixelpp, fgp, bgp; + unsigned int x, xx, y, yy, gx; + uint32_t curmask; + unsigned char gmode, fg, bg; + unsigned char cc, invmask; + unsigned int xdup = FONT_XDUP << vdu.mode40; + + if (tx >= (unsigned int)(TS_WIDTH >> vdu.mode40) || + ty >= (unsigned int)TS_HEIGHT) + return; + + bg = 0; /* XXX: handle NWBG */ + fg = 7; + + gmode = 0; + for (gx = 0; gx < tx; gx++) { + cc = screendata(ty, gx); + if ((cc & 0x68) == 0) { + gmode = (cc & 0x10) << 3; + fg = (cc & 0x07); + } } - } - - voffs = screenoffs(ty,tx,vdu.mode40) + vdu.startaddr; - cc = vdu.vram[voffs & VRAM_MASK]; - fontp = abc_font[(cc & 0x7f) + gmode]; - invmask = (blink || model != MODEL_ABC80) ? 0x80 : 0; - invmask = (cc & invmask) ? 7 : 0; - bg ^= invmask; - fg ^= invmask; - - bgp = s->colors[bg]; - fgp = s->colors[fg]; - - pixelp = ((uint32_t *) s->surf->pixels) + - ty*PX_WIDTH*FONT_YSIZE*FONT_YDUP + - ((tx*FONT_XSIZE*FONT_XDUP) << vdu.mode40); - - curmask = 0; - if (unlikely(voffs == vdu.curaddr)) { - if (blink | (vdu.crtc.r.curstart & 0x40)) { - curmask = (~0U << (vdu.crtc.r.curstart & 0x1f)); - curmask &= (2U << (vdu.crtc.r.curend & 0x1f))-1; + + voffs = screenoffs(ty, tx, vdu.mode40) + vdu.startaddr; + cc = vdu.vram[voffs & VRAM_MASK]; + fontp = abc_font[(cc & 0x7f) + gmode]; + invmask = (blink || model != MODEL_ABC80) ? 0x80 : 0; + invmask = (cc & invmask) ? 7 : 0; + bg ^= invmask; + fg ^= invmask; + + bgp = s->colors[bg]; + fgp = s->colors[fg]; + + pixelp = ((uint32_t *) s->surf->pixels) + + ty * PX_WIDTH * FONT_YSIZE * FONT_YDUP + + ((tx * FONT_XSIZE * FONT_XDUP) << vdu.mode40); + + curmask = 0; + if (unlikely(voffs == vdu.curaddr)) { + if (blink | (vdu.crtc.r.curstart & 0x40)) { + curmask = (~0U << (vdu.crtc.r.curstart & 0x1f)); + curmask &= (2U << (vdu.crtc.r.curend & 0x1f)) - 1; + } } - } - - for ( y = 0 ; y < FONT_YSIZE ; y++ ) { - vv = *fontp++; - if (curmask & 1) - vv = 0x3f; - curmask >>= 1; - for ( yy = 0 ; yy < FONT_YDUP ; yy++ ) { - v = vv; - pixelpp = pixelp; - for ( x = 0 ; x < FONT_XSIZE ; x++ ) { - for ( xx = 0 ; xx < xdup ; xx++) { - *pixelpp++ = (v & 0x80) ? fgp : bgp; - } - v <<= 1; - } - pixelp += PX_WIDTH; + + for (y = 0; y < FONT_YSIZE; y++) { + vv = *fontp++; + if (curmask & 1) + vv = 0x3f; + curmask >>= 1; + for (yy = 0; yy < FONT_YDUP; yy++) { + v = vv; + pixelpp = pixelp; + for (x = 0; x < FONT_XSIZE; x++) { + for (xx = 0; xx < xdup; xx++) { + *pixelpp++ = (v & 0x80) ? fgp : bgp; + } + v <<= 1; + } + pixelp += PX_WIDTH; + } } - } } static void update_screen(struct surface *s) { - if (s->lock_count > 0) - return; + if (s->lock_count > 0) + return; - SDL_Flip(s->surf); + SDL_Flip(s->surf); } /* @@ -259,25 +268,25 @@ static void update_screen(struct surface *s) */ static void refresh_screen(struct surface *s, bool force_blink) { - unsigned int x, y; - unsigned int width; - bool blink; + unsigned int x, y; + unsigned int width; + bool blink; - SDL_mutexP(screen_mutex); - vdu = xfr; - SDL_mutexV(screen_mutex); + SDL_mutexP(screen_mutex); + vdu = xfr; + SDL_mutexV(screen_mutex); - width = TS_WIDTH >> vdu.mode40; - blink = force_blink | vdu.blink_on; + width = TS_WIDTH >> vdu.mode40; + blink = force_blink | vdu.blink_on; - lock_screen(s); + lock_screen(s); - for (y = 0; y < TS_HEIGHT; y++) - for (x = 0; x < width; x++) - put_screen(s, x, y, blink); + for (y = 0; y < TS_HEIGHT; y++) + for (x = 0; x < width; x++) + put_screen(s, x, y, blink); - unlock_screen(s); - update_screen(s); + unlock_screen(s); + update_screen(s); } /* Called in CPU thread context */ @@ -285,7 +294,7 @@ void setmode40(bool m40) { cpu.mode40 = m40; if (model == MODEL_ABC80) - abc80_mem_mode40(m40); + abc80_mem_mode40(m40); } /* @@ -293,21 +302,22 @@ void setmode40(bool m40) */ static struct surface *init_surface(struct surface *s) { - int i; + int i; - if (unlikely(!s || !s->surf)) - return NULL; + if (unlikely(!s || !s->surf)) + return NULL; - /* Convert colors to preferred machine representation */ - for ( i = 0 ; i < NCOLORS ; i++ ) { - s->colors[i] = SDL_MapRGB(s->surf->format, - rgbcolors[i].r, rgbcolors[i].g, rgbcolors[i].b); - } + /* Convert colors to preferred machine representation */ + for (i = 0; i < NCOLORS; i++) { + s->colors[i] = SDL_MapRGB(s->surf->format, + rgbcolors[i].r, rgbcolors[i].g, + rgbcolors[i].b); + } - /* Surface is unlocked */ - s->lock_count = 0; + /* Surface is unlocked */ + s->lock_count = 0; - return s; + return s; } /* @@ -315,16 +325,16 @@ static struct surface *init_surface(struct surface *s) */ static void abc_screenshot(void) { - struct surface s; + struct surface s; - s.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, PX_WIDTH, PX_HEIGHT, 32, - 0x00ff0000, 0x0000ff00, 0x000000ff, 0); - if (!init_surface(&s)) - return; - refresh_screen(&s, true); /* Always snapshot with blink on */ + s.surf = SDL_CreateRGBSurface(SDL_SWSURFACE, PX_WIDTH, PX_HEIGHT, 32, + 0x00ff0000, 0x0000ff00, 0x000000ff, 0); + if (!init_surface(&s)) + return; + refresh_screen(&s, true); /* Always snapshot with blink on */ - screenshot(s.surf); - SDL_FreeSurface(s.surf); + screenshot(s.surf); + SDL_FreeSurface(s.surf); } /* @@ -332,66 +342,66 @@ static void abc_screenshot(void) */ void screen_init(bool width40, bool color) { - int window = 1; /* True = run in a window */ - int debug = 1; /* False = force clean shutdown */ - int i, x, y; - - if ( SDL_Init(SDL_INIT_TIMER|SDL_INIT_VIDEO - | (debug ? SDL_INIT_NOPARACHUTE : 0)) ) - return; - - atexit(SDL_Quit); - - rscreen.surf = SDL_SetVideoMode(PX_WIDTH, PX_HEIGHT, 32, - SDL_HWSURFACE | SDL_DOUBLEBUF | - (window ? 0 : SDL_FULLSCREEN)); - - /* No mouse cursor in full screen mode */ - if ( !window ) - SDL_ShowCursor(SDL_DISABLE); - - /* If not color, then overwrite colors 1-6 with white */ - if (!color) { - for (i = 1; i < NCOLORS-1; i++) - rgbcolors[i] = rgbcolors[NCOLORS-1]; - } - - /* Initialize CRTC values to something sensible (also used by ABC80) */ - memset(&cpu, 0, sizeof cpu); - cpu.crtc.r.htotal = 80; - cpu.crtc.r.hdisp = 80; - cpu.crtc.r.vscantotal = 24; - cpu.crtc.r.vdisplay = 24; - cpu.crtc.r.curstart = 0x1f; /* No CRTC cursor */ - setmode40(width40); - vdu = xfr = cpu; - - /* Initialize reverse mapping table */ - memset(addr_to_xy_tbl, -1, sizeof addr_to_xy_tbl); - for ( i = 0 ; i < 2 ; i++ ) { - for ( y = 0 ; y < TS_HEIGHT ; y++ ) { - for ( x = 0 ; x < (TS_WIDTH >> i); x++ ) { - size_t p = screenoffs(y,x,i); - addr_to_xy_tbl[i][p].x = x; - addr_to_xy_tbl[i][p].y = y; - } + int window = 1; /* True = run in a window */ + int debug = 1; /* False = force clean shutdown */ + int i, x, y; + + if (SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO + | (debug ? SDL_INIT_NOPARACHUTE : 0))) + return; + + atexit(SDL_Quit); + + rscreen.surf = SDL_SetVideoMode(PX_WIDTH, PX_HEIGHT, 32, + SDL_HWSURFACE | SDL_DOUBLEBUF | + (window ? 0 : SDL_FULLSCREEN)); + + /* No mouse cursor in full screen mode */ + if (!window) + SDL_ShowCursor(SDL_DISABLE); + + /* If not color, then overwrite colors 1-6 with white */ + if (!color) { + for (i = 1; i < NCOLORS - 1; i++) + rgbcolors[i] = rgbcolors[NCOLORS - 1]; + } + + /* Initialize CRTC values to something sensible (also used by ABC80) */ + memset(&cpu, 0, sizeof cpu); + cpu.crtc.r.htotal = 80; + cpu.crtc.r.hdisp = 80; + cpu.crtc.r.vscantotal = 24; + cpu.crtc.r.vdisplay = 24; + cpu.crtc.r.curstart = 0x1f; /* No CRTC cursor */ + setmode40(width40); + vdu = xfr = cpu; + + /* Initialize reverse mapping table */ + memset(addr_to_xy_tbl, -1, sizeof addr_to_xy_tbl); + for (i = 0; i < 2; i++) { + for (y = 0; y < TS_HEIGHT; y++) { + for (x = 0; x < (TS_WIDTH >> i); x++) { + size_t p = screenoffs(y, x, i); + addr_to_xy_tbl[i][p].x = x; + addr_to_xy_tbl[i][p].y = y; + } + } } - } - /* Create interlock mutex */ - screen_mutex = SDL_CreateMutex(); + /* Create interlock mutex */ + screen_mutex = SDL_CreateMutex(); - if (!init_surface(&rscreen)) - return; + if (!init_surface(&rscreen)) + return; - /* Enable keyboard decoding */ - SDL_EnableUNICODE(1); + /* Enable keyboard decoding */ + SDL_EnableUNICODE(1); - /* Enable keyboard repeat */ - SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); + /* Enable keyboard repeat */ + SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); - /* Draw initial screen */ - refresh_screen(&rscreen, false); + /* Draw initial screen */ + refresh_screen(&rscreen, false); } /* @@ -399,211 +409,323 @@ void screen_init(bool width40, bool color) */ void screen_reset(void) { - /* Handled by atexit */ + /* Handled by atexit */ } /* * Event-handling loop; main loop of the event/screen thread. */ enum dump_memory_type { - DUMP_NONE, - DUMP_MEM, - DUMP_RAM + DUMP_NONE, + DUMP_MEM, + DUMP_RAM }; static volatile enum dump_memory_type dump_memory_now; void event_loop(void) { - SDL_Event event; - static int keyboard_scan = -1; /* No key currently down */ - enum kshift { - KSH_SHIFT = 1, - KSH_CTRL = 2, - KSH_ALT = 4 - } kshift; - - while ( SDL_WaitEvent(&event) ) { - switch ( event.type ) { - case SDL_KEYDOWN: - kshift = \ - ((event.key.keysym.mod & (KMOD_LALT|KMOD_RALT)) ? KSH_ALT : 0) | - ((event.key.keysym.mod & (KMOD_LCTRL|KMOD_RCTRL)) ? KSH_CTRL : 0) | - ((event.key.keysym.mod & (KMOD_LSHIFT|KMOD_RSHIFT)) ? KSH_SHIFT : 0); - - if (kshift & KSH_ALT) { - /* Alt+key are special functions */ - - switch (event.key.keysym.sym) { - case SDLK_END: - case SDLK_q: - return; /* Return to main() and exit simulator */ - - case SDLK_s: - abc_screenshot(); - break; - - case SDLK_r: - z80_reset(); - break; - - case SDLK_n: - z80_nmi(); - break; - - case SDLK_m: - dump_memory_now = DUMP_MEM; - break; - - case SDLK_u: - dump_memory_now = DUMP_RAM; - break; - - case SDLK_f: - faketype = !faketype; - break; - - default: - break; - } - } else { - int mysym = -1; - - switch (event.key.keysym.sym) { - case SDLK_LEFT: - mysym = 8; - break; - - case SDLK_RIGHT: - mysym = 9; - break; - - case SDLK_F1: - case SDLK_F2: - case SDLK_F3: - case SDLK_F4: - case SDLK_F5: - case SDLK_F6: - case SDLK_F7: - case SDLK_F8: - mysym = (event.key.keysym.sym - SDLK_F1 + 192) + ((int)kshift << 3); - break; - - case SDLK_ESCAPE: - mysym = 127; - break; - - case SDLK_SPACE: /* Ctrl+Space -> NUL */ - mysym = (kshift^KSH_CTRL) << 4; - break; - - default: - switch (event.key.keysym.unicode) { - case 1: case 2: case 3: - case 4: case 5: case 6: case 7: - case 8: case 9: case 10: case 11: - case 12: case 13: case 14: case 15: - case 16: case 17: case 18: case 19: - case 20: case 21: case 22: case 23: - case 24: case 25: case 26: case 27: - case 28: case 29: case 30: case 31: - case ' ': case '!': case '"': case '#': - case '$': case '%': case '&': case 39: - case '(': case ')': case '*': case '+': - case ',': case '-': case '.': case '/': - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - case '8': case '9': case ':': case ';': - case '=': case '?': - case '@': case 'A': case 'B': case 'C': - case 'D': case 'E': case 'F': case 'G': - case 'H': case 'I': case 'J': case 'K': - case 'L': case 'M': case 'N': case 'O': - case 'P': case 'Q': case 'R': case 'S': - case 'T': case 'U': case 'V': case 'W': - case 'X': case 'Y': case 'Z': case '[': - case 92: case ']': case '^': case '_': - case '`': case 'a': case 'b': case 'c': - case 'd': case 'e': case 'f': case 'g': - case 'h': case 'i': case 'j': case 'k': - case 'l': case 'm': case 'n': case 'o': - case 'p': case 'q': case 'r': case 's': - case 't': case 'u': case 'v': case 'w': - case 'x': case 'y': case 'z': case '{': - case '|': case '}': case '~': case 127: - mysym = event.key.keysym.unicode; - break; - case L'¤': - mysym = '$'; - break; - case L'É': - mysym = '@'; - break; - case L'Å': - mysym = ']'; - break; - case L'Ä': - mysym = '['; - break; - case L'Ö': - mysym = '\\'; - break; - case L'Ü': - mysym = '^'; - break; - case L'é': - mysym = '`'; - break; - case L'å': - mysym = '}'; - break; - case L'ä': - mysym = '{'; - break; - case L'ö': - mysym = '|'; - break; - case L'ü': - mysym = '~'; - break; - case L'<': - case L'>': - mysym = (kshift & KSH_CTRL) ? 127 : event.key.keysym.unicode; - break; - case L'§': - case L'½': - mysym = 127; - break; - default: - break; - } - if (!(mysym & ~0x1f)) { - /* Shift+Ctrl -> invert bit 4 */ - if (kshift == (KSH_CTRL|KSH_SHIFT)) - mysym ^= 0x10; - } - } - if ( mysym >= 0 ) { - /* Remember which key so we can tell when it is released */ - keyboard_scan = event.key.keysym.scancode; - keyboard_down(mysym); - } - } - break; - case SDL_KEYUP: - if ( event.key.keysym.scancode == keyboard_scan ) - keyboard_up(); - break; - case SDL_USEREVENT: - /* Time to update the screen */ - refresh_screen(&rscreen, false); - break; - case SDL_QUIT: - return; /* Return to main(), terminate */ - default: - break; + SDL_Event event; + static int keyboard_scan = -1; /* No key currently down */ + enum kshift { + KSH_SHIFT = 1, + KSH_CTRL = 2, + KSH_ALT = 4 + } kshift; + + while (SDL_WaitEvent(&event)) { + switch (event.type) { + case SDL_KEYDOWN: + kshift = + ((event.key.keysym. + mod & (KMOD_LALT | KMOD_RALT)) ? KSH_ALT : 0) | ((event.key. + keysym. + mod & + (KMOD_LCTRL + | + KMOD_RCTRL)) + ? KSH_CTRL : + 0) | ((event. + key. + keysym. + mod & + (KMOD_LSHIFT + | + KMOD_RSHIFT)) + ? + KSH_SHIFT + : 0); + + if (kshift & KSH_ALT) { + /* Alt+key are special functions */ + + switch (event.key.keysym.sym) { + case SDLK_END: + case SDLK_q: + return; /* Return to main() and exit simulator */ + + case SDLK_s: + abc_screenshot(); + break; + + case SDLK_r: + z80_reset(); + break; + + case SDLK_n: + z80_nmi(); + break; + + case SDLK_m: + dump_memory_now = DUMP_MEM; + break; + + case SDLK_u: + dump_memory_now = DUMP_RAM; + break; + + case SDLK_f: + faketype = !faketype; + break; + + default: + break; + } + } else { + int mysym = -1; + + switch (event.key.keysym.sym) { + case SDLK_LEFT: + mysym = 8; + break; + + case SDLK_RIGHT: + mysym = 9; + break; + + case SDLK_F1: + case SDLK_F2: + case SDLK_F3: + case SDLK_F4: + case SDLK_F5: + case SDLK_F6: + case SDLK_F7: + case SDLK_F8: + mysym = + (event.key.keysym.sym - SDLK_F1 + 192) + + ((int)kshift << 3); + break; + + case SDLK_ESCAPE: + mysym = 127; + break; + + case SDLK_SPACE: /* Ctrl+Space -> NUL */ + mysym = (kshift ^ KSH_CTRL) << 4; + break; + + default: + switch (event.key.keysym.unicode) { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + case 17: + case 18: + case 19: + case 20: + case 21: + case 22: + case 23: + case 24: + case 25: + case 26: + case 27: + case 28: + case 29: + case 30: + case 31: + case ' ': + case '!': + case '"': + case '#': + case '$': + case '%': + case '&': + case 39: + case '(': + case ')': + case '*': + case '+': + case ',': + case '-': + case '.': + case '/': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case ':': + case ';': + case '=': + case '?': + case '@': + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case '[': + case 92: + case ']': + case '^': + case '_': + case '`': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + case '{': + case '|': + case '}': + case '~': + case 127: + mysym = event.key.keysym.unicode; + break; + case L'¤': + mysym = '$'; + break; + case L'É': + mysym = '@'; + break; + case L'Å': + mysym = ']'; + break; + case L'Ä': + mysym = '['; + break; + case L'Ö': + mysym = '\\'; + break; + case L'Ü': + mysym = '^'; + break; + case L'é': + mysym = '`'; + break; + case L'å': + mysym = '}'; + break; + case L'ä': + mysym = '{'; + break; + case L'ö': + mysym = '|'; + break; + case L'ü': + mysym = '~'; + break; + case L'<': + case L'>': + mysym = + (kshift & KSH_CTRL) ? 127 : event.key.keysym. + unicode; + break; + case L'§': + case L'½': + mysym = 127; + break; + default: + break; + } + if (!(mysym & ~0x1f)) { + /* Shift+Ctrl -> invert bit 4 */ + if (kshift == (KSH_CTRL | KSH_SHIFT)) + mysym ^= 0x10; + } + } + if (mysym >= 0) { + /* Remember which key so we can tell when it is released */ + keyboard_scan = event.key.keysym.scancode; + keyboard_down(mysym); + } + } + break; + case SDL_KEYUP: + if (event.key.keysym.scancode == keyboard_scan) + keyboard_up(); + break; + case SDL_USEREVENT: + /* Time to update the screen */ + refresh_screen(&rscreen, false); + break; + case SDL_QUIT: + return; /* Return to main(), terminate */ + default: + break; + } } - } } /* @@ -612,25 +734,25 @@ void event_loop(void) */ void vsync_screen(void) { - const int blink_rate = 400/20; /* 400 ms/20 ms = 2.5 Hz */ - static int blink_ctr; - enum dump_memory_type dm; + const int blink_rate = 400 / 20; /* 400 ms/20 ms = 2.5 Hz */ + static int blink_ctr; + enum dump_memory_type dm; - if (!blink_ctr--) { - blink_ctr = blink_rate; - cpu.blink_on = !cpu.blink_on; - } + if (!blink_ctr--) { + blink_ctr = blink_rate; + cpu.blink_on = !cpu.blink_on; + } - trigger_refresh(); + trigger_refresh(); - if (unlikely(dump_memory_now)) { - dm = xchg(&dump_memory_now, DUMP_NONE); - if (dm) - dump_memory(dm == DUMP_RAM); - } + if (unlikely(dump_memory_now)) { + dm = xchg(&dump_memory_now, DUMP_NONE); + if (dm) + dump_memory(dm == DUMP_RAM); + } - if (traceflags) - fflush(tracef); /* So we don't buffer indefinitely */ + if (traceflags) + fflush(tracef); /* So we don't buffer indefinitely */ } /* Used from the CPU thread context to cause a screen redraw */ @@ -652,30 +774,30 @@ static uint8_t crtc_addr; void crtc_out(uint8_t port, uint8_t data) { - if (!(port & 1)) { - crtc_addr = data; - return; - } + if (!(port & 1)) { + crtc_addr = data; + return; + } - if (crtc_addr >= sizeof cpu.crtc.regs) - return; + if (crtc_addr >= sizeof cpu.crtc.regs) + return; - SDL_mutexP(screen_mutex); + SDL_mutexP(screen_mutex); - cpu.crtc.regs[crtc_addr] = data; - cpu.startaddr = ((cpu.crtc.r.starth & 0x3f) << 8) + cpu.crtc.r.startl; - cpu.curaddr = ((cpu.crtc.r.curh & 0x3f) << 8) + cpu.crtc.r.curl; + cpu.crtc.regs[crtc_addr] = data; + cpu.startaddr = ((cpu.crtc.r.starth & 0x3f) << 8) + cpu.crtc.r.startl; + cpu.curaddr = ((cpu.crtc.r.curh & 0x3f) << 8) + cpu.crtc.r.curl; - SDL_mutexV(screen_mutex); + SDL_mutexV(screen_mutex); } uint8_t crtc_in(uint8_t port) { - if (!(port & 1)) - return crtc_addr; + if (!(port & 1)) + return crtc_addr; - if (crtc_addr >= sizeof cpu.crtc.regs) - return 0xff; + if (crtc_addr >= sizeof cpu.crtc.regs) + return 0xff; - return cpu.crtc.regs[crtc_addr]; + return cpu.crtc.regs[crtc_addr]; } @@ -10,92 +10,92 @@ static int output_head, output_tail; /* Called to send data abcprint -> abc */ void abcprint_send(const void *buf, size_t count) { - const unsigned char *bp = buf; + const unsigned char *bp = buf; - while (count--) { - int nt = (output_tail + 1) % BUF_SIZE; + while (count--) { + int nt = (output_tail + 1) % BUF_SIZE; - if (nt == output_head) - return; /* Output buffer full - data lost */ + if (nt == output_head) + return; /* Output buffer full - data lost */ - output_buf[output_tail] = *bp++; - output_tail = nt; - } + output_buf[output_tail] = *bp++; + output_tail = nt; + } } static int abcprint_read(void) { - int c; - - if (output_head == output_tail) { - return -1; - } else { - c = output_buf[output_head]; - output_head = (output_head + 1) % BUF_SIZE; - return c; - } + int c; + + if (output_head == output_tail) { + return -1; + } else { + c = output_buf[output_head]; + output_head = (output_head + 1) % BUF_SIZE; + return c; + } } static bool abcprint_poll(void) { - return output_head != output_tail; + return output_head != output_tail; } static struct z80_irq dart_pr_irq; void printer_reset(void) { - static bool init = false; - - if (!init) { - init = true; - abcprint_init(); - if (model != MODEL_ABC80) - z80_register_irq(&dart_pr_irq); - } + static bool init = false; + + if (!init) { + init = true; + abcprint_init(); + if (model != MODEL_ABC80) + z80_register_irq(&dart_pr_irq); + } } void printer_out(int sel, int port, int value) { - unsigned char v = value; + unsigned char v = value; - (void)sel; + (void)sel; - switch (port) { - case 0: - abcprint_recv(&v, 1); /* Data received abc -> abcprint */ - break; + switch (port) { + case 0: + abcprint_recv(&v, 1); /* Data received abc -> abcprint */ + break; - case 4: - abcprint_init(); - break; + case 4: + abcprint_init(); + break; - default: - break; - } + default: + break; + } } int printer_in(int sel, int port) { - int v; + int v; - (void)sel; + (void)sel; - switch (port) { - case 0: - v = abcprint_read(); - break; + switch (port) { + case 0: + v = abcprint_read(); + break; - case 1: - v = abcprint_poll() ? 0x40 : 0; - break; + case 1: + v = abcprint_poll()? 0x40 : 0; + break; - default: - v = -1; - break; - } + default: + v = -1; + break; + } - return v; + return v; } /* Hardware-like interface via the ABC800 PR: port */ @@ -105,65 +105,66 @@ static struct z80_irq dart_pr_irq = IRQ(IRQ800_DARTA, NULL, NULL, NULL); void dart_pr_out(uint8_t port, uint8_t v) { - uint8_t r; - - switch (port & 1) { - case 0: /* Data port */ - if (dart_pr_ctl[5] & 0x08) - abcprint_recv(&v, 1); - break; - - case 1: /* Control port */ - r = dart_pr_ctl[0] & 7; - dart_pr_ctl[0] &= ~7; - dart_pr_ctl[r] = v; - /* Should to things like supporting interrupts here */ - break; - } + uint8_t r; + + switch (port & 1) { + case 0: /* Data port */ + if (dart_pr_ctl[5] & 0x08) + abcprint_recv(&v, 1); + break; + + case 1: /* Control port */ + r = dart_pr_ctl[0] & 7; + dart_pr_ctl[0] &= ~7; + dart_pr_ctl[r] = v; + /* Should to things like supporting interrupts here */ + break; + } } uint8_t dart_pr_in(uint8_t port) { - uint8_t r, v = 0; - - switch (port & 1) { - case 0: /* Data port */ - if (dart_pr_ctl[3] & 1) - v = abcprint_read(); - break; - - case 1: - r = dart_pr_ctl[0] & 7; - dart_pr_ctl[0] &= ~7; - - switch (r) { - case 0: /* RR0 primary status */ - /* - * 7 - 0 - No break - * 6 - 0 - No transmit underrun - * 5 - 1 - CTS# asserted - * 4 - x - RI# asserted if 80 columns on boot - * 3 - 1 - DCD# asserted - * 2 - 1 - Transmit buffer empty - * 1 - 0 - Interrupt not pending - * 0 - x - Receive character available - */ - v = 0x2c | (!startup_width40 << 4) | (dart_pr_ctl[3] & abcprint_poll()); - break; - - case 1: /* RR1 Rx special modes */ - /* - * 5 - 0 - No receiver overrun - * 4 - 0 - No parity error - * 0 - 1 - All sent - */ - v = 0x01; - break; - - default: - break; + uint8_t r, v = 0; + + switch (port & 1) { + case 0: /* Data port */ + if (dart_pr_ctl[3] & 1) + v = abcprint_read(); + break; + + case 1: + r = dart_pr_ctl[0] & 7; + dart_pr_ctl[0] &= ~7; + + switch (r) { + case 0: /* RR0 primary status */ + /* + * 7 - 0 - No break + * 6 - 0 - No transmit underrun + * 5 - 1 - CTS# asserted + * 4 - x - RI# asserted if 80 columns on boot + * 3 - 1 - DCD# asserted + * 2 - 1 - Transmit buffer empty + * 1 - 0 - Interrupt not pending + * 0 - x - Receive character available + */ + v = 0x2c | (!startup_width40 << 4) | (dart_pr_ctl[3] & + abcprint_poll()); + break; + + case 1: /* RR1 Rx special modes */ + /* + * 5 - 0 - No receiver overrun + * 4 - 0 - No parity error + * 0 - 1 - All sent + */ + v = 0x01; + break; + + default: + break; + } } - } - return v; + return v; } @@ -7,35 +7,35 @@ void trace_dump_data(const char *prefix, const void *data, unsigned int l) const uint8_t *p = data; for (i = 0; i < l; i += 16) { - fprintf(tracef, "%s: %04x : ", prefix, i); + fprintf(tracef, "%s: %04x : ", prefix, i); - for (j = 0; j < 16; j++) { - if (i+j < l) - fprintf(tracef, " %02x", p[j]); - else - fputs(" ", tracef); + for (j = 0; j < 16; j++) { + if (i + j < l) + fprintf(tracef, " %02x", p[j]); + else + fputs(" ", tracef); - if (j == 8) - fputs(" -", tracef); - } + if (j == 8) + fputs(" -", tracef); + } - fputs(" [", tracef); + fputs(" [", tracef); - for (j = 0; j < 16; j++) { - char c; + for (j = 0; j < 16; j++) { + char c; - if (i+j < l) - c = p[j]; - else - c = ' '; + if (i + j < l) + c = p[j]; + else + c = ' '; - if (c < ' ' || c > '~') - c = '.'; + if (c < ' ' || c > '~') + c = '.'; - fputc(c, tracef); - } + fputc(c, tracef); + } - fputs("]\n", tracef); - p += 16; + fputs("]\n", tracef); + p += 16; } } @@ -6,13 +6,13 @@ extern FILE *tracef; enum tracing { - TRACE_NONE = 0x00, - TRACE_CPU = 0x01, - TRACE_IO = 0x02, - TRACE_DISK = 0x04, - TRACE_CAS = 0x08, - TRACE_PR = 0x10, - TRACE_ALL = 0x1f + TRACE_NONE = 0x00, + TRACE_CPU = 0x01, + TRACE_IO = 0x02, + TRACE_DISK = 0x04, + TRACE_CAS = 0x08, + TRACE_PR = 0x10, + TRACE_ALL = 0x1f }; extern enum tracing traceflags; @@ -29,7 +29,7 @@ static inline void trace_dump(enum tracing flags, const char *prefix, const void *data, size_t l) { if (tracing(flags)) - trace_dump_data(prefix, data, l); + trace_dump_data(prefix, data, l); } #endif /* TRACE_H */ @@ -93,8 +93,7 @@ static const uint8_t clk_ED[256] = { * Tables and routines for computing various flag values: */ -static const uint8_t sign_carry_overflow_table[] = -{ +static const uint8_t sign_carry_overflow_table[] = { 0, OVERFLOW_MASK | SIGN_MASK, CARRY_MASK, @@ -105,8 +104,7 @@ static const uint8_t sign_carry_overflow_table[] = CARRY_MASK | SIGN_MASK, }; -static const uint8_t half_carry_table[] = -{ +static const uint8_t half_carry_table[] = { 0, 0, HALF_CARRY_MASK, @@ -117,8 +115,7 @@ static const uint8_t half_carry_table[] = HALF_CARRY_MASK, }; -static const uint8_t subtract_sign_carry_overflow_table[] = -{ +static const uint8_t subtract_sign_carry_overflow_table[] = { 0, CARRY_MASK | SIGN_MASK, CARRY_MASK, @@ -129,8 +126,7 @@ static const uint8_t subtract_sign_carry_overflow_table[] = CARRY_MASK | SIGN_MASK, }; -static const uint8_t subtract_half_carry_table[] = -{ +static const uint8_t subtract_half_carry_table[] = { 0, HALF_CARRY_MASK, HALF_CARRY_MASK, @@ -144,27 +140,26 @@ static const uint8_t subtract_half_carry_table[] = static int parity(unsigned value) { /* for parity flag, 1 = even parity, 0 = odd parity. */ - static const char parity_table[256] = - { - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 + static const char parity_table[256] = { + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 }; - return(parity_table[value]); + return (parity_table[value]); } static void add_r(uint8_t jump) @@ -193,13 +188,13 @@ static void do_add_flags(int a, int b, int result) */ f = REG_F & ~(SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK - | OVERFLOW_MASK | SUBTRACT_MASK | CARRY_MASK); + | OVERFLOW_MASK | SUBTRACT_MASK | CARRY_MASK); index = ((a & 0x88) >> 1) | ((b & 0x88) >> 2) | ((result & 0x88) >> 3); - f |= half_carry_table[index & 7] | - sign_carry_overflow_table[index >> 4]; + f |= half_carry_table[index & 7] | sign_carry_overflow_table[index >> 4]; - if((result & 0xFF) == 0) f |= ZERO_MASK; + if ((result & 0xFF) == 0) + f |= ZERO_MASK; REG_F = f; } @@ -217,13 +212,14 @@ static void do_sub_flags(int a, int b, int result) */ f = (REG_F | SUBTRACT_MASK) & ~(SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK - | OVERFLOW_MASK | CARRY_MASK); + | OVERFLOW_MASK | CARRY_MASK); index = ((a & 0x88) >> 1) | ((b & 0x88) >> 2) | ((result & 0x88) >> 3); f |= subtract_half_carry_table[index & 7] | - subtract_sign_carry_overflow_table[index >> 4]; + subtract_sign_carry_overflow_table[index >> 4]; - if((result & 0xFF) == 0) f |= ZERO_MASK; + if ((result & 0xFF) == 0) + f |= ZERO_MASK; REG_F = f; } @@ -241,15 +237,15 @@ static void do_adc_word_flags(int a, int b, int result) */ f = REG_F & ~(SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK - | OVERFLOW_MASK | SUBTRACT_MASK | CARRY_MASK); + | OVERFLOW_MASK | SUBTRACT_MASK | CARRY_MASK); index = ((a & 0x8800) >> 9) | ((b & 0x8800) >> 10) | - ((result & 0x8800) >> 11); + ((result & 0x8800) >> 11); - f |= half_carry_table[index & 7] | - sign_carry_overflow_table[index >> 4]; + f |= half_carry_table[index & 7] | sign_carry_overflow_table[index >> 4]; - if((result & 0xFFFF) == 0) f |= ZERO_MASK; + if ((result & 0xFFFF) == 0) + f |= ZERO_MASK; REG_F = f; } @@ -269,10 +265,10 @@ static void do_add_word_flags(int a, int b, int result) f = REG_F & ~(HALF_CARRY_MASK | SUBTRACT_MASK | CARRY_MASK); index = ((a & 0x8800) >> 9) | ((b & 0x8800) >> 10) | - ((result & 0x8800) >> 11); + ((result & 0x8800) >> 11); f |= half_carry_table[index & 7] | - (sign_carry_overflow_table[index >> 4] & CARRY_MASK); + (sign_carry_overflow_table[index >> 4] & CARRY_MASK); REG_F = f; } @@ -290,15 +286,16 @@ static void do_sbc_word_flags(int a, int b, int result) */ f = (REG_F | SUBTRACT_MASK) & ~(SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK - | OVERFLOW_MASK | CARRY_MASK); + | OVERFLOW_MASK | CARRY_MASK); index = ((a & 0x8800) >> 9) | ((b & 0x8800) >> 10) | - ((result & 0x8800) >> 11); + ((result & 0x8800) >> 11); f |= subtract_half_carry_table[index & 7] | - subtract_sign_carry_overflow_table[index >> 4]; + subtract_sign_carry_overflow_table[index >> 4]; - if((result & 0xFFFF) == 0) f |= ZERO_MASK; + if ((result & 0xFFFF) == 0) + f |= ZERO_MASK; REG_F = f; } @@ -310,14 +307,14 @@ static void do_flags_dec_byte(int value) clear = OVERFLOW_MASK | HALF_CARRY_MASK | ZERO_MASK | SIGN_MASK; set = SUBTRACT_MASK; - if(value == 0x7f) - set |= OVERFLOW_MASK; - if((value & 0xF) == 0xF) - set |= HALF_CARRY_MASK; - if(value == 0) - set |= ZERO_MASK; - if(value & 0x80) - set |= SIGN_MASK; + if (value == 0x7f) + set |= OVERFLOW_MASK; + if ((value & 0xF) == 0xF) + set |= HALF_CARRY_MASK; + if (value == 0) + set |= ZERO_MASK; + if (value & 0x80) + set |= SIGN_MASK; REG_F = (REG_F & ~clear) | set; } @@ -327,17 +324,17 @@ static void do_flags_inc_byte(int value) uint8_t clear, set; clear = SUBTRACT_MASK | OVERFLOW_MASK | HALF_CARRY_MASK | - ZERO_MASK | SIGN_MASK; + ZERO_MASK | SIGN_MASK; set = 0; - if(value == 0x80) - set |= OVERFLOW_MASK; - if((value & 0xF) == 0) - set |= HALF_CARRY_MASK; - if(value == 0) - set |= ZERO_MASK; - if(value & 0x80) - set |= SIGN_MASK; + if (value == 0x80) + set |= OVERFLOW_MASK; + if ((value & 0xF) == 0) + set |= HALF_CARRY_MASK; + if (value == 0) + set |= ZERO_MASK; + if (value & 0x80) + set |= SIGN_MASK; REG_F = (REG_F & ~clear) | set; } @@ -353,58 +350,57 @@ static void do_and_byte(int value) result = (REG_A &= value); - clear = CARRY_MASK | SUBTRACT_MASK | PARITY_MASK - | ZERO_MASK | SIGN_MASK; + clear = CARRY_MASK | SUBTRACT_MASK | PARITY_MASK | ZERO_MASK | SIGN_MASK; set = HALF_CARRY_MASK; - if(parity(result)) - set |= PARITY_MASK; - if(result == 0) - set |= ZERO_MASK; - if(result & 0x80) - set |= SIGN_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (result == 0) + set |= ZERO_MASK; + if (result & 0x80) + set |= SIGN_MASK; REG_F = (REG_F & ~clear) | set; } static void do_or_byte(int value) { - int result; /* the result of the or operation */ + int result; /* the result of the or operation */ uint8_t clear, set; result = (REG_A |= value); clear = CARRY_MASK | SUBTRACT_MASK | PARITY_MASK - | HALF_CARRY_MASK | ZERO_MASK | SIGN_MASK; + | HALF_CARRY_MASK | ZERO_MASK | SIGN_MASK; set = 0; - if(parity(result)) - set |= PARITY_MASK; - if(result == 0) - set |= ZERO_MASK; - if(result & 0x80) - set |= SIGN_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (result == 0) + set |= ZERO_MASK; + if (result & 0x80) + set |= SIGN_MASK; REG_F = (REG_F & ~clear) | set; } static void do_xor_byte(int value) { - int result; /* the result of the xor operation */ + int result; /* the result of the xor operation */ uint8_t clear, set; result = (REG_A ^= value); clear = CARRY_MASK | SUBTRACT_MASK | PARITY_MASK - | HALF_CARRY_MASK | ZERO_MASK | SIGN_MASK; + | HALF_CARRY_MASK | ZERO_MASK | SIGN_MASK; set = 0; - if(parity(result)) - set |= PARITY_MASK; - if(result == 0) - set |= ZERO_MASK; - if(result & 0x80) - set |= SIGN_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (result == 0) + set |= ZERO_MASK; + if (result & 0x80) + set |= SIGN_MASK; REG_F = (REG_F & ~clear) | set; } @@ -422,10 +418,10 @@ static void do_adc_byte(int value) { int a, result; - if(CARRY_FLAG) - result = (a = REG_A) + value + 1; + if (CARRY_FLAG) + result = (a = REG_A) + value + 1; else - result = (a = REG_A) + value; + result = (a = REG_A) + value; REG_A = result; do_add_flags(a, value, result); } @@ -444,20 +440,20 @@ static void do_negate(void) int a; a = REG_A; - REG_A = - a; + REG_A = -a; do_sub_flags(0, a, REG_A); - if(a == 0) - REG_F |= CARRY_MASK; + if (a == 0) + REG_F |= CARRY_MASK; } static void do_sbc_byte(int value) { int a, result; - if(CARRY_FLAG) - result = (a = REG_A) - (value + 1); + if (CARRY_FLAG) + result = (a = REG_A) - (value + 1); else - result = (a = REG_A) - value; + result = (a = REG_A) - value; REG_A = result; do_sub_flags(a, value, result); } @@ -466,10 +462,10 @@ static void do_adc_word(int value) { int a, result; - if(CARRY_FLAG) - result = (a = REG_HL) + value + 1; + if (CARRY_FLAG) + result = (a = REG_HL) + value + 1; else - result = (a = REG_HL) + value; + result = (a = REG_HL) + value; REG_HL = result; @@ -480,17 +476,17 @@ static void do_sbc_word(int value) { int a, result; - if(CARRY_FLAG) - result = (a = REG_HL) - (value + 1); + if (CARRY_FLAG) + result = (a = REG_HL) - (value + 1); else - result = (a = REG_HL) - value; + result = (a = REG_HL) - value; REG_HL = result; do_sbc_word_flags(a, value, result); } -static void do_add_word(wordregister *ix, int value) +static void do_add_word(wordregister * ix, int value) { int a, result; @@ -500,8 +496,8 @@ static void do_add_word(wordregister *ix, int value) do_add_word_flags(a, value, result); } -static void do_cp(int value) /* compare this value with A's contents */ -{ +static void do_cp(int value) +{ /* compare this value with A's contents */ int a, result; result = (a = REG_A) - value; @@ -516,9 +512,9 @@ static void do_cpid(int dir) REG_BC--; if (REG_BC == 0) - CLEAR_OVERFLOW(); + CLEAR_OVERFLOW(); else - SET_OVERFLOW(); + SET_OVERFLOW(); } /* dir == 1 for CPIR, -1 for CPDR */ @@ -527,8 +523,8 @@ static void do_cpidr(int dir) do_cpid(dir); if (REG_BC != 0 && !ZERO_FLAG) { - TSTATE += 5; - REG_PC -= 2; + TSTATE += 5; + REG_PC -= 2; } } @@ -539,8 +535,8 @@ static void do_test_bit(int value, int bit) clear = SIGN_MASK | ZERO_MASK | OVERFLOW_MASK | SUBTRACT_MASK; set = HALF_CARRY_MASK; - if((value & (1 << bit)) == 0) - set |= ZERO_MASK; + if ((value & (1 << bit)) == 0) + set |= ZERO_MASK; REG_F = (REG_F & ~clear) | set; } @@ -556,26 +552,23 @@ static int rl_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; - if(CARRY_FLAG) - { - result = ((value << 1) & 0xFF) | 1; - } - else - { - result = (value << 1) & 0xFF; + if (CARRY_FLAG) { + result = ((value << 1) & 0xFF) | 1; + } else { + result = (value << 1) & 0xFF; } - if(result & 0x80) - set |= SIGN_MASK; - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; - if(value & 0x80) - set |= CARRY_MASK; + if (result & 0x80) + set |= SIGN_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (value & 0x80) + set |= CARRY_MASK; REG_F = (REG_F & ~clear) | set; @@ -593,26 +586,23 @@ static int rr_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; - if(CARRY_FLAG) - { - result = (value >> 1) | 0x80; - } - else - { - result = (value >> 1); + if (CARRY_FLAG) { + result = (value >> 1) | 0x80; + } else { + result = (value >> 1); } - if(result & 0x80) - set |= SIGN_MASK; - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; - if(value & 0x1) - set |= CARRY_MASK; + if (result & 0x80) + set |= SIGN_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (value & 0x1) + set |= CARRY_MASK; REG_F = (REG_F & ~clear) | set; @@ -630,25 +620,22 @@ static int rlc_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; - if(value & 0x80) - { - result = ((value << 1) & 0xFF) | 1; - set |= CARRY_MASK; - } - else - { - result = (value << 1) & 0xFF; + if (value & 0x80) { + result = ((value << 1) & 0xFF) | 1; + set |= CARRY_MASK; + } else { + result = (value << 1) & 0xFF; } - if(result & 0x80) - set |= SIGN_MASK; - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; + if (result & 0x80) + set |= SIGN_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; REG_F = (REG_F & ~clear) | set; @@ -661,25 +648,22 @@ static int rrc_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; - if(value & 0x1) - { - result = (value >> 1) | 0x80; - set |= CARRY_MASK; - } - else - { - result = (value >> 1); /* fixed /jonas-y */ + if (value & 0x1) { + result = (value >> 1) | 0x80; + set |= CARRY_MASK; + } else { + result = (value >> 1); /* fixed /jonas-y */ } - if(result & 0x80) - set |= SIGN_MASK; - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; + if (result & 0x80) + set |= SIGN_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; REG_F = (REG_F & ~clear) | set; @@ -697,16 +681,13 @@ static void do_rla(void) clear = HALF_CARRY_MASK | SUBTRACT_MASK | CARRY_MASK; set = 0; - if(REG_A & 0x80) - set |= CARRY_MASK; + if (REG_A & 0x80) + set |= CARRY_MASK; - if(CARRY_FLAG) - { - REG_A = ((REG_A << 1) & 0xFF) | 1; - } - else - { - REG_A = (REG_A << 1) & 0xFF; + if (CARRY_FLAG) { + REG_A = ((REG_A << 1) & 0xFF) | 1; + } else { + REG_A = (REG_A << 1) & 0xFF; } REG_F = (REG_F & ~clear) | set; @@ -719,16 +700,13 @@ static void do_rra(void) clear = HALF_CARRY_MASK | SUBTRACT_MASK | CARRY_MASK; set = 0; - if(REG_A & 0x1) - set |= CARRY_MASK; + if (REG_A & 0x1) + set |= CARRY_MASK; - if(CARRY_FLAG) - { - REG_A = (REG_A >> 1) | 0x80; - } - else - { - REG_A = REG_A >> 1; + if (CARRY_FLAG) { + REG_A = (REG_A >> 1) | 0x80; + } else { + REG_A = REG_A >> 1; } REG_F = (REG_F & ~clear) | set; } @@ -740,14 +718,11 @@ static void do_rlca(void) clear = HALF_CARRY_MASK | SUBTRACT_MASK | CARRY_MASK; set = 0; - if(REG_A & 0x80) - { - REG_A = ((REG_A << 1) & 0xFF) | 1; - set |= CARRY_MASK; - } - else - { - REG_A = (REG_A << 1) & 0xFF; + if (REG_A & 0x80) { + REG_A = ((REG_A << 1) & 0xFF) | 1; + set |= CARRY_MASK; + } else { + REG_A = (REG_A << 1) & 0xFF; } REG_F = (REG_F & ~clear) | set; } @@ -759,14 +734,11 @@ static void do_rrca(void) clear = HALF_CARRY_MASK | SUBTRACT_MASK | CARRY_MASK; set = 0; - if(REG_A & 0x1) - { - REG_A = (REG_A >> 1) | 0x80; - set |= CARRY_MASK; - } - else - { - REG_A = REG_A >> 1; + if (REG_A & 0x1) { + REG_A = (REG_A >> 1) | 0x80; + set |= CARRY_MASK; + } else { + REG_A = REG_A >> 1; } REG_F = (REG_F & ~clear) | set; } @@ -777,19 +749,19 @@ static int sla_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; result = value << 1; - if(result & 0x80) - set |= SIGN_MASK; - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; - if(value & 0x80) - set |= CARRY_MASK; + if (result & 0x80) + set |= SIGN_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (value & 0x80) + set |= CARRY_MASK; REG_F = (REG_F & ~clear) | set; @@ -803,19 +775,19 @@ static int sll_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; result = (value << 1) | 1; - if(result & 0x80) - set |= SIGN_MASK; - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; - if(value & 0x80) - set |= CARRY_MASK; + if (result & 0x80) + set |= SIGN_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (value & 0x80) + set |= CARRY_MASK; REG_F = (REG_F & ~clear) | set; @@ -828,25 +800,22 @@ static int sra_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; - if(value & 0x80) - { - result = (value >> 1) & 0x80; - set |= SIGN_MASK; - } - else - { - result = value >> 1; + if (value & 0x80) { + result = (value >> 1) & 0x80; + set |= SIGN_MASK; + } else { + result = value >> 1; } - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; - if(value & 0x1) - set |= CARRY_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (value & 0x1) + set |= CARRY_MASK; REG_F = (REG_F & ~clear) | set; @@ -859,19 +828,19 @@ static int srl_byte(int value) int result; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK | CARRY_MASK; + SUBTRACT_MASK | CARRY_MASK; set = 0; result = value >> 1; - if(result & 0x80) - set |= SIGN_MASK; - if(result == 0) - set |= ZERO_MASK; - if(parity(result)) - set |= PARITY_MASK; - if(value & 0x1) - set |= CARRY_MASK; + if (result & 0x80) + set |= SIGN_MASK; + if (result == 0) + set |= ZERO_MASK; + if (parity(result)) + set |= PARITY_MASK; + if (value & 0x1) + set |= CARRY_MASK; REG_F = (REG_F & ~clear) | set; @@ -887,10 +856,10 @@ static void do_ldid(int dir) CLEAR_HALF_CARRY(); CLEAR_SUBTRACT(); - if(REG_BC == 0) - CLEAR_OVERFLOW(); + if (REG_BC == 0) + CLEAR_OVERFLOW(); else - SET_OVERFLOW(); + SET_OVERFLOW(); } static void do_ldidr(int dir) @@ -898,8 +867,8 @@ static void do_ldidr(int dir) do_ldid(dir); if (REG_BC != 0) { - TSTATE += 5; - REG_PC -= 2; + TSTATE += 5; + REG_PC -= 2; } } @@ -908,18 +877,18 @@ static void do_ld_a_ir(uint8_t val) uint8_t clear, set; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | OVERFLOW_MASK | - SUBTRACT_MASK; + SUBTRACT_MASK; set = 0; REG_A = val; - if(REG_A & 0x80) - set |= SIGN_MASK; - if(REG_A == 0) - set |= ZERO_MASK; + if (REG_A & 0x80) + set |= SIGN_MASK; + if (REG_A == 0) + set |= ZERO_MASK; - if(z80_state.iff2) - set |= OVERFLOW_MASK; + if (z80_state.iff2) + set |= OVERFLOW_MASK; REG_F = (REG_F & ~clear) | set; } @@ -936,108 +905,92 @@ static void do_daa(void) low_nibble = REG_A & 0xf; subtract_flag = SUBTRACT_FLAG; - if(subtract_flag == 0) /* add, adc, inc */ - { - if(CARRY_FLAG == 0) /* no carry */ - { - if(HALF_CARRY_FLAG == 0) /* no half-carry */ - { - if(low_nibble < 10) - { - if(high_nibble < 10) - { - add = 0x00; carry = 0; - } - else - { - add = 0x60; carry = 1; - } - } - else - { - if(high_nibble < 9) - { - add = 0x06; carry = 0; - } - else - { - add = 0x66; carry = 1; - } - } - } - else /* half-carry */ - { - if(high_nibble < 10) - { - add = 0x06; carry = 0; - } - else - { - add = 0x66; carry = 1; - } - } - } - else /* carry */ - { - if(HALF_CARRY_FLAG == 0) /* no half-carry */ - { - if(low_nibble < 10) - { - add = 0x60; carry = 1; - } - else - { - add = 0x66; carry = 1; - } - } - else /* half-carry */ - { - add = 0x66; carry = 1; - } - } - } - else /* sub, sbc, dec, neg */ - { - if(CARRY_FLAG == 0) /* no carry */ - { - if(HALF_CARRY_FLAG == 0) /* no half-carry */ - { - add = 0x00; carry = 0; - } - else /* half-carry */ - { - add = 0xFA; carry = 0; - } - } - else /* carry */ - { - if(HALF_CARRY_FLAG == 0) /* no half-carry */ - { - add = 0xA0; carry = 1; - } - else /* half-carry */ - { - add = 0x9A; carry = 1; - } - } + if (subtract_flag == 0) { /* add, adc, inc */ + if (CARRY_FLAG == 0) { /* no carry */ + if (HALF_CARRY_FLAG == 0) { /* no half-carry */ + if (low_nibble < 10) { + if (high_nibble < 10) { + add = 0x00; + carry = 0; + } else { + add = 0x60; + carry = 1; + } + } else { + if (high_nibble < 9) { + add = 0x06; + carry = 0; + } else { + add = 0x66; + carry = 1; + } + } + } else { /* half-carry */ + + if (high_nibble < 10) { + add = 0x06; + carry = 0; + } else { + add = 0x66; + carry = 1; + } + } + } else { /* carry */ + + if (HALF_CARRY_FLAG == 0) { /* no half-carry */ + if (low_nibble < 10) { + add = 0x60; + carry = 1; + } else { + add = 0x66; + carry = 1; + } + } else { /* half-carry */ + + add = 0x66; + carry = 1; + } + } + } else { /* sub, sbc, dec, neg */ + + if (CARRY_FLAG == 0) { /* no carry */ + if (HALF_CARRY_FLAG == 0) { /* no half-carry */ + add = 0x00; + carry = 0; + } else { /* half-carry */ + + add = 0xFA; + carry = 0; + } + } else { /* carry */ + + if (HALF_CARRY_FLAG == 0) { /* no half-carry */ + add = 0xA0; + carry = 1; + } else { /* half-carry */ + + add = 0x9A; + carry = 1; + } + } } - do_add_byte(add); /* adjust the value */ + do_add_byte(add); /* adjust the value */ - if(parity(REG_A)) /* This seems odd -- is it a mistake? */ - SET_PARITY(); + if (parity(REG_A)) /* This seems odd -- is it a mistake? */ + SET_PARITY(); else - CLEAR_PARITY(); + CLEAR_PARITY(); - if(subtract_flag) /* leave the subtract flag intact (right?) */ - SET_SUBTRACT(); + if (subtract_flag) /* leave the subtract flag intact (right?) */ + SET_SUBTRACT(); else - CLEAR_SUBTRACT(); + CLEAR_SUBTRACT(); - if(carry) - SET_CARRY(); + if (carry) + SET_CARRY(); else - CLEAR_CARRY(); + CLEAR_CARRY(); } static void do_rld(void) @@ -1049,7 +1002,7 @@ static void do_rld(void) uint8_t clear, set; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK; + SUBTRACT_MASK; set = 0; old_value = mem_read(REG_HL); @@ -1060,15 +1013,15 @@ static void do_rld(void) /* rotate high bits of old value into low bits of a */ REG_A = (REG_A & 0xf0) | (old_value >> 4); - if(REG_A & 0x80) - set |= SIGN_MASK; - if(REG_A == 0) - set |= ZERO_MASK; - if(parity(REG_A)) - set |= PARITY_MASK; + if (REG_A & 0x80) + set |= SIGN_MASK; + if (REG_A == 0) + set |= ZERO_MASK; + if (parity(REG_A)) + set |= PARITY_MASK; REG_F = (REG_F & ~clear) | set; - mem_write(REG_HL,new_value); + mem_write(REG_HL, new_value); } static void do_rrd(void) @@ -1080,7 +1033,7 @@ static void do_rrd(void) uint8_t clear, set; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | PARITY_MASK | - SUBTRACT_MASK; + SUBTRACT_MASK; set = 0; old_value = mem_read(REG_HL); @@ -1091,18 +1044,17 @@ static void do_rrd(void) /* rotate low bits of old value into low bits of a */ REG_A = (REG_A & 0xf0) | (old_value & 0x0f); - if(REG_A & 0x80) - set |= SIGN_MASK; - if(REG_A == 0) - set |= ZERO_MASK; - if(parity(REG_A)) - set |= PARITY_MASK; + if (REG_A & 0x80) + set |= SIGN_MASK; + if (REG_A == 0) + set |= ZERO_MASK; + if (parity(REG_A)) + set |= PARITY_MASK; REG_F = (REG_F & ~clear) | set; - mem_write(REG_HL,new_value); + mem_write(REG_HL, new_value); } - /* * Input/output instruction support: */ @@ -1113,10 +1065,10 @@ static void do_inid(int dir) REG_HL += dir; REG_B--; - if(REG_B == 0) - SET_ZERO(); + if (REG_B == 0) + SET_ZERO(); else - CLEAR_ZERO(); + CLEAR_ZERO(); SET_SUBTRACT(); } @@ -1126,8 +1078,8 @@ static void do_inidr(int dir) do_inid(dir); if (REG_B != 0) { - TSTATE += 5; - REG_PC -= 2; + TSTATE += 5; + REG_PC -= 2; } } @@ -1142,17 +1094,17 @@ static int in_with_flags(int port) uint8_t clear, set; clear = SIGN_MASK | ZERO_MASK | HALF_CARRY_MASK | - PARITY_MASK | SUBTRACT_MASK; + PARITY_MASK | SUBTRACT_MASK; set = 0; value = z80_in(port); - if(value & 0x80) - set |= SIGN_MASK; - if(value == 0) - set |= ZERO_MASK; - if(parity(value)) - set |= PARITY_MASK; + if (value & 0x80) + set |= SIGN_MASK; + if (value == 0) + set |= ZERO_MASK; + if (parity(value)) + set |= PARITY_MASK; /* What should the half-carry do? Is this a mistake? */ @@ -1167,10 +1119,10 @@ static void do_outid(int dir) REG_HL += dir; REG_B--; - if(REG_B == 0) - SET_ZERO(); + if (REG_B == 0) + SET_ZERO(); else - CLEAR_ZERO(); + CLEAR_ZERO(); SET_SUBTRACT(); } @@ -1180,8 +1132,8 @@ static void do_outidr(int dir) do_outid(dir); if (REG_B != 0) { - TSTATE += 5; - REG_PC -= 2; + TSTATE += 5; + REG_PC -= 2; } } @@ -1220,11 +1172,11 @@ static void do_nmi(void) bool nminterrupt = xchg(&z80_state.nminterrupt, false); if (!nminterrupt) - return; + return; /* handle a non-maskable interrupt */ - if (tracing(TRACE_IO|TRACE_CPU)) { - fprintf(tracef, "[%12"PRIu64"] NMI: PC=%04x\n", TSTATE, REG_PC); + if (tracing(TRACE_IO | TRACE_CPU)) { + fprintf(tracef, "[%12" PRIu64 "] NMI: PC=%04x\n", TSTATE, REG_PC); } REG_SP -= 2; @@ -1237,8 +1189,7 @@ static void do_nmi(void) TSTATE += 11; } -static void -do_int(void) +static void do_int(void) { uint16_t old_pc = REG_PC; uint64_t when = TSTATE; @@ -1246,56 +1197,56 @@ do_int(void) i_vector = z80_intack(); if (i_vector < 0) - return; + return; switch (z80_state.interrupt_mode) { case 0: - /* We blithly assume we are fed an RST instruction */ - do_di(); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = i_vector & 0x38; - TSTATE += 11; - break; + /* We blithly assume we are fed an RST instruction */ + do_di(); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = i_vector & 0x38; + TSTATE += 11; + break; case 1: do_di(); REG_SP -= 2; mem_write_word(REG_SP, REG_PC); REG_PC = 0x38; - TSTATE += 11; + TSTATE += 11; break; - case 2: + case 2: do_di(); REG_SP -= 2; mem_write_word(REG_SP, REG_PC); REG_PC = mem_read_word((z80_state.i << 8) | (i_vector & ~1)); - TSTATE += 19; + TSTATE += 19; break; - default: /* oops, unkown interrupt mode... */ + default: /* oops, unkown interrupt mode... */ break; } z80_state.iff1 = false; - if (tracing(TRACE_CPU|TRACE_IO)) { - fprintf(tracef, "[%12"PRIu64"] INT: " - "vector 0x%02x (%3d) I=%02x PC=%04x -> %04x\n", - when, i_vector, i_vector, z80_state.i, old_pc, REG_PC); + if (tracing(TRACE_CPU | TRACE_IO)) { + fprintf(tracef, "[%12" PRIu64 "] INT: " + "vector 0x%02x (%3d) I=%02x PC=%04x -> %04x\n", + when, i_vector, i_vector, z80_state.i, old_pc, REG_PC); } inc_r(); } -static uint16_t get_hl_addr(wordregister *ix) +static uint16_t get_hl_addr(wordregister * ix) { if (ix == &z80_state.hl) { - return ix->word; + return ix->word; } else { - TSTATE += 8; /* Ouch! */ - return ix->word + (int8_t)mem_fetch(REG_PC++); + TSTATE += 8; /* Ouch! */ + return ix->word + (int8_t) mem_fetch(REG_PC++); } } @@ -1303,906 +1254,905 @@ static uint16_t get_hl_addr(wordregister *ix) * Extended instructions which have 0xCB as the first byte: */ -static void do_CB_instruction(wordregister *ix) +static void do_CB_instruction(wordregister * ix) { uint8_t instruction; uint16_t addr; uint8_t data; if (ix == &z80_state.hl) { - /* - * Normal operation sans DD/FD prefix - */ - - instruction = mem_fetch(REG_PC++); - inc_r(); - - /* (HL) = 7 additional clocks, otherwise 4 */ - if ((instruction & 7) == 6) { - TSTATE += (instruction & 0xc0) == 0x40 ? 8 : 11; - } else { - TSTATE += 4; - } - - switch(instruction) - { - case 0x47: /* bit 0, a */ - do_test_bit(REG_A, 0); - break; - case 0x40: /* bit 0, b */ - do_test_bit(REG_B, 0); - break; - case 0x41: /* bit 0, c */ - do_test_bit(REG_C, 0); - break; - case 0x42: /* bit 0, d */ - do_test_bit(REG_D, 0); - break; - case 0x43: /* bit 0, e */ - do_test_bit(REG_E, 0); - break; - case 0x44: /* bit 0, h */ - do_test_bit(REG_H, 0); - break; - case 0x45: /* bit 0, l */ - do_test_bit(REG_L, 0); - break; - case 0x4F: /* bit 1, a */ - do_test_bit(REG_A, 1); - break; - case 0x48: /* bit 1, b */ - do_test_bit(REG_B, 1); - break; - case 0x49: /* bit 1, c */ - do_test_bit(REG_C, 1); - break; - case 0x4A: /* bit 1, d */ - do_test_bit(REG_D, 1); - break; - case 0x4B: /* bit 1, e */ - do_test_bit(REG_E, 1); - break; - case 0x4C: /* bit 1, h */ - do_test_bit(REG_H, 1); - break; - case 0x4D: /* bit 1, l */ - do_test_bit(REG_L, 1); - break; - case 0x57: /* bit 2, a */ - do_test_bit(REG_A, 2); - break; - case 0x50: /* bit 2, b */ - do_test_bit(REG_B, 2); - break; - case 0x51: /* bit 2, c */ - do_test_bit(REG_C, 2); - break; - case 0x52: /* bit 2, d */ - do_test_bit(REG_D, 2); - break; - case 0x53: /* bit 2, e */ - do_test_bit(REG_E, 2); - break; - case 0x54: /* bit 2, h */ - do_test_bit(REG_H, 2); - break; - case 0x55: /* bit 2, l */ - do_test_bit(REG_L, 2); - break; - case 0x5F: /* bit 3, a */ - do_test_bit(REG_A, 3); - break; - case 0x58: /* bit 3, b */ - do_test_bit(REG_B, 3); - break; - case 0x59: /* bit 3, c */ - do_test_bit(REG_C, 3); - break; - case 0x5A: /* bit 3, d */ - do_test_bit(REG_D, 3); - break; - case 0x5B: /* bit 3, e */ - do_test_bit(REG_E, 3); - break; - case 0x5C: /* bit 3, h */ - do_test_bit(REG_H, 3); - break; - case 0x5D: /* bit 3, l */ - do_test_bit(REG_L, 3); - break; - case 0x67: /* bit 4, a */ - do_test_bit(REG_A, 4); - break; - case 0x60: /* bit 4, b */ - do_test_bit(REG_B, 4); - break; - case 0x61: /* bit 4, c */ - do_test_bit(REG_C, 4); - break; - case 0x62: /* bit 4, d */ - do_test_bit(REG_D, 4); - break; - case 0x63: /* bit 4, e */ - do_test_bit(REG_E, 4); - break; - case 0x64: /* bit 4, h */ - do_test_bit(REG_H, 4); - break; - case 0x65: /* bit 4, l */ - do_test_bit(REG_L, 4); - break; - case 0x6F: /* bit 5, a */ - do_test_bit(REG_A, 5); - break; - case 0x68: /* bit 5, b */ - do_test_bit(REG_B, 5); - break; - case 0x69: /* bit 5, c */ - do_test_bit(REG_C, 5); - break; - case 0x6A: /* bit 5, d */ - do_test_bit(REG_D, 5); - break; - case 0x6B: /* bit 5, e */ - do_test_bit(REG_E, 5); - break; - case 0x6C: /* bit 5, h */ - do_test_bit(REG_H, 5); - break; - case 0x6D: /* bit 5, l */ - do_test_bit(REG_L, 5); - break; - case 0x77: /* bit 6, a */ - do_test_bit(REG_A, 6); - break; - case 0x70: /* bit 6, b */ - do_test_bit(REG_B, 6); - break; - case 0x71: /* bit 6, c */ - do_test_bit(REG_C, 6); - break; - case 0x72: /* bit 6, d */ - do_test_bit(REG_D, 6); - break; - case 0x73: /* bit 6, e */ - do_test_bit(REG_E, 6); - break; - case 0x74: /* bit 6, h */ - do_test_bit(REG_H, 6); - break; - case 0x75: /* bit 6, l */ - do_test_bit(REG_L, 6); - break; - case 0x7F: /* bit 7, a */ - do_test_bit(REG_A, 7); - break; - case 0x78: /* bit 7, b */ - do_test_bit(REG_B, 7); - break; - case 0x79: /* bit 7, c */ - do_test_bit(REG_C, 7); - break; - case 0x7A: /* bit 7, d */ - do_test_bit(REG_D, 7); - break; - case 0x7B: /* bit 7, e */ - do_test_bit(REG_E, 7); - break; - case 0x7C: /* bit 7, h */ - do_test_bit(REG_H, 7); - break; - case 0x7D: /* bit 7, l */ - do_test_bit(REG_L, 7); - break; - - case 0x46: /* bit 0, (hl) */ - do_test_bit(mem_read(REG_HL), 0); - break; - case 0x4E: /* bit 1, (hl) */ - do_test_bit(mem_read(REG_HL), 1); - break; - case 0x56: /* bit 2, (hl) */ - do_test_bit(mem_read(REG_HL), 2); - break; - case 0x5E: /* bit 3, (hl) */ - do_test_bit(mem_read(REG_HL), 3); - break; - case 0x66: /* bit 4, (hl) */ - do_test_bit(mem_read(REG_HL), 4); - break; - case 0x6E: /* bit 5, (hl) */ - do_test_bit(mem_read(REG_HL), 5); - break; - case 0x76: /* bit 6, (hl) */ - do_test_bit(mem_read(REG_HL), 6); - break; - case 0x7E: /* bit 7, (hl) */ - do_test_bit(mem_read(REG_HL), 7); - break; - - case 0x87: /* res 0, a */ - REG_A &= ~(1 << 0); - break; - case 0x80: /* res 0, b */ - REG_B &= ~(1 << 0); - break; - case 0x81: /* res 0, c */ - REG_C &= ~(1 << 0); - break; - case 0x82: /* res 0, d */ - REG_D &= ~(1 << 0); - break; - case 0x83: /* res 0, e */ - REG_E &= ~(1 << 0); - break; - case 0x84: /* res 0, h */ - REG_H &= ~(1 << 0); - break; - case 0x85: /* res 0, l */ - REG_L &= ~(1 << 0); - break; - case 0x8F: /* res 1, a */ - REG_A &= ~(1 << 1); - break; - case 0x88: /* res 1, b */ - REG_B &= ~(1 << 1); - break; - case 0x89: /* res 1, c */ - REG_C &= ~(1 << 1); - break; - case 0x8A: /* res 1, d */ - REG_D &= ~(1 << 1); - break; - case 0x8B: /* res 1, e */ - REG_E &= ~(1 << 1); - break; - case 0x8C: /* res 1, h */ - REG_H &= ~(1 << 1); - break; - case 0x8D: /* res 1, l */ - REG_L &= ~(1 << 1); - break; - case 0x97: /* res 2, a */ - REG_A &= ~(1 << 2); - break; - case 0x90: /* res 2, b */ - REG_B &= ~(1 << 2); - break; - case 0x91: /* res 2, c */ - REG_C &= ~(1 << 2); - break; - case 0x92: /* res 2, d */ - REG_D &= ~(1 << 2); - break; - case 0x93: /* res 2, e */ - REG_E &= ~(1 << 2); - break; - case 0x94: /* res 2, h */ - REG_H &= ~(1 << 2); - break; - case 0x95: /* res 2, l */ - REG_L &= ~(1 << 2); - break; - case 0x9F: /* res 3, a */ - REG_A &= ~(1 << 3); - break; - case 0x98: /* res 3, b */ - REG_B &= ~(1 << 3); - break; - case 0x99: /* res 3, c */ - REG_C &= ~(1 << 3); - break; - case 0x9A: /* res 3, d */ - REG_D &= ~(1 << 3); - break; - case 0x9B: /* res 3, e */ - REG_E &= ~(1 << 3); - break; - case 0x9C: /* res 3, h */ - REG_H &= ~(1 << 3); - break; - case 0x9D: /* res 3, l */ - REG_L &= ~(1 << 3); - break; - case 0xA7: /* res 4, a */ - REG_A &= ~(1 << 4); - break; - case 0xA0: /* res 4, b */ - REG_B &= ~(1 << 4); - break; - case 0xA1: /* res 4, c */ - REG_C &= ~(1 << 4); - break; - case 0xA2: /* res 4, d */ - REG_D &= ~(1 << 4); - break; - case 0xA3: /* res 4, e */ - REG_E &= ~(1 << 4); - break; - case 0xA4: /* res 4, h */ - REG_H &= ~(1 << 4); - break; - case 0xA5: /* res 4, l */ - REG_L &= ~(1 << 4); - break; - case 0xAF: /* res 5, a */ - REG_A &= ~(1 << 5); - break; - case 0xA8: /* res 5, b */ - REG_B &= ~(1 << 5); - break; - case 0xA9: /* res 5, c */ - REG_C &= ~(1 << 5); - break; - case 0xAA: /* res 5, d */ - REG_D &= ~(1 << 5); - break; - case 0xAB: /* res 5, e */ - REG_E &= ~(1 << 5); - break; - case 0xAC: /* res 5, h */ - REG_H &= ~(1 << 5); - break; - case 0xAD: /* res 5, l */ - REG_L &= ~(1 << 5); - break; - case 0xB7: /* res 6, a */ - REG_A &= ~(1 << 6); - break; - case 0xB0: /* res 6, b */ - REG_B &= ~(1 << 6); - break; - case 0xB1: /* res 6, c */ - REG_C &= ~(1 << 6); - break; - case 0xB2: /* res 6, d */ - REG_D &= ~(1 << 6); - break; - case 0xB3: /* res 6, e */ - REG_E &= ~(1 << 6); - break; - case 0xB4: /* res 6, h */ - REG_H &= ~(1 << 6); - break; - case 0xB5: /* res 6, l */ - REG_L &= ~(1 << 6); - break; - case 0xBF: /* res 7, a */ - REG_A &= ~(1 << 7); - break; - case 0xB8: /* res 7, b */ - REG_B &= ~(1 << 7); - break; - case 0xB9: /* res 7, c */ - REG_C &= ~(1 << 7); - break; - case 0xBA: /* res 7, d */ - REG_D &= ~(1 << 7); - break; - case 0xBB: /* res 7, e */ - REG_E &= ~(1 << 7); - break; - case 0xBC: /* res 7, h */ - REG_H &= ~(1 << 7); - break; - case 0xBD: /* res 7, l */ - REG_L &= ~(1 << 7); - break; - - case 0x86: /* res 0, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 0)); - break; - case 0x8E: /* res 1, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 1)); - break; - case 0x96: /* res 2, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 2)); - break; - case 0x9E: /* res 3, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 3)); - break; - case 0xA6: /* res 4, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 4)); - break; - case 0xAE: /* res 5, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 5)); - break; - case 0xB6: /* res 6, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 6)); - break; - case 0xBE: /* res 7, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 7)); - break; - - case 0x17: /* rl a */ - REG_A = rl_byte(REG_A); - break; - case 0x10: /* rl b */ - REG_B = rl_byte(REG_B); - break; - case 0x11: /* rl c */ - REG_C = rl_byte(REG_C); - break; - case 0x12: /* rl d */ - REG_D = rl_byte(REG_D); - break; - case 0x13: /* rl e */ - REG_E = rl_byte(REG_E); - break; - case 0x14: /* rl h */ - REG_H = rl_byte(REG_H); - break; - case 0x15: /* rl l */ - REG_L = rl_byte(REG_L); - break; - case 0x16: /* rl (hl) */ - mem_write(REG_HL, rl_byte(mem_read(REG_HL))); - break; - - case 0x07: /* rlc a */ - REG_A = rlc_byte(REG_A); - break; - case 0x00: /* rlc b */ - REG_B = rlc_byte(REG_B); - break; - case 0x01: /* rlc c */ - REG_C = rlc_byte(REG_C); - break; - case 0x02: /* rlc d */ - REG_D = rlc_byte(REG_D); - break; - case 0x03: /* rlc e */ - REG_E = rlc_byte(REG_E); - break; - case 0x04: /* rlc h */ - REG_H = rlc_byte(REG_H); - break; - case 0x05: /* rlc l */ - REG_L = rlc_byte(REG_L); - break; - case 0x06: /* rlc (hl) */ - mem_write(REG_HL, rlc_byte(mem_read(REG_HL))); - break; - - case 0x1F: /* rr a */ - REG_A = rr_byte(REG_A); - break; - case 0x18: /* rr b */ - REG_B = rr_byte(REG_B); - break; - case 0x19: /* rr c */ - REG_C = rr_byte(REG_C); - break; - case 0x1A: /* rr d */ - REG_D = rr_byte(REG_D); - break; - case 0x1B: /* rr e */ - REG_E = rr_byte(REG_E); - break; - case 0x1C: /* rr h */ - REG_H = rr_byte(REG_H); - break; - case 0x1D: /* rr l */ - REG_L = rr_byte(REG_L); - break; - case 0x1E: /* rr (hl) */ - mem_write(REG_HL, rr_byte(mem_read(REG_HL))); - break; - - case 0x0F: /* rrc a */ - REG_A = rrc_byte(REG_A); - break; - case 0x08: /* rrc b */ - REG_B = rrc_byte(REG_B); - break; - case 0x09: /* rrc c */ - REG_C = rrc_byte(REG_C); - break; - case 0x0A: /* rrc d */ - REG_D = rrc_byte(REG_D); - break; - case 0x0B: /* rrc e */ - REG_E = rrc_byte(REG_E); - break; - case 0x0C: /* rrc h */ - REG_H = rrc_byte(REG_H); - break; - case 0x0D: /* rrc l */ - REG_L = rrc_byte(REG_L); - break; - case 0x0E: /* rrc (hl) */ - mem_write(REG_HL, rrc_byte(mem_read(REG_HL))); - break; - - case 0xC7: /* set 0, a */ - REG_A |= (1 << 0); - break; - case 0xC0: /* set 0, b */ - REG_B |= (1 << 0); - break; - case 0xC1: /* set 0, c */ - REG_C |= (1 << 0); - break; - case 0xC2: /* set 0, d */ - REG_D |= (1 << 0); - break; - case 0xC3: /* set 0, e */ - REG_E |= (1 << 0); - break; - case 0xC4: /* set 0, h */ - REG_H |= (1 << 0); - break; - case 0xC5: /* set 0, l */ - REG_L |= (1 << 0); - break; - case 0xCF: /* set 1, a */ - REG_A |= (1 << 1); - break; - case 0xC8: /* set 1, b */ - REG_B |= (1 << 1); - break; - case 0xC9: /* set 1, c */ - REG_C |= (1 << 1); - break; - case 0xCA: /* set 1, d */ - REG_D |= (1 << 1); - break; - case 0xCB: /* set 1, e */ - REG_E |= (1 << 1); - break; - case 0xCC: /* set 1, h */ - REG_H |= (1 << 1); - break; - case 0xCD: /* set 1, l */ - REG_L |= (1 << 1); - break; - case 0xD7: /* set 2, a */ - REG_A |= (1 << 2); - break; - case 0xD0: /* set 2, b */ - REG_B |= (1 << 2); - break; - case 0xD1: /* set 2, c */ - REG_C |= (1 << 2); - break; - case 0xD2: /* set 2, d */ - REG_D |= (1 << 2); - break; - case 0xD3: /* set 2, e */ - REG_E |= (1 << 2); - break; - case 0xD4: /* set 2, h */ - REG_H |= (1 << 2); - break; - case 0xD5: /* set 2, l */ - REG_L |= (1 << 2); - break; - case 0xDF: /* set 3, a */ - REG_A |= (1 << 3); - break; - case 0xD8: /* set 3, b */ - REG_B |= (1 << 3); - break; - case 0xD9: /* set 3, c */ - REG_C |= (1 << 3); - break; - case 0xDA: /* set 3, d */ - REG_D |= (1 << 3); - break; - case 0xDB: /* set 3, e */ - REG_E |= (1 << 3); - break; - case 0xDC: /* set 3, h */ - REG_H |= (1 << 3); - break; - case 0xDD: /* set 3, l */ - REG_L |= (1 << 3); - break; - case 0xE7: /* set 4, a */ - REG_A |= (1 << 4); - break; - case 0xE0: /* set 4, b */ - REG_B |= (1 << 4); - break; - case 0xE1: /* set 4, c */ - REG_C |= (1 << 4); - break; - case 0xE2: /* set 4, d */ - REG_D |= (1 << 4); - break; - case 0xE3: /* set 4, e */ - REG_E |= (1 << 4); - break; - case 0xE4: /* set 4, h */ - REG_H |= (1 << 4); - break; - case 0xE5: /* set 4, l */ - REG_L |= (1 << 4); - break; - case 0xEF: /* set 5, a */ - REG_A |= (1 << 5); - break; - case 0xE8: /* set 5, b */ - REG_B |= (1 << 5); - break; - case 0xE9: /* set 5, c */ - REG_C |= (1 << 5); - break; - case 0xEA: /* set 5, d */ - REG_D |= (1 << 5); - break; - case 0xEB: /* set 5, e */ - REG_E |= (1 << 5); - break; - case 0xEC: /* set 5, h */ - REG_H |= (1 << 5); - break; - case 0xED: /* set 5, l */ - REG_L |= (1 << 5); - break; - case 0xF7: /* set 6, a */ - REG_A |= (1 << 6); - break; - case 0xF0: /* set 6, b */ - REG_B |= (1 << 6); - break; - case 0xF1: /* set 6, c */ - REG_C |= (1 << 6); - break; - case 0xF2: /* set 6, d */ - REG_D |= (1 << 6); - break; - case 0xF3: /* set 6, e */ - REG_E |= (1 << 6); - break; - case 0xF4: /* set 6, h */ - REG_H |= (1 << 6); - break; - case 0xF5: /* set 6, l */ - REG_L |= (1 << 6); - break; - case 0xFF: /* set 7, a */ - REG_A |= (1 << 7); - break; - case 0xF8: /* set 7, b */ - REG_B |= (1 << 7); - break; - case 0xF9: /* set 7, c */ - REG_C |= (1 << 7); - break; - case 0xFA: /* set 7, d */ - REG_D |= (1 << 7); - break; - case 0xFB: /* set 7, e */ - REG_E |= (1 << 7); - break; - case 0xFC: /* set 7, h */ - REG_H |= (1 << 7); - break; - case 0xFD: /* set 7, l */ - REG_L |= (1 << 7); - break; - - case 0xC6: /* set 0, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 0)); - break; - case 0xCE: /* set 1, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 1)); - break; - case 0xD6: /* set 2, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 2)); - break; - case 0xDE: /* set 3, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 3)); - break; - case 0xE6: /* set 4, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 4)); - break; - case 0xEE: /* set 5, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 5)); - break; - case 0xF6: /* set 6, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 6)); - break; - case 0xFE: /* set 7, (hl) */ - mem_write(REG_HL, mem_read(REG_HL) | (1 << 7)); - break; - - case 0x27: /* sla a */ - REG_A = sla_byte(REG_A); - break; - case 0x20: /* sla b */ - REG_B = sla_byte(REG_B); - break; - case 0x21: /* sla c */ - REG_C = sla_byte(REG_C); - break; - case 0x22: /* sla d */ - REG_D = sla_byte(REG_D); - break; - case 0x23: /* sla e */ - REG_E = sla_byte(REG_E); - break; - case 0x24: /* sla h */ - REG_H = sla_byte(REG_H); - break; - case 0x25: /* sla l */ - REG_L = sla_byte(REG_L); - break; - case 0x26: /* sla (hl) */ - mem_write(REG_HL, sla_byte(mem_read(REG_HL))); - break; - - case 0x37: /* sll a */ - REG_A = sll_byte(REG_A); - break; - case 0x30: /* sll b */ - REG_B = sll_byte(REG_B); - break; - case 0x31: /* sll c */ - REG_C = sll_byte(REG_C); - break; - case 0x32: /* sll d */ - REG_D = sll_byte(REG_D); - break; - case 0x33: /* sll e */ - REG_E = sll_byte(REG_E); - break; - case 0x34: /* sll h */ - REG_H = sll_byte(REG_H); - break; - case 0x35: /* sll l */ - REG_L = sll_byte(REG_L); - break; - case 0x36: /* sll (hl) */ - mem_write(REG_HL, sll_byte(mem_read(REG_HL))); - break; - - case 0x2F: /* sra a */ - REG_A = sra_byte(REG_A); - break; - case 0x28: /* sra b */ - REG_B = sra_byte(REG_B); - break; - case 0x29: /* sra c */ - REG_C = sra_byte(REG_C); - break; - case 0x2A: /* sra d */ - REG_D = sra_byte(REG_D); - break; - case 0x2B: /* sra e */ - REG_E = sra_byte(REG_E); - break; - case 0x2C: /* sra h */ - REG_H = sra_byte(REG_H); - break; - case 0x2D: /* sra l */ - REG_L = sra_byte(REG_L); - break; - case 0x2E: /* sra (hl) */ - mem_write(REG_HL, sra_byte(mem_read(REG_HL))); - break; - - case 0x3F: /* srl a */ - REG_A = srl_byte(REG_A); - break; - case 0x38: /* srl b */ - REG_B = srl_byte(REG_B); - break; - case 0x39: /* srl c */ - REG_C = srl_byte(REG_C); - break; - case 0x3A: /* srl d */ - REG_D = srl_byte(REG_D); - break; - case 0x3B: /* srl e */ - REG_E = srl_byte(REG_E); - break; - case 0x3C: /* srl h */ - REG_H = srl_byte(REG_H); - break; - case 0x3D: /* srl l */ - REG_L = srl_byte(REG_L); - break; - case 0x3E: /* srl (hl) */ - mem_write(REG_HL, srl_byte(mem_read(REG_HL))); - break; - } + /* + * Normal operation sans DD/FD prefix + */ + + instruction = mem_fetch(REG_PC++); + inc_r(); + + /* (HL) = 7 additional clocks, otherwise 4 */ + if ((instruction & 7) == 6) { + TSTATE += (instruction & 0xc0) == 0x40 ? 8 : 11; + } else { + TSTATE += 4; + } + + switch (instruction) { + case 0x47: /* bit 0, a */ + do_test_bit(REG_A, 0); + break; + case 0x40: /* bit 0, b */ + do_test_bit(REG_B, 0); + break; + case 0x41: /* bit 0, c */ + do_test_bit(REG_C, 0); + break; + case 0x42: /* bit 0, d */ + do_test_bit(REG_D, 0); + break; + case 0x43: /* bit 0, e */ + do_test_bit(REG_E, 0); + break; + case 0x44: /* bit 0, h */ + do_test_bit(REG_H, 0); + break; + case 0x45: /* bit 0, l */ + do_test_bit(REG_L, 0); + break; + case 0x4F: /* bit 1, a */ + do_test_bit(REG_A, 1); + break; + case 0x48: /* bit 1, b */ + do_test_bit(REG_B, 1); + break; + case 0x49: /* bit 1, c */ + do_test_bit(REG_C, 1); + break; + case 0x4A: /* bit 1, d */ + do_test_bit(REG_D, 1); + break; + case 0x4B: /* bit 1, e */ + do_test_bit(REG_E, 1); + break; + case 0x4C: /* bit 1, h */ + do_test_bit(REG_H, 1); + break; + case 0x4D: /* bit 1, l */ + do_test_bit(REG_L, 1); + break; + case 0x57: /* bit 2, a */ + do_test_bit(REG_A, 2); + break; + case 0x50: /* bit 2, b */ + do_test_bit(REG_B, 2); + break; + case 0x51: /* bit 2, c */ + do_test_bit(REG_C, 2); + break; + case 0x52: /* bit 2, d */ + do_test_bit(REG_D, 2); + break; + case 0x53: /* bit 2, e */ + do_test_bit(REG_E, 2); + break; + case 0x54: /* bit 2, h */ + do_test_bit(REG_H, 2); + break; + case 0x55: /* bit 2, l */ + do_test_bit(REG_L, 2); + break; + case 0x5F: /* bit 3, a */ + do_test_bit(REG_A, 3); + break; + case 0x58: /* bit 3, b */ + do_test_bit(REG_B, 3); + break; + case 0x59: /* bit 3, c */ + do_test_bit(REG_C, 3); + break; + case 0x5A: /* bit 3, d */ + do_test_bit(REG_D, 3); + break; + case 0x5B: /* bit 3, e */ + do_test_bit(REG_E, 3); + break; + case 0x5C: /* bit 3, h */ + do_test_bit(REG_H, 3); + break; + case 0x5D: /* bit 3, l */ + do_test_bit(REG_L, 3); + break; + case 0x67: /* bit 4, a */ + do_test_bit(REG_A, 4); + break; + case 0x60: /* bit 4, b */ + do_test_bit(REG_B, 4); + break; + case 0x61: /* bit 4, c */ + do_test_bit(REG_C, 4); + break; + case 0x62: /* bit 4, d */ + do_test_bit(REG_D, 4); + break; + case 0x63: /* bit 4, e */ + do_test_bit(REG_E, 4); + break; + case 0x64: /* bit 4, h */ + do_test_bit(REG_H, 4); + break; + case 0x65: /* bit 4, l */ + do_test_bit(REG_L, 4); + break; + case 0x6F: /* bit 5, a */ + do_test_bit(REG_A, 5); + break; + case 0x68: /* bit 5, b */ + do_test_bit(REG_B, 5); + break; + case 0x69: /* bit 5, c */ + do_test_bit(REG_C, 5); + break; + case 0x6A: /* bit 5, d */ + do_test_bit(REG_D, 5); + break; + case 0x6B: /* bit 5, e */ + do_test_bit(REG_E, 5); + break; + case 0x6C: /* bit 5, h */ + do_test_bit(REG_H, 5); + break; + case 0x6D: /* bit 5, l */ + do_test_bit(REG_L, 5); + break; + case 0x77: /* bit 6, a */ + do_test_bit(REG_A, 6); + break; + case 0x70: /* bit 6, b */ + do_test_bit(REG_B, 6); + break; + case 0x71: /* bit 6, c */ + do_test_bit(REG_C, 6); + break; + case 0x72: /* bit 6, d */ + do_test_bit(REG_D, 6); + break; + case 0x73: /* bit 6, e */ + do_test_bit(REG_E, 6); + break; + case 0x74: /* bit 6, h */ + do_test_bit(REG_H, 6); + break; + case 0x75: /* bit 6, l */ + do_test_bit(REG_L, 6); + break; + case 0x7F: /* bit 7, a */ + do_test_bit(REG_A, 7); + break; + case 0x78: /* bit 7, b */ + do_test_bit(REG_B, 7); + break; + case 0x79: /* bit 7, c */ + do_test_bit(REG_C, 7); + break; + case 0x7A: /* bit 7, d */ + do_test_bit(REG_D, 7); + break; + case 0x7B: /* bit 7, e */ + do_test_bit(REG_E, 7); + break; + case 0x7C: /* bit 7, h */ + do_test_bit(REG_H, 7); + break; + case 0x7D: /* bit 7, l */ + do_test_bit(REG_L, 7); + break; + + case 0x46: /* bit 0, (hl) */ + do_test_bit(mem_read(REG_HL), 0); + break; + case 0x4E: /* bit 1, (hl) */ + do_test_bit(mem_read(REG_HL), 1); + break; + case 0x56: /* bit 2, (hl) */ + do_test_bit(mem_read(REG_HL), 2); + break; + case 0x5E: /* bit 3, (hl) */ + do_test_bit(mem_read(REG_HL), 3); + break; + case 0x66: /* bit 4, (hl) */ + do_test_bit(mem_read(REG_HL), 4); + break; + case 0x6E: /* bit 5, (hl) */ + do_test_bit(mem_read(REG_HL), 5); + break; + case 0x76: /* bit 6, (hl) */ + do_test_bit(mem_read(REG_HL), 6); + break; + case 0x7E: /* bit 7, (hl) */ + do_test_bit(mem_read(REG_HL), 7); + break; + + case 0x87: /* res 0, a */ + REG_A &= ~(1 << 0); + break; + case 0x80: /* res 0, b */ + REG_B &= ~(1 << 0); + break; + case 0x81: /* res 0, c */ + REG_C &= ~(1 << 0); + break; + case 0x82: /* res 0, d */ + REG_D &= ~(1 << 0); + break; + case 0x83: /* res 0, e */ + REG_E &= ~(1 << 0); + break; + case 0x84: /* res 0, h */ + REG_H &= ~(1 << 0); + break; + case 0x85: /* res 0, l */ + REG_L &= ~(1 << 0); + break; + case 0x8F: /* res 1, a */ + REG_A &= ~(1 << 1); + break; + case 0x88: /* res 1, b */ + REG_B &= ~(1 << 1); + break; + case 0x89: /* res 1, c */ + REG_C &= ~(1 << 1); + break; + case 0x8A: /* res 1, d */ + REG_D &= ~(1 << 1); + break; + case 0x8B: /* res 1, e */ + REG_E &= ~(1 << 1); + break; + case 0x8C: /* res 1, h */ + REG_H &= ~(1 << 1); + break; + case 0x8D: /* res 1, l */ + REG_L &= ~(1 << 1); + break; + case 0x97: /* res 2, a */ + REG_A &= ~(1 << 2); + break; + case 0x90: /* res 2, b */ + REG_B &= ~(1 << 2); + break; + case 0x91: /* res 2, c */ + REG_C &= ~(1 << 2); + break; + case 0x92: /* res 2, d */ + REG_D &= ~(1 << 2); + break; + case 0x93: /* res 2, e */ + REG_E &= ~(1 << 2); + break; + case 0x94: /* res 2, h */ + REG_H &= ~(1 << 2); + break; + case 0x95: /* res 2, l */ + REG_L &= ~(1 << 2); + break; + case 0x9F: /* res 3, a */ + REG_A &= ~(1 << 3); + break; + case 0x98: /* res 3, b */ + REG_B &= ~(1 << 3); + break; + case 0x99: /* res 3, c */ + REG_C &= ~(1 << 3); + break; + case 0x9A: /* res 3, d */ + REG_D &= ~(1 << 3); + break; + case 0x9B: /* res 3, e */ + REG_E &= ~(1 << 3); + break; + case 0x9C: /* res 3, h */ + REG_H &= ~(1 << 3); + break; + case 0x9D: /* res 3, l */ + REG_L &= ~(1 << 3); + break; + case 0xA7: /* res 4, a */ + REG_A &= ~(1 << 4); + break; + case 0xA0: /* res 4, b */ + REG_B &= ~(1 << 4); + break; + case 0xA1: /* res 4, c */ + REG_C &= ~(1 << 4); + break; + case 0xA2: /* res 4, d */ + REG_D &= ~(1 << 4); + break; + case 0xA3: /* res 4, e */ + REG_E &= ~(1 << 4); + break; + case 0xA4: /* res 4, h */ + REG_H &= ~(1 << 4); + break; + case 0xA5: /* res 4, l */ + REG_L &= ~(1 << 4); + break; + case 0xAF: /* res 5, a */ + REG_A &= ~(1 << 5); + break; + case 0xA8: /* res 5, b */ + REG_B &= ~(1 << 5); + break; + case 0xA9: /* res 5, c */ + REG_C &= ~(1 << 5); + break; + case 0xAA: /* res 5, d */ + REG_D &= ~(1 << 5); + break; + case 0xAB: /* res 5, e */ + REG_E &= ~(1 << 5); + break; + case 0xAC: /* res 5, h */ + REG_H &= ~(1 << 5); + break; + case 0xAD: /* res 5, l */ + REG_L &= ~(1 << 5); + break; + case 0xB7: /* res 6, a */ + REG_A &= ~(1 << 6); + break; + case 0xB0: /* res 6, b */ + REG_B &= ~(1 << 6); + break; + case 0xB1: /* res 6, c */ + REG_C &= ~(1 << 6); + break; + case 0xB2: /* res 6, d */ + REG_D &= ~(1 << 6); + break; + case 0xB3: /* res 6, e */ + REG_E &= ~(1 << 6); + break; + case 0xB4: /* res 6, h */ + REG_H &= ~(1 << 6); + break; + case 0xB5: /* res 6, l */ + REG_L &= ~(1 << 6); + break; + case 0xBF: /* res 7, a */ + REG_A &= ~(1 << 7); + break; + case 0xB8: /* res 7, b */ + REG_B &= ~(1 << 7); + break; + case 0xB9: /* res 7, c */ + REG_C &= ~(1 << 7); + break; + case 0xBA: /* res 7, d */ + REG_D &= ~(1 << 7); + break; + case 0xBB: /* res 7, e */ + REG_E &= ~(1 << 7); + break; + case 0xBC: /* res 7, h */ + REG_H &= ~(1 << 7); + break; + case 0xBD: /* res 7, l */ + REG_L &= ~(1 << 7); + break; + + case 0x86: /* res 0, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 0)); + break; + case 0x8E: /* res 1, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 1)); + break; + case 0x96: /* res 2, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 2)); + break; + case 0x9E: /* res 3, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 3)); + break; + case 0xA6: /* res 4, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 4)); + break; + case 0xAE: /* res 5, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 5)); + break; + case 0xB6: /* res 6, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 6)); + break; + case 0xBE: /* res 7, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) & ~(1 << 7)); + break; + + case 0x17: /* rl a */ + REG_A = rl_byte(REG_A); + break; + case 0x10: /* rl b */ + REG_B = rl_byte(REG_B); + break; + case 0x11: /* rl c */ + REG_C = rl_byte(REG_C); + break; + case 0x12: /* rl d */ + REG_D = rl_byte(REG_D); + break; + case 0x13: /* rl e */ + REG_E = rl_byte(REG_E); + break; + case 0x14: /* rl h */ + REG_H = rl_byte(REG_H); + break; + case 0x15: /* rl l */ + REG_L = rl_byte(REG_L); + break; + case 0x16: /* rl (hl) */ + mem_write(REG_HL, rl_byte(mem_read(REG_HL))); + break; + + case 0x07: /* rlc a */ + REG_A = rlc_byte(REG_A); + break; + case 0x00: /* rlc b */ + REG_B = rlc_byte(REG_B); + break; + case 0x01: /* rlc c */ + REG_C = rlc_byte(REG_C); + break; + case 0x02: /* rlc d */ + REG_D = rlc_byte(REG_D); + break; + case 0x03: /* rlc e */ + REG_E = rlc_byte(REG_E); + break; + case 0x04: /* rlc h */ + REG_H = rlc_byte(REG_H); + break; + case 0x05: /* rlc l */ + REG_L = rlc_byte(REG_L); + break; + case 0x06: /* rlc (hl) */ + mem_write(REG_HL, rlc_byte(mem_read(REG_HL))); + break; + + case 0x1F: /* rr a */ + REG_A = rr_byte(REG_A); + break; + case 0x18: /* rr b */ + REG_B = rr_byte(REG_B); + break; + case 0x19: /* rr c */ + REG_C = rr_byte(REG_C); + break; + case 0x1A: /* rr d */ + REG_D = rr_byte(REG_D); + break; + case 0x1B: /* rr e */ + REG_E = rr_byte(REG_E); + break; + case 0x1C: /* rr h */ + REG_H = rr_byte(REG_H); + break; + case 0x1D: /* rr l */ + REG_L = rr_byte(REG_L); + break; + case 0x1E: /* rr (hl) */ + mem_write(REG_HL, rr_byte(mem_read(REG_HL))); + break; + + case 0x0F: /* rrc a */ + REG_A = rrc_byte(REG_A); + break; + case 0x08: /* rrc b */ + REG_B = rrc_byte(REG_B); + break; + case 0x09: /* rrc c */ + REG_C = rrc_byte(REG_C); + break; + case 0x0A: /* rrc d */ + REG_D = rrc_byte(REG_D); + break; + case 0x0B: /* rrc e */ + REG_E = rrc_byte(REG_E); + break; + case 0x0C: /* rrc h */ + REG_H = rrc_byte(REG_H); + break; + case 0x0D: /* rrc l */ + REG_L = rrc_byte(REG_L); + break; + case 0x0E: /* rrc (hl) */ + mem_write(REG_HL, rrc_byte(mem_read(REG_HL))); + break; + + case 0xC7: /* set 0, a */ + REG_A |= (1 << 0); + break; + case 0xC0: /* set 0, b */ + REG_B |= (1 << 0); + break; + case 0xC1: /* set 0, c */ + REG_C |= (1 << 0); + break; + case 0xC2: /* set 0, d */ + REG_D |= (1 << 0); + break; + case 0xC3: /* set 0, e */ + REG_E |= (1 << 0); + break; + case 0xC4: /* set 0, h */ + REG_H |= (1 << 0); + break; + case 0xC5: /* set 0, l */ + REG_L |= (1 << 0); + break; + case 0xCF: /* set 1, a */ + REG_A |= (1 << 1); + break; + case 0xC8: /* set 1, b */ + REG_B |= (1 << 1); + break; + case 0xC9: /* set 1, c */ + REG_C |= (1 << 1); + break; + case 0xCA: /* set 1, d */ + REG_D |= (1 << 1); + break; + case 0xCB: /* set 1, e */ + REG_E |= (1 << 1); + break; + case 0xCC: /* set 1, h */ + REG_H |= (1 << 1); + break; + case 0xCD: /* set 1, l */ + REG_L |= (1 << 1); + break; + case 0xD7: /* set 2, a */ + REG_A |= (1 << 2); + break; + case 0xD0: /* set 2, b */ + REG_B |= (1 << 2); + break; + case 0xD1: /* set 2, c */ + REG_C |= (1 << 2); + break; + case 0xD2: /* set 2, d */ + REG_D |= (1 << 2); + break; + case 0xD3: /* set 2, e */ + REG_E |= (1 << 2); + break; + case 0xD4: /* set 2, h */ + REG_H |= (1 << 2); + break; + case 0xD5: /* set 2, l */ + REG_L |= (1 << 2); + break; + case 0xDF: /* set 3, a */ + REG_A |= (1 << 3); + break; + case 0xD8: /* set 3, b */ + REG_B |= (1 << 3); + break; + case 0xD9: /* set 3, c */ + REG_C |= (1 << 3); + break; + case 0xDA: /* set 3, d */ + REG_D |= (1 << 3); + break; + case 0xDB: /* set 3, e */ + REG_E |= (1 << 3); + break; + case 0xDC: /* set 3, h */ + REG_H |= (1 << 3); + break; + case 0xDD: /* set 3, l */ + REG_L |= (1 << 3); + break; + case 0xE7: /* set 4, a */ + REG_A |= (1 << 4); + break; + case 0xE0: /* set 4, b */ + REG_B |= (1 << 4); + break; + case 0xE1: /* set 4, c */ + REG_C |= (1 << 4); + break; + case 0xE2: /* set 4, d */ + REG_D |= (1 << 4); + break; + case 0xE3: /* set 4, e */ + REG_E |= (1 << 4); + break; + case 0xE4: /* set 4, h */ + REG_H |= (1 << 4); + break; + case 0xE5: /* set 4, l */ + REG_L |= (1 << 4); + break; + case 0xEF: /* set 5, a */ + REG_A |= (1 << 5); + break; + case 0xE8: /* set 5, b */ + REG_B |= (1 << 5); + break; + case 0xE9: /* set 5, c */ + REG_C |= (1 << 5); + break; + case 0xEA: /* set 5, d */ + REG_D |= (1 << 5); + break; + case 0xEB: /* set 5, e */ + REG_E |= (1 << 5); + break; + case 0xEC: /* set 5, h */ + REG_H |= (1 << 5); + break; + case 0xED: /* set 5, l */ + REG_L |= (1 << 5); + break; + case 0xF7: /* set 6, a */ + REG_A |= (1 << 6); + break; + case 0xF0: /* set 6, b */ + REG_B |= (1 << 6); + break; + case 0xF1: /* set 6, c */ + REG_C |= (1 << 6); + break; + case 0xF2: /* set 6, d */ + REG_D |= (1 << 6); + break; + case 0xF3: /* set 6, e */ + REG_E |= (1 << 6); + break; + case 0xF4: /* set 6, h */ + REG_H |= (1 << 6); + break; + case 0xF5: /* set 6, l */ + REG_L |= (1 << 6); + break; + case 0xFF: /* set 7, a */ + REG_A |= (1 << 7); + break; + case 0xF8: /* set 7, b */ + REG_B |= (1 << 7); + break; + case 0xF9: /* set 7, c */ + REG_C |= (1 << 7); + break; + case 0xFA: /* set 7, d */ + REG_D |= (1 << 7); + break; + case 0xFB: /* set 7, e */ + REG_E |= (1 << 7); + break; + case 0xFC: /* set 7, h */ + REG_H |= (1 << 7); + break; + case 0xFD: /* set 7, l */ + REG_L |= (1 << 7); + break; + + case 0xC6: /* set 0, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 0)); + break; + case 0xCE: /* set 1, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 1)); + break; + case 0xD6: /* set 2, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 2)); + break; + case 0xDE: /* set 3, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 3)); + break; + case 0xE6: /* set 4, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 4)); + break; + case 0xEE: /* set 5, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 5)); + break; + case 0xF6: /* set 6, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 6)); + break; + case 0xFE: /* set 7, (hl) */ + mem_write(REG_HL, mem_read(REG_HL) | (1 << 7)); + break; + + case 0x27: /* sla a */ + REG_A = sla_byte(REG_A); + break; + case 0x20: /* sla b */ + REG_B = sla_byte(REG_B); + break; + case 0x21: /* sla c */ + REG_C = sla_byte(REG_C); + break; + case 0x22: /* sla d */ + REG_D = sla_byte(REG_D); + break; + case 0x23: /* sla e */ + REG_E = sla_byte(REG_E); + break; + case 0x24: /* sla h */ + REG_H = sla_byte(REG_H); + break; + case 0x25: /* sla l */ + REG_L = sla_byte(REG_L); + break; + case 0x26: /* sla (hl) */ + mem_write(REG_HL, sla_byte(mem_read(REG_HL))); + break; + + case 0x37: /* sll a */ + REG_A = sll_byte(REG_A); + break; + case 0x30: /* sll b */ + REG_B = sll_byte(REG_B); + break; + case 0x31: /* sll c */ + REG_C = sll_byte(REG_C); + break; + case 0x32: /* sll d */ + REG_D = sll_byte(REG_D); + break; + case 0x33: /* sll e */ + REG_E = sll_byte(REG_E); + break; + case 0x34: /* sll h */ + REG_H = sll_byte(REG_H); + break; + case 0x35: /* sll l */ + REG_L = sll_byte(REG_L); + break; + case 0x36: /* sll (hl) */ + mem_write(REG_HL, sll_byte(mem_read(REG_HL))); + break; + + case 0x2F: /* sra a */ + REG_A = sra_byte(REG_A); + break; + case 0x28: /* sra b */ + REG_B = sra_byte(REG_B); + break; + case 0x29: /* sra c */ + REG_C = sra_byte(REG_C); + break; + case 0x2A: /* sra d */ + REG_D = sra_byte(REG_D); + break; + case 0x2B: /* sra e */ + REG_E = sra_byte(REG_E); + break; + case 0x2C: /* sra h */ + REG_H = sra_byte(REG_H); + break; + case 0x2D: /* sra l */ + REG_L = sra_byte(REG_L); + break; + case 0x2E: /* sra (hl) */ + mem_write(REG_HL, sra_byte(mem_read(REG_HL))); + break; + + case 0x3F: /* srl a */ + REG_A = srl_byte(REG_A); + break; + case 0x38: /* srl b */ + REG_B = srl_byte(REG_B); + break; + case 0x39: /* srl c */ + REG_C = srl_byte(REG_C); + break; + case 0x3A: /* srl d */ + REG_D = srl_byte(REG_D); + break; + case 0x3B: /* srl e */ + REG_E = srl_byte(REG_E); + break; + case 0x3C: /* srl h */ + REG_H = srl_byte(REG_H); + break; + case 0x3D: /* srl l */ + REG_L = srl_byte(REG_L); + break; + case 0x3E: /* srl (hl) */ + mem_write(REG_HL, srl_byte(mem_read(REG_HL))); + break; + } } else { - /* - * Indexed instructions are weird. They ALWAYS take the source from - * (Ix+d) and ALWAYS write the result back, but ALSO write the result - * to a GPR unless the register specifier is 6. BIT never writes - * anything back to either memory or GPR. - */ - - addr = ix->word + (int8_t)mem_fetch(REG_PC++); - instruction = mem_fetch(REG_PC++); - /* No R increment here, for some reason */ - - TSTATE += ((instruction & 0xc0) == 0x40) ? 12 : 15; - - data = mem_read(addr); - - switch (instruction & 0xc0) { - case 0x00: - switch (instruction & ~7) { - case 0x00: /* RLC */ - data = rlc_byte(data); - break; - case 0x08: /* RRC */ - data = rrc_byte(data); - break; - case 0x10: /* RL */ - data = rl_byte(data); - break; - case 0x18: /* RR */ - data = rr_byte(data); - break; - case 0x20: /* SLA */ - data = sla_byte(data); - break; - case 0x28: /* SRA */ - data = sra_byte(data); - break; - case 0x30: /* SLL */ - data = sll_byte(data); - break; - case 0x38: /* SRL */ - data = srl_byte(data); - break; - } - break; - - case 0x40: /* BIT */ - do_test_bit(data, (instruction >> 3) & 7); - return; /* No writeback! */ - - case 0x80: /* RES */ - data &= ~(1 << ((instruction >> 3) & 7)); - break; - - case 0xc0: /* SET */ - data |= (1 << ((instruction >> 3) & 7)); - break; - } - - switch (instruction & 7) { - case 0: - REG_B = data; - break; - case 1: - REG_C = data; - break; - case 2: - REG_D = data; - break; - case 3: - REG_E = data; - break; - case 4: - REG_H = data; - break; - case 5: - REG_L = data; - break; - case 6: - /* Only memory */ - break; - case 7: - REG_A = data; - break; - } - - mem_write(addr, data); + /* + * Indexed instructions are weird. They ALWAYS take the source from + * (Ix+d) and ALWAYS write the result back, but ALSO write the result + * to a GPR unless the register specifier is 6. BIT never writes + * anything back to either memory or GPR. + */ + + addr = ix->word + (int8_t) mem_fetch(REG_PC++); + instruction = mem_fetch(REG_PC++); + /* No R increment here, for some reason */ + + TSTATE += ((instruction & 0xc0) == 0x40) ? 12 : 15; + + data = mem_read(addr); + + switch (instruction & 0xc0) { + case 0x00: + switch (instruction & ~7) { + case 0x00: /* RLC */ + data = rlc_byte(data); + break; + case 0x08: /* RRC */ + data = rrc_byte(data); + break; + case 0x10: /* RL */ + data = rl_byte(data); + break; + case 0x18: /* RR */ + data = rr_byte(data); + break; + case 0x20: /* SLA */ + data = sla_byte(data); + break; + case 0x28: /* SRA */ + data = sra_byte(data); + break; + case 0x30: /* SLL */ + data = sll_byte(data); + break; + case 0x38: /* SRL */ + data = srl_byte(data); + break; + } + break; + + case 0x40: /* BIT */ + do_test_bit(data, (instruction >> 3) & 7); + return; /* No writeback! */ + + case 0x80: /* RES */ + data &= ~(1 << ((instruction >> 3) & 7)); + break; + + case 0xc0: /* SET */ + data |= (1 << ((instruction >> 3) & 7)); + break; + } + + switch (instruction & 7) { + case 0: + REG_B = data; + break; + case 1: + REG_C = data; + break; + case 2: + REG_D = data; + break; + case 3: + REG_E = data; + break; + case 4: + REG_H = data; + break; + case 5: + REG_L = data; + break; + case 6: + /* Only memory */ + break; + case 7: + REG_A = data; + break; + } + + mem_write(addr, data); } } -static void do_ED_instruction(wordregister *ix) +static void do_ED_instruction(wordregister * ix) { uint8_t instruction; - (void)ix; /* DD/FD has no effect */ + (void)ix; /* DD/FD has no effect */ /* * Undocumented instruction notes: @@ -2226,253 +2176,251 @@ static void do_ED_instruction(wordregister *ix) inc_r(); TSTATE += clk_ED[instruction]; - switch(instruction) - { - case 0x4A: /* adc hl, bc */ - do_adc_word(REG_BC); - break; - case 0x5A: /* adc hl, de */ - do_adc_word(REG_DE); - break; - case 0x6A: /* adc hl, hl */ - do_adc_word(REG_HL); - break; - case 0x7A: /* adc hl, sp */ - do_adc_word(REG_SP); - break; - - case 0xA9: /* cpd */ - do_cpid(-1); - break; - case 0xB9: /* cpdr */ - do_cpidr(-1); - break; - - case 0xA1: /* cpi */ - do_cpid(+1); - break; - case 0xB1: /* cpir */ - do_cpidr(+1); - break; - - case 0x46: /* im 0 */ - case 0x66: - case 0x4E: - case 0x6E: - do_im0(); - break; - case 0x56: /* im 1 */ - case 0x76: - do_im1(); - break; - case 0x5E: /* im 2 */ - case 0x7E: - do_im2(); - break; - - case 0x78: /* in a, (c) */ - REG_A = in_with_flags(REG_C); - break; - case 0x40: /* in b, (c) */ - REG_B = in_with_flags(REG_C); - break; - case 0x48: /* in c, (c) */ - REG_C = in_with_flags(REG_C); - break; - case 0x50: /* in d, (c) */ - REG_D = in_with_flags(REG_C); - break; - case 0x58: /* in e, (c) */ - REG_E = in_with_flags(REG_C); - break; - case 0x60: /* in h, (c) */ - REG_H = in_with_flags(REG_C); - break; - case 0x68: /* in l, (c) */ - REG_L = in_with_flags(REG_C); - break; - - case 0xAA: /* ind */ - do_inid(-1); - break; - case 0xBA: /* indr */ - do_inidr(-1); - break; - case 0xA2: /* ini */ - do_inid(+1); - break; - case 0xB2: /* inir */ - do_inidr(+1); - break; - - case 0x57: /* ld a, i */ - do_ld_a_ir(REG_I); - break; - case 0x47: /* ld i, a */ - REG_I = REG_A; - break; - - case 0x5F: /* ld a, r */ - do_ld_a_ir(REG_R); - break; - case 0x4F: /* ld r, a */ - z80_state.rf = z80_state.rc = REG_A; - break; - - case 0x4B: /* ld bc, (address) */ - REG_BC = mem_read_word(mem_fetch_word(REG_PC)); - REG_PC += 2; - break; - case 0x5B: /* ld de, (address) */ - REG_DE = mem_read_word(mem_fetch_word(REG_PC)); - REG_PC += 2; - break; - case 0x6B: /* ld hl, (address) */ - /* this instruction is redundant with the 2A instruction */ - REG_HL = mem_read_word(mem_fetch_word(REG_PC)); - REG_PC += 2; - break; - case 0x7B: /* ld sp, (address) */ - REG_SP = mem_read_word(mem_fetch_word(REG_PC)); - REG_PC += 2; - break; - - case 0x43: /* ld (address), bc */ - mem_write_word(mem_fetch_word(REG_PC), REG_BC); - REG_PC += 2; - break; - case 0x53: /* ld (address), de */ - mem_write_word(mem_fetch_word(REG_PC), REG_DE); - REG_PC += 2; - break; - case 0x63: /* ld (address), hl */ - mem_write_word(mem_fetch_word(REG_PC), REG_HL); - REG_PC += 2; - break; - case 0x73: /* ld (address), sp */ - mem_write_word(mem_fetch_word(REG_PC), REG_SP); - REG_PC += 2; - break; - - case 0xA8: /* ldd */ - do_ldid(-1); - break; - case 0xB8: /* lddr */ - do_ldidr(-1); - break; - case 0xA0: /* ldi */ - do_ldid(+1); - break; - case 0xB0: /* ldir */ - do_ldidr(+1); - break; - - case 0x44: /* neg */ - case 0x4C: - case 0x54: - case 0x5C: - case 0x64: - case 0x6C: - case 0x74: - case 0x7C: - do_negate(); - break; - - case 0x79: /* out (c), a */ - z80_out(REG_C, REG_A); - break; - case 0x41: /* out (c), b */ - z80_out(REG_C, REG_B); - break; - case 0x49: /* out (c), c */ - z80_out(REG_C, REG_C); - break; - case 0x51: /* out (c), d */ - z80_out(REG_C, REG_D); - break; - case 0x59: /* out (c), e */ - z80_out(REG_C, REG_E); - break; - case 0x61: /* out (c), h */ - z80_out(REG_C, REG_H); - break; - case 0x69: /* out (c), l */ - z80_out(REG_C, REG_L); - break; - case 0x71: /* out (c), 0 */ - z80_out(REG_C, 0); - break; - - case 0xAB: /* outd */ - do_outid(-1); - break; - case 0xBB: /* outdr */ - do_outidr(-1); - break; - case 0xA3: /* outi */ - do_outid(+1); - break; - case 0xB3: /* outir */ - do_outidr(+1); - break; - - case 0x4D: /* reti */ - case 0x5D: - case 0x6D: - case 0x7D: - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - z80_state.iff1 = z80_state.iff2; - z80_state.signal_eoi = true; /* Send EOI before next instruction */ - } - break; - - case 0x45: /* retn */ - case 0x55: - case 0x65: - case 0x75: - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - z80_state.iff1 = z80_state.iff2; - z80_state.nmi_in_progress = false; - break; - - case 0x6F: /* rld */ - do_rld(); - break; - - case 0x67: /* rrd */ - do_rrd(); - break; - - case 0x42: /* sbc hl, bc */ - do_sbc_word(REG_BC); - break; - case 0x52: /* sbc hl, de */ - do_sbc_word(REG_DE); - break; - case 0x62: /* sbc hl, hl */ - do_sbc_word(REG_HL); - break; - case 0x72: /* sbc hl, sp */ - do_sbc_word(REG_SP); - break; - - default: - /* Assume all others are NOP */ - break; + switch (instruction) { + case 0x4A: /* adc hl, bc */ + do_adc_word(REG_BC); + break; + case 0x5A: /* adc hl, de */ + do_adc_word(REG_DE); + break; + case 0x6A: /* adc hl, hl */ + do_adc_word(REG_HL); + break; + case 0x7A: /* adc hl, sp */ + do_adc_word(REG_SP); + break; + + case 0xA9: /* cpd */ + do_cpid(-1); + break; + case 0xB9: /* cpdr */ + do_cpidr(-1); + break; + + case 0xA1: /* cpi */ + do_cpid(+1); + break; + case 0xB1: /* cpir */ + do_cpidr(+1); + break; + + case 0x46: /* im 0 */ + case 0x66: + case 0x4E: + case 0x6E: + do_im0(); + break; + case 0x56: /* im 1 */ + case 0x76: + do_im1(); + break; + case 0x5E: /* im 2 */ + case 0x7E: + do_im2(); + break; + + case 0x78: /* in a, (c) */ + REG_A = in_with_flags(REG_C); + break; + case 0x40: /* in b, (c) */ + REG_B = in_with_flags(REG_C); + break; + case 0x48: /* in c, (c) */ + REG_C = in_with_flags(REG_C); + break; + case 0x50: /* in d, (c) */ + REG_D = in_with_flags(REG_C); + break; + case 0x58: /* in e, (c) */ + REG_E = in_with_flags(REG_C); + break; + case 0x60: /* in h, (c) */ + REG_H = in_with_flags(REG_C); + break; + case 0x68: /* in l, (c) */ + REG_L = in_with_flags(REG_C); + break; + + case 0xAA: /* ind */ + do_inid(-1); + break; + case 0xBA: /* indr */ + do_inidr(-1); + break; + case 0xA2: /* ini */ + do_inid(+1); + break; + case 0xB2: /* inir */ + do_inidr(+1); + break; + + case 0x57: /* ld a, i */ + do_ld_a_ir(REG_I); + break; + case 0x47: /* ld i, a */ + REG_I = REG_A; + break; + + case 0x5F: /* ld a, r */ + do_ld_a_ir(REG_R); + break; + case 0x4F: /* ld r, a */ + z80_state.rf = z80_state.rc = REG_A; + break; + + case 0x4B: /* ld bc, (address) */ + REG_BC = mem_read_word(mem_fetch_word(REG_PC)); + REG_PC += 2; + break; + case 0x5B: /* ld de, (address) */ + REG_DE = mem_read_word(mem_fetch_word(REG_PC)); + REG_PC += 2; + break; + case 0x6B: /* ld hl, (address) */ + /* this instruction is redundant with the 2A instruction */ + REG_HL = mem_read_word(mem_fetch_word(REG_PC)); + REG_PC += 2; + break; + case 0x7B: /* ld sp, (address) */ + REG_SP = mem_read_word(mem_fetch_word(REG_PC)); + REG_PC += 2; + break; + + case 0x43: /* ld (address), bc */ + mem_write_word(mem_fetch_word(REG_PC), REG_BC); + REG_PC += 2; + break; + case 0x53: /* ld (address), de */ + mem_write_word(mem_fetch_word(REG_PC), REG_DE); + REG_PC += 2; + break; + case 0x63: /* ld (address), hl */ + mem_write_word(mem_fetch_word(REG_PC), REG_HL); + REG_PC += 2; + break; + case 0x73: /* ld (address), sp */ + mem_write_word(mem_fetch_word(REG_PC), REG_SP); + REG_PC += 2; + break; + + case 0xA8: /* ldd */ + do_ldid(-1); + break; + case 0xB8: /* lddr */ + do_ldidr(-1); + break; + case 0xA0: /* ldi */ + do_ldid(+1); + break; + case 0xB0: /* ldir */ + do_ldidr(+1); + break; + + case 0x44: /* neg */ + case 0x4C: + case 0x54: + case 0x5C: + case 0x64: + case 0x6C: + case 0x74: + case 0x7C: + do_negate(); + break; + + case 0x79: /* out (c), a */ + z80_out(REG_C, REG_A); + break; + case 0x41: /* out (c), b */ + z80_out(REG_C, REG_B); + break; + case 0x49: /* out (c), c */ + z80_out(REG_C, REG_C); + break; + case 0x51: /* out (c), d */ + z80_out(REG_C, REG_D); + break; + case 0x59: /* out (c), e */ + z80_out(REG_C, REG_E); + break; + case 0x61: /* out (c), h */ + z80_out(REG_C, REG_H); + break; + case 0x69: /* out (c), l */ + z80_out(REG_C, REG_L); + break; + case 0x71: /* out (c), 0 */ + z80_out(REG_C, 0); + break; + + case 0xAB: /* outd */ + do_outid(-1); + break; + case 0xBB: /* outdr */ + do_outidr(-1); + break; + case 0xA3: /* outi */ + do_outid(+1); + break; + case 0xB3: /* outir */ + do_outidr(+1); + break; + + case 0x4D: /* reti */ + case 0x5D: + case 0x6D: + case 0x7D: + { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + z80_state.iff1 = z80_state.iff2; + z80_state.signal_eoi = true; /* Send EOI before next instruction */ + } + break; + + case 0x45: /* retn */ + case 0x55: + case 0x65: + case 0x75: + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + z80_state.iff1 = z80_state.iff2; + z80_state.nmi_in_progress = false; + break; + + case 0x6F: /* rld */ + do_rld(); + break; + + case 0x67: /* rrd */ + do_rrd(); + break; + + case 0x42: /* sbc hl, bc */ + do_sbc_word(REG_BC); + break; + case 0x52: /* sbc hl, de */ + do_sbc_word(REG_DE); + break; + case 0x62: /* sbc hl, hl */ + do_sbc_word(REG_HL); + break; + case 0x72: /* sbc hl, sp */ + do_sbc_word(REG_SP); + break; + + default: + /* Assume all others are NOP */ + break; } } - static inline void check_eoi(void) { if (!likely(z80_state.signal_eoi)) - return; + return; if (tracing(TRACE_IO)) { - fprintf(tracef, "[%12"PRIu64"] EOI: RETI executed\n", TSTATE); + fprintf(tracef, "[%12" PRIu64 "] EOI: RETI executed\n", TSTATE); } z80_state.signal_eoi = false; @@ -2482,1194 +2430,1131 @@ static inline void check_eoi(void) int z80_run(bool continuous, bool halted) { uint8_t instruction; - uint16_t address; /* generic temps */ + uint16_t address; /* generic temps */ wordregister *ix; /* loop to do a z80 instruction */ do { - if (tracing(TRACE_CPU)) { - diffstate(); - tracemem(); - fputc('\n', tracef); - } - check_eoi(); - for (;;) { - /* Poll for external event */ - if (z80_poll_external()) - return halted; - - /* Check for an interrupt */ - if (z80_state.nminterrupt && !z80_state.nmi_in_progress) { - halted = false; - do_nmi(); - } else if (z80_state.iff1 && !z80_state.ei_shadow && - poll_irq()) { - halted = false; - do_int(); - } - z80_state.ei_shadow = false; - if (!halted) - break; - TSTATE += 4; - - if (!continuous) - return halted; - } - - if (tracing(TRACE_CPU)) { - fprintf(tracef, "[%12"PRIu64"] PC=%04X ", TSTATE, REG_PC); - disassemble(z80_state.pc.word); - } - - ix = &z80_state.hl; /* Not an index instruction */ - - instruction = mem_fetch_m1(REG_PC++); - - indexed: - TSTATE += clk_main[instruction]; - inc_r(); - - switch(instruction) - { - case 0xCB: /* CB.. extended instruction */ - do_CB_instruction(ix); - break; - case 0xDD: /* DD.. extended instruction */ - ix = &z80_state.ix; - instruction = mem_fetch(REG_PC++); - goto indexed; - case 0xED: /* ED.. extended instruction */ - do_ED_instruction(ix); - break; - case 0xFD: /* FD.. extended instruction */ - ix = &z80_state.iy; - instruction = mem_fetch(REG_PC++); - goto indexed; - - case 0x8F: /* adc a, a */ - do_adc_byte(REG_A); - break; - case 0x88: /* adc a, b */ - do_adc_byte(REG_B); - break; - case 0x89: /* adc a, c */ - do_adc_byte(REG_C); - break; - case 0x8A: /* adc a, d */ - do_adc_byte(REG_D); - break; - case 0x8B: /* adc a, e */ - do_adc_byte(REG_E); - break; - case 0x8C: /* adc a, h */ - do_adc_byte(ix->byte.high); - break; - case 0x8D: /* adc a, l */ - do_adc_byte(ix->byte.low); - break; - case 0xCE: /* adc a, value */ - do_adc_byte(mem_fetch(REG_PC++)); - break; - case 0x8E: /* adc a, (hl) */ - do_adc_byte(mem_read(get_hl_addr(ix))); - break; - - case 0x87: /* add a, a */ - do_add_byte(REG_A); - break; - case 0x80: /* add a, b */ - do_add_byte(REG_B); - break; - case 0x81: /* add a, c */ - do_add_byte(REG_C); - break; - case 0x82: /* add a, d */ - do_add_byte(REG_D); - break; - case 0x83: /* add a, e */ - do_add_byte(REG_E); - break; - case 0x84: /* add a, h */ - do_add_byte(ix->byte.high); - break; - case 0x85: /* add a, l */ - do_add_byte(ix->byte.low); - break; - case 0xC6: /* add a, value */ - do_add_byte(mem_fetch(REG_PC++)); - break; - case 0x86: /* add a, (hl) */ - do_add_byte(mem_read(get_hl_addr(ix))); - break; - - case 0x09: /* add hl, bc */ - do_add_word(ix, REG_BC); - break; - case 0x19: /* add hl, de */ - do_add_word(ix, REG_DE); - break; - case 0x29: /* add hl, hl */ - do_add_word(ix, ix->word); - break; - case 0x39: /* add hl, sp */ - do_add_word(ix, REG_SP); - break; - - case 0xA7: /* and a */ - do_and_byte(REG_A); - break; - case 0xA0: /* and b */ - do_and_byte(REG_B); - break; - case 0xA1: /* and c */ - do_and_byte(REG_C); - break; - case 0xA2: /* and d */ - do_and_byte(REG_D); - break; - case 0xA3: /* and e */ - do_and_byte(REG_E); - break; - case 0xA4: /* and h */ - do_and_byte(ix->byte.high); - break; - case 0xA5: /* and l */ - do_and_byte(ix->byte.low); - break; - case 0xE6: /* and value */ - do_and_byte(mem_fetch(REG_PC++)); - break; - case 0xA6: /* and (hl) */ - do_and_byte(mem_read(get_hl_addr(ix))); - break; - - case 0xCD: /* call address */ - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - break; - - case 0xC4: /* call nz, address */ - if(!ZERO_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - case 0xCC: /* call z, address */ - if(ZERO_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - case 0xD4: /* call nc, address */ - if(!CARRY_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - case 0xDC: /* call c, address */ - if(CARRY_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - case 0xE4: /* call po, address */ - if(!PARITY_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - case 0xEC: /* call pe, address */ - if(PARITY_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - case 0xF4: /* call p, address */ - if(!SIGN_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - case 0xFC: /* call m, address */ - if(SIGN_FLAG) - { - address = mem_fetch_word(REG_PC); - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC + 2); - REG_PC = address; - TSTATE += 7; - break; - } - else - { - REG_PC += 2; - } - break; - - - case 0x3F: /* ccf */ - REG_F = (REG_F ^ CARRY_MASK) & ~SUBTRACT_MASK; - break; - - case 0xBF: /* cp a */ - do_cp(REG_A); - break; - case 0xB8: /* cp b */ - do_cp(REG_B); - break; - case 0xB9: /* cp c */ - do_cp(REG_C); - break; - case 0xBA: /* cp d */ - do_cp(REG_D); - break; - case 0xBB: /* cp e */ - do_cp(REG_E); - break; - case 0xBC: /* cp h */ - do_cp(ix->byte.high); - break; - case 0xBD: /* cp l */ - do_cp(ix->byte.low); - break; - case 0xFE: /* cp value */ - do_cp(mem_fetch(REG_PC++)); - break; - case 0xBE: /* cp (hl) */ - do_cp(mem_read(get_hl_addr(ix))); - break; - - case 0x2F: /* cpl */ - REG_A = ~REG_A; - REG_F |= (HALF_CARRY_MASK | SUBTRACT_MASK); - break; - - case 0x27: /* daa */ - do_daa(); - break; - - case 0x3D: /* dec a */ - do_flags_dec_byte(--REG_A); - break; - case 0x05: /* dec b */ - do_flags_dec_byte(--REG_B); - break; - case 0x0D: /* dec c */ - do_flags_dec_byte(--REG_C); - break; - case 0x15: /* dec d */ - do_flags_dec_byte(--REG_D); - break; - case 0x1D: /* dec e */ - do_flags_dec_byte(--REG_E); - break; - case 0x25: /* dec h */ - do_flags_dec_byte(--ix->byte.high); - break; - case 0x2D: /* dec l */ - do_flags_dec_byte(--ix->byte.low); - break; - - case 0x35: /* dec (hl) */ - { - uint16_t addr = get_hl_addr(ix); - uint8_t value = mem_read(addr) - 1; - mem_write(addr, value); - do_flags_dec_byte(value); - } - break; - - case 0x0B: /* dec bc */ - REG_BC--; - break; - case 0x1B: /* dec de */ - REG_DE--; - break; - case 0x2B: /* dec hl */ - ix->word--; - break; - case 0x3B: /* dec sp */ - REG_SP--; - break; - - case 0xF3: /* di */ - do_di(); - break; - - case 0x10: /* djnz offset */ - /* Zaks says no flag changes. */ - if(--REG_B != 0) - { - REG_PC += ((int8_t) mem_fetch(REG_PC)); - TSTATE += 5; - } - REG_PC++; - break; - - case 0xFB: /* ei */ - do_ei(); - break; - - case 0x08: /* ex af, af' */ - { - uint16_t temp; - temp = REG_AF; - REG_AF = REG_AF_PRIME; - REG_AF_PRIME = temp; - } - break; - - case 0xEB: /* ex de, hl */ - { - uint16_t temp; - temp = REG_DE; - REG_DE = ix->word; - ix->word = temp; - } - break; - - case 0xE3: /* ex (sp), hl */ - { - uint16_t temp; - temp = mem_read_word(REG_SP); - mem_write_word(REG_SP, ix->word); - ix->word = temp; - } - break; - - case 0xD9: /* exx */ - { - uint16_t tmp; - tmp = REG_BC_PRIME; - REG_BC_PRIME = REG_BC; - REG_BC = tmp; - tmp = REG_DE_PRIME; - REG_DE_PRIME = REG_DE; - REG_DE = tmp; - tmp = REG_HL_PRIME; - REG_HL_PRIME = REG_HL; - REG_HL = tmp; - } - break; - - case 0x76: /* halt */ - halted = 1; - break; - - case 0xDB: /* in a, (port) */ - REG_A = z80_in(mem_fetch(REG_PC++)); - break; - - case 0x3C: /* inc a */ - REG_A++; - do_flags_inc_byte(REG_A); - break; - case 0x04: /* inc b */ - REG_B++; - do_flags_inc_byte(REG_B); - break; - case 0x0C: /* inc c */ - REG_C++; - do_flags_inc_byte(REG_C); - break; - case 0x14: /* inc d */ - REG_D++; - do_flags_inc_byte(REG_D); - break; - case 0x1C: /* inc e */ - REG_E++; - do_flags_inc_byte(REG_E); - break; - case 0x24: /* inc h */ - ix->byte.high++; - do_flags_inc_byte(ix->byte.high); - break; - case 0x2C: /* inc l */ - ix->byte.low++; - do_flags_inc_byte(ix->byte.low); - break; - - case 0x34: /* inc (hl) */ - { - uint16_t addr = get_hl_addr(ix); - uint8_t value = mem_read(addr) + 1; - mem_write(addr, value); - do_flags_inc_byte(value); - } - break; - - case 0x03: /* inc bc */ - REG_BC++; - break; - case 0x13: /* inc de */ - REG_DE++; - break; - case 0x23: /* inc hl */ - ix->word++; - break; - case 0x33: /* inc sp */ - REG_SP++; - break; - - case 0xC3: /* jp address */ - REG_PC = mem_fetch_word(REG_PC); - break; - - case 0xE9: /* jp (hl) */ - REG_PC = ix->word; - break; - - case 0xC2: /* jp nz, address */ - if(!ZERO_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - case 0xCA: /* jp z, address */ - if(ZERO_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - case 0xD2: /* jp nc, address */ - if(!CARRY_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - case 0xDA: /* jp c, address */ - if(CARRY_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - case 0xE2: /* jp po, address */ - if(!PARITY_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - case 0xEA: /* jp pe, address */ - if(PARITY_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - case 0xF2: /* jp p, address */ - if(!SIGN_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - case 0xFA: /* jp m, address */ - if(SIGN_FLAG) - { - REG_PC = mem_fetch_word(REG_PC); - } - else - { - REG_PC += 2; - } - break; - - case 0x18: /* jr offset */ - REG_PC += (int8_t) mem_fetch(REG_PC); - REG_PC++; - break; - - case 0x20: /* jr nz, offset */ - if (!ZERO_FLAG) { - REG_PC += (int8_t) mem_fetch(REG_PC); - TSTATE += 5; - } - REG_PC++; - break; - case 0x28: /* jr z, offset */ - if (ZERO_FLAG) { - REG_PC += (int8_t) mem_fetch(REG_PC); - TSTATE += 5; - } - REG_PC++; - break; - case 0x30: /* jr nc, offset */ - if (!CARRY_FLAG) { - REG_PC += (int8_t) mem_fetch(REG_PC); - TSTATE += 5; - } - REG_PC++; - break; - case 0x38: /* jr c, offset */ - if (CARRY_FLAG) { - REG_PC += (int8_t) mem_fetch(REG_PC); - TSTATE += 5; - } - REG_PC++; - break; - - case 0x7F: /* ld a, a */ - REG_A = REG_A; - break; - case 0x78: /* ld a, b */ - REG_A = REG_B; - break; - case 0x79: /* ld a, c */ - REG_A = REG_C; - break; - case 0x7A: /* ld a, d */ - REG_A = REG_D; - break; - case 0x7B: /* ld a, e */ - REG_A = REG_E; - break; - case 0x7C: /* ld a, h */ - REG_A = ix->byte.high; - break; - case 0x7D: /* ld a, l */ - REG_A = ix->byte.low; - break; - case 0x47: /* ld b, a */ - REG_B = REG_A; - break; - case 0x40: /* ld b, b */ - REG_B = REG_B; - break; - case 0x41: /* ld b, c */ - REG_B = REG_C; - break; - case 0x42: /* ld b, d */ - REG_B = REG_D; - break; - case 0x43: /* ld b, e */ - REG_B = REG_E; - break; - case 0x44: /* ld b, h */ - REG_B = ix->byte.high; - break; - case 0x45: /* ld b, l */ - REG_B = ix->byte.low; - break; - case 0x4F: /* ld c, a */ - REG_C = REG_A; - break; - case 0x48: /* ld c, b */ - REG_C = REG_B; - break; - case 0x49: /* ld c, c */ - REG_C = REG_C; - break; - case 0x4A: /* ld c, d */ - REG_C = REG_D; - break; - case 0x4B: /* ld c, e */ - REG_C = REG_E; - break; - case 0x4C: /* ld c, h */ - REG_C = ix->byte.high; - break; - case 0x4D: /* ld c, l */ - REG_C = ix->byte.low; - break; - case 0x57: /* ld d, a */ - REG_D = REG_A; - break; - case 0x50: /* ld d, b */ - REG_D = REG_B; - break; - case 0x51: /* ld d, c */ - REG_D = REG_C; - break; - case 0x52: /* ld d, d */ - REG_D = REG_D; - break; - case 0x53: /* ld d, e */ - REG_D = REG_E; - break; - case 0x54: /* ld d, h */ - REG_D = ix->byte.high; - break; - case 0x55: /* ld d, l */ - REG_D = ix->byte.low; - break; - case 0x5F: /* ld e, a */ - REG_E = REG_A; - break; - case 0x58: /* ld e, b */ - REG_E = REG_B; - break; - case 0x59: /* ld e, c */ - REG_E = REG_C; - break; - case 0x5A: /* ld e, d */ - REG_E = REG_D; - break; - case 0x5B: /* ld e, e */ - REG_E = REG_E; - break; - case 0x5C: /* ld e, h */ - REG_E = ix->byte.high; - break; - case 0x5D: /* ld e, l */ - REG_E = ix->byte.low; - break; - case 0x67: /* ld h, a */ - ix->byte.high = REG_A; - break; - case 0x60: /* ld h, b */ - ix->byte.high = REG_B; - break; - case 0x61: /* ld h, c */ - ix->byte.high = REG_C; - break; - case 0x62: /* ld h, d */ - ix->byte.high = REG_D; - break; - case 0x63: /* ld h, e */ - ix->byte.high = REG_E; - break; - case 0x64: /* ld h, h */ - ix->byte.high = ix->byte.high; - break; - case 0x65: /* ld h, l */ - ix->byte.high = ix->byte.low; - break; - case 0x6F: /* ld l, a */ - ix->byte.low = REG_A; - break; - case 0x68: /* ld l, b */ - ix->byte.low = REG_B; - break; - case 0x69: /* ld l, c */ - ix->byte.low = REG_C; - break; - case 0x6A: /* ld l, d */ - ix->byte.low = REG_D; - break; - case 0x6B: /* ld l, e */ - ix->byte.low = REG_E; - break; - case 0x6C: /* ld l, h */ - ix->byte.low = ix->byte.high; - break; - case 0x6D: /* ld l, l */ - ix->byte.low = ix->byte.low; - break; - - case 0x02: /* ld (bc), a */ - mem_write(REG_BC, REG_A); - break; - case 0x12: /* ld (de), a */ - mem_write(REG_DE, REG_A); - break; - case 0x77: /* ld (hl), a */ - mem_write(get_hl_addr(ix), REG_A); - break; - case 0x70: /* ld (hl), b */ - mem_write(get_hl_addr(ix), REG_B); - break; - case 0x71: /* ld (hl), c */ - mem_write(get_hl_addr(ix), REG_C); - break; - case 0x72: /* ld (hl), d */ - mem_write(get_hl_addr(ix), REG_D); - break; - case 0x73: /* ld (hl), e */ - mem_write(get_hl_addr(ix), REG_E); - break; - case 0x74: /* ld (hl), h */ - mem_write(get_hl_addr(ix), REG_H); - break; - case 0x75: /* ld (hl), l */ - mem_write(get_hl_addr(ix), REG_L); - break; - - case 0x7E: /* ld a, (hl) */ - REG_A = mem_read(get_hl_addr(ix)); - break; - case 0x46: /* ld b, (hl) */ - REG_B = mem_read(get_hl_addr(ix)); - break; - case 0x4E: /* ld c, (hl) */ - REG_C = mem_read(get_hl_addr(ix)); - break; - case 0x56: /* ld d, (hl) */ - REG_D = mem_read(get_hl_addr(ix)); - break; - case 0x5E: /* ld e, (hl) */ - REG_E = mem_read(get_hl_addr(ix)); - break; - case 0x66: /* ld h, (hl) */ - REG_H = mem_read(get_hl_addr(ix)); - break; - case 0x6E: /* ld l, (hl) */ - REG_L = mem_read(get_hl_addr(ix)); - break; - - case 0x3E: /* ld a, value */ - REG_A = mem_fetch(REG_PC++); - break; - case 0x06: /* ld b, value */ - REG_B = mem_fetch(REG_PC++); - break; - case 0x0E: /* ld c, value */ - REG_C = mem_fetch(REG_PC++); - break; - case 0x16: /* ld d, value */ - REG_D = mem_fetch(REG_PC++); - break; - case 0x1E: /* ld e, value */ - REG_E = mem_fetch(REG_PC++); - break; - case 0x26: /* ld h, value */ - ix->byte.high = mem_fetch(REG_PC++); - break; - case 0x2E: /* ld l, value */ - ix->byte.low = mem_fetch(REG_PC++); - break; - - case 0x01: /* ld bc, value */ - REG_BC = mem_fetch_word(REG_PC); - REG_PC += 2; - break; - case 0x11: /* ld de, value */ - REG_DE = mem_fetch_word(REG_PC); - REG_PC += 2; - break; - case 0x21: /* ld hl, value */ - ix->word = mem_fetch_word(REG_PC); - REG_PC += 2; - break; - case 0x31: /* ld sp, value */ - REG_SP = mem_fetch_word(REG_PC); - REG_PC += 2; - break; - - - case 0x3A: /* ld a, (address) */ - /* this one is missing from Zaks */ - REG_A = mem_read(mem_fetch_word(REG_PC)); - REG_PC += 2; - break; - - case 0x0A: /* ld a, (bc) */ - REG_A = mem_read(REG_BC); - break; - case 0x1A: /* ld a, (de) */ - REG_A = mem_read(REG_DE); - break; - - case 0x32: /* ld (address), a */ - mem_write(mem_fetch_word(REG_PC), REG_A); - REG_PC += 2; - break; - - case 0x22: /* ld (address), hl */ - mem_write_word(mem_fetch_word(REG_PC), ix->word); - REG_PC += 2; - break; - - case 0x36: /* ld (hl), value */ - { - uint16_t addr = get_hl_addr(ix); - mem_write(addr, mem_fetch(REG_PC++)); - break; - } - - case 0x2A: /* ld hl, (address) */ - ix->word = mem_read_word(mem_fetch_word(REG_PC)); - REG_PC += 2; - break; - - case 0xF9: /* ld sp, hl */ - REG_SP = ix->word; - break; - - case 0x00: /* nop */ - break; - - case 0xF6: /* or value */ - do_or_byte(mem_fetch(REG_PC++)); - break; - - case 0xB7: /* or a */ - do_or_byte(REG_A); - break; - case 0xB0: /* or b */ - do_or_byte(REG_B); - break; - case 0xB1: /* or c */ - do_or_byte(REG_C); - break; - case 0xB2: /* or d */ - do_or_byte(REG_D); - break; - case 0xB3: /* or e */ - do_or_byte(REG_E); - break; - case 0xB4: /* or h */ - do_or_byte(ix->byte.high); - break; - case 0xB5: /* or l */ - do_or_byte(ix->byte.low); - break; - - case 0xB6: /* or (hl) */ - do_or_byte(mem_read(get_hl_addr(ix))); - break; - - case 0xD3: /* out (port), a */ - z80_out(mem_fetch(REG_PC++), REG_A); - break; - - case 0xC1: /* pop bc */ - REG_BC = mem_read_word(REG_SP); - REG_SP += 2; - break; - case 0xD1: /* pop de */ - REG_DE = mem_read_word(REG_SP); - REG_SP += 2; - break; - case 0xE1: /* pop hl */ - ix->word = mem_read_word(REG_SP); - REG_SP += 2; - break; - case 0xF1: /* pop af */ - REG_AF = mem_read_word(REG_SP); - REG_SP += 2; - break; - - case 0xC5: /* push bc */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_BC); - break; - case 0xD5: /* push de */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_DE); - break; - case 0xE5: /* push hl */ - REG_SP -= 2; - mem_write_word(REG_SP, ix->word); - break; - case 0xF5: /* push af */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_AF); - break; - - case 0xC9: /* ret */ - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - break; - - case 0xC0: /* ret nz */ - if(!ZERO_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - case 0xC8: /* ret z */ - if(ZERO_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - case 0xD0: /* ret nc */ - if(!CARRY_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - case 0xD8: /* ret c */ - if(CARRY_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - case 0xE0: /* ret po */ - if(!PARITY_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - case 0xE8: /* ret pe */ - if(PARITY_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - case 0xF0: /* ret p */ - if(!SIGN_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - case 0xF8: /* ret m */ - if(SIGN_FLAG) - { - REG_PC = mem_read_word(REG_SP); - REG_SP += 2; - TSTATE += 6; - } - break; - - case 0x17: /* rla */ - do_rla(); - break; - - case 0x07: /* rlca */ - do_rlca(); - break; - - case 0x1F: /* rra */ - do_rra(); - break; - - case 0x0F: /* rrca */ - do_rrca(); - break; - - case 0xC7: /* rst 00h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x00; - break; - case 0xCF: /* rst 08h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x08; - break; - case 0xD7: /* rst 10h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x10; - break; - case 0xDF: /* rst 18h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x18; - break; - case 0xE7: /* rst 20h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x20; - break; - case 0xEF: /* rst 28h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x28; - break; - case 0xF7: /* rst 30h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x30; - break; - case 0xFF: /* rst 38h */ - REG_SP -= 2; - mem_write_word(REG_SP, REG_PC); - REG_PC = 0x38; - break; - - case 0x37: /* scf */ - REG_F = (REG_F | CARRY_MASK) & ~(SUBTRACT_MASK | HALF_CARRY_MASK); - break; - - case 0x9F: /* sbc a, a */ - do_sbc_byte(REG_A); - break; - case 0x98: /* sbc a, b */ - do_sbc_byte(REG_B); - break; - case 0x99: /* sbc a, c */ - do_sbc_byte(REG_C); - break; - case 0x9A: /* sbc a, d */ - do_sbc_byte(REG_D); - break; - case 0x9B: /* sbc a, e */ - do_sbc_byte(REG_E); - break; - case 0x9C: /* sbc a, h */ - do_sbc_byte(ix->byte.high); - break; - case 0x9D: /* sbc a, l */ - do_sbc_byte(ix->byte.low); - break; - case 0xDE: /* sbc a, value */ - do_sbc_byte(mem_fetch(REG_PC++)); - break; - case 0x9E: /* sbc a, (hl) */ - do_sbc_byte(mem_read(get_hl_addr(ix))); - break; - - case 0x97: /* sub a, a */ - do_sub_byte(REG_A); - break; - case 0x90: /* sub a, b */ - do_sub_byte(REG_B); - break; - case 0x91: /* sub a, c */ - do_sub_byte(REG_C); - break; - case 0x92: /* sub a, d */ - do_sub_byte(REG_D); - break; - case 0x93: /* sub a, e */ - do_sub_byte(REG_E); - break; - case 0x94: /* sub a, h */ - do_sub_byte(ix->byte.high); - break; - case 0x95: /* sub a, l */ - do_sub_byte(ix->byte.low); - break; - case 0xD6: /* sub a, value */ - do_sub_byte(mem_fetch(REG_PC++)); - break; - case 0x96: /* sub a, (hl) */ - do_sub_byte(mem_read(get_hl_addr(ix))); - break; - - case 0xEE: /* xor value */ - do_xor_byte(mem_fetch(REG_PC++)); - break; - - case 0xAF: /* xor a */ - do_xor_byte(REG_A); - break; - case 0xA8: /* xor b */ - do_xor_byte(REG_B); - break; - case 0xA9: /* xor c */ - do_xor_byte(REG_C); - break; - case 0xAA: /* xor d */ - do_xor_byte(REG_D); - break; - case 0xAB: /* xor e */ - do_xor_byte(REG_E); - break; - case 0xAC: /* xor h */ - do_xor_byte(ix->byte.high); - break; - case 0xAD: /* xor l */ - do_xor_byte(ix->byte.low); - break; - case 0xAE: /* xor (hl) */ - do_xor_byte(mem_read(get_hl_addr(ix))); - break; - } + if (tracing(TRACE_CPU)) { + diffstate(); + tracemem(); + fputc('\n', tracef); + } + check_eoi(); + for (;;) { + /* Poll for external event */ + if (z80_poll_external()) + return halted; + + /* Check for an interrupt */ + if (z80_state.nminterrupt && !z80_state.nmi_in_progress) { + halted = false; + do_nmi(); + } else if (z80_state.iff1 && !z80_state.ei_shadow && poll_irq()) { + halted = false; + do_int(); + } + z80_state.ei_shadow = false; + if (!halted) + break; + TSTATE += 4; + + if (!continuous) + return halted; + } + + if (tracing(TRACE_CPU)) { + fprintf(tracef, "[%12" PRIu64 "] PC=%04X ", TSTATE, REG_PC); + disassemble(z80_state.pc.word); + } + + ix = &z80_state.hl; /* Not an index instruction */ + + instruction = mem_fetch_m1(REG_PC++); + +indexed: + TSTATE += clk_main[instruction]; + inc_r(); + + switch (instruction) { + case 0xCB: /* CB.. extended instruction */ + do_CB_instruction(ix); + break; + case 0xDD: /* DD.. extended instruction */ + ix = &z80_state.ix; + instruction = mem_fetch(REG_PC++); + goto indexed; + case 0xED: /* ED.. extended instruction */ + do_ED_instruction(ix); + break; + case 0xFD: /* FD.. extended instruction */ + ix = &z80_state.iy; + instruction = mem_fetch(REG_PC++); + goto indexed; + + case 0x8F: /* adc a, a */ + do_adc_byte(REG_A); + break; + case 0x88: /* adc a, b */ + do_adc_byte(REG_B); + break; + case 0x89: /* adc a, c */ + do_adc_byte(REG_C); + break; + case 0x8A: /* adc a, d */ + do_adc_byte(REG_D); + break; + case 0x8B: /* adc a, e */ + do_adc_byte(REG_E); + break; + case 0x8C: /* adc a, h */ + do_adc_byte(ix->byte.high); + break; + case 0x8D: /* adc a, l */ + do_adc_byte(ix->byte.low); + break; + case 0xCE: /* adc a, value */ + do_adc_byte(mem_fetch(REG_PC++)); + break; + case 0x8E: /* adc a, (hl) */ + do_adc_byte(mem_read(get_hl_addr(ix))); + break; + + case 0x87: /* add a, a */ + do_add_byte(REG_A); + break; + case 0x80: /* add a, b */ + do_add_byte(REG_B); + break; + case 0x81: /* add a, c */ + do_add_byte(REG_C); + break; + case 0x82: /* add a, d */ + do_add_byte(REG_D); + break; + case 0x83: /* add a, e */ + do_add_byte(REG_E); + break; + case 0x84: /* add a, h */ + do_add_byte(ix->byte.high); + break; + case 0x85: /* add a, l */ + do_add_byte(ix->byte.low); + break; + case 0xC6: /* add a, value */ + do_add_byte(mem_fetch(REG_PC++)); + break; + case 0x86: /* add a, (hl) */ + do_add_byte(mem_read(get_hl_addr(ix))); + break; + + case 0x09: /* add hl, bc */ + do_add_word(ix, REG_BC); + break; + case 0x19: /* add hl, de */ + do_add_word(ix, REG_DE); + break; + case 0x29: /* add hl, hl */ + do_add_word(ix, ix->word); + break; + case 0x39: /* add hl, sp */ + do_add_word(ix, REG_SP); + break; + + case 0xA7: /* and a */ + do_and_byte(REG_A); + break; + case 0xA0: /* and b */ + do_and_byte(REG_B); + break; + case 0xA1: /* and c */ + do_and_byte(REG_C); + break; + case 0xA2: /* and d */ + do_and_byte(REG_D); + break; + case 0xA3: /* and e */ + do_and_byte(REG_E); + break; + case 0xA4: /* and h */ + do_and_byte(ix->byte.high); + break; + case 0xA5: /* and l */ + do_and_byte(ix->byte.low); + break; + case 0xE6: /* and value */ + do_and_byte(mem_fetch(REG_PC++)); + break; + case 0xA6: /* and (hl) */ + do_and_byte(mem_read(get_hl_addr(ix))); + break; + + case 0xCD: /* call address */ + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + break; + + case 0xC4: /* call nz, address */ + if (!ZERO_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + case 0xCC: /* call z, address */ + if (ZERO_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + case 0xD4: /* call nc, address */ + if (!CARRY_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + case 0xDC: /* call c, address */ + if (CARRY_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + case 0xE4: /* call po, address */ + if (!PARITY_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + case 0xEC: /* call pe, address */ + if (PARITY_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + case 0xF4: /* call p, address */ + if (!SIGN_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + case 0xFC: /* call m, address */ + if (SIGN_FLAG) { + address = mem_fetch_word(REG_PC); + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC + 2); + REG_PC = address; + TSTATE += 7; + break; + } else { + REG_PC += 2; + } + break; + + case 0x3F: /* ccf */ + REG_F = (REG_F ^ CARRY_MASK) & ~SUBTRACT_MASK; + break; + + case 0xBF: /* cp a */ + do_cp(REG_A); + break; + case 0xB8: /* cp b */ + do_cp(REG_B); + break; + case 0xB9: /* cp c */ + do_cp(REG_C); + break; + case 0xBA: /* cp d */ + do_cp(REG_D); + break; + case 0xBB: /* cp e */ + do_cp(REG_E); + break; + case 0xBC: /* cp h */ + do_cp(ix->byte.high); + break; + case 0xBD: /* cp l */ + do_cp(ix->byte.low); + break; + case 0xFE: /* cp value */ + do_cp(mem_fetch(REG_PC++)); + break; + case 0xBE: /* cp (hl) */ + do_cp(mem_read(get_hl_addr(ix))); + break; + + case 0x2F: /* cpl */ + REG_A = ~REG_A; + REG_F |= (HALF_CARRY_MASK | SUBTRACT_MASK); + break; + + case 0x27: /* daa */ + do_daa(); + break; + + case 0x3D: /* dec a */ + do_flags_dec_byte(--REG_A); + break; + case 0x05: /* dec b */ + do_flags_dec_byte(--REG_B); + break; + case 0x0D: /* dec c */ + do_flags_dec_byte(--REG_C); + break; + case 0x15: /* dec d */ + do_flags_dec_byte(--REG_D); + break; + case 0x1D: /* dec e */ + do_flags_dec_byte(--REG_E); + break; + case 0x25: /* dec h */ + do_flags_dec_byte(--ix->byte.high); + break; + case 0x2D: /* dec l */ + do_flags_dec_byte(--ix->byte.low); + break; + + case 0x35: /* dec (hl) */ + { + uint16_t addr = get_hl_addr(ix); + uint8_t value = mem_read(addr) - 1; + mem_write(addr, value); + do_flags_dec_byte(value); + } + break; + + case 0x0B: /* dec bc */ + REG_BC--; + break; + case 0x1B: /* dec de */ + REG_DE--; + break; + case 0x2B: /* dec hl */ + ix->word--; + break; + case 0x3B: /* dec sp */ + REG_SP--; + break; + + case 0xF3: /* di */ + do_di(); + break; + + case 0x10: /* djnz offset */ + /* Zaks says no flag changes. */ + if (--REG_B != 0) { + REG_PC += ((int8_t) mem_fetch(REG_PC)); + TSTATE += 5; + } + REG_PC++; + break; + + case 0xFB: /* ei */ + do_ei(); + break; + + case 0x08: /* ex af, af' */ + { + uint16_t temp; + temp = REG_AF; + REG_AF = REG_AF_PRIME; + REG_AF_PRIME = temp; + } + break; + + case 0xEB: /* ex de, hl */ + { + uint16_t temp; + temp = REG_DE; + REG_DE = ix->word; + ix->word = temp; + } + break; + + case 0xE3: /* ex (sp), hl */ + { + uint16_t temp; + temp = mem_read_word(REG_SP); + mem_write_word(REG_SP, ix->word); + ix->word = temp; + } + break; + + case 0xD9: /* exx */ + { + uint16_t tmp; + tmp = REG_BC_PRIME; + REG_BC_PRIME = REG_BC; + REG_BC = tmp; + tmp = REG_DE_PRIME; + REG_DE_PRIME = REG_DE; + REG_DE = tmp; + tmp = REG_HL_PRIME; + REG_HL_PRIME = REG_HL; + REG_HL = tmp; + } + break; + + case 0x76: /* halt */ + halted = 1; + break; + + case 0xDB: /* in a, (port) */ + REG_A = z80_in(mem_fetch(REG_PC++)); + break; + + case 0x3C: /* inc a */ + REG_A++; + do_flags_inc_byte(REG_A); + break; + case 0x04: /* inc b */ + REG_B++; + do_flags_inc_byte(REG_B); + break; + case 0x0C: /* inc c */ + REG_C++; + do_flags_inc_byte(REG_C); + break; + case 0x14: /* inc d */ + REG_D++; + do_flags_inc_byte(REG_D); + break; + case 0x1C: /* inc e */ + REG_E++; + do_flags_inc_byte(REG_E); + break; + case 0x24: /* inc h */ + ix->byte.high++; + do_flags_inc_byte(ix->byte.high); + break; + case 0x2C: /* inc l */ + ix->byte.low++; + do_flags_inc_byte(ix->byte.low); + break; + + case 0x34: /* inc (hl) */ + { + uint16_t addr = get_hl_addr(ix); + uint8_t value = mem_read(addr) + 1; + mem_write(addr, value); + do_flags_inc_byte(value); + } + break; + + case 0x03: /* inc bc */ + REG_BC++; + break; + case 0x13: /* inc de */ + REG_DE++; + break; + case 0x23: /* inc hl */ + ix->word++; + break; + case 0x33: /* inc sp */ + REG_SP++; + break; + + case 0xC3: /* jp address */ + REG_PC = mem_fetch_word(REG_PC); + break; + + case 0xE9: /* jp (hl) */ + REG_PC = ix->word; + break; + + case 0xC2: /* jp nz, address */ + if (!ZERO_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + case 0xCA: /* jp z, address */ + if (ZERO_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + case 0xD2: /* jp nc, address */ + if (!CARRY_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + case 0xDA: /* jp c, address */ + if (CARRY_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + case 0xE2: /* jp po, address */ + if (!PARITY_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + case 0xEA: /* jp pe, address */ + if (PARITY_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + case 0xF2: /* jp p, address */ + if (!SIGN_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + case 0xFA: /* jp m, address */ + if (SIGN_FLAG) { + REG_PC = mem_fetch_word(REG_PC); + } else { + REG_PC += 2; + } + break; + + case 0x18: /* jr offset */ + REG_PC += (int8_t) mem_fetch(REG_PC); + REG_PC++; + break; + + case 0x20: /* jr nz, offset */ + if (!ZERO_FLAG) { + REG_PC += (int8_t) mem_fetch(REG_PC); + TSTATE += 5; + } + REG_PC++; + break; + case 0x28: /* jr z, offset */ + if (ZERO_FLAG) { + REG_PC += (int8_t) mem_fetch(REG_PC); + TSTATE += 5; + } + REG_PC++; + break; + case 0x30: /* jr nc, offset */ + if (!CARRY_FLAG) { + REG_PC += (int8_t) mem_fetch(REG_PC); + TSTATE += 5; + } + REG_PC++; + break; + case 0x38: /* jr c, offset */ + if (CARRY_FLAG) { + REG_PC += (int8_t) mem_fetch(REG_PC); + TSTATE += 5; + } + REG_PC++; + break; + + case 0x7F: /* ld a, a */ + REG_A = REG_A; + break; + case 0x78: /* ld a, b */ + REG_A = REG_B; + break; + case 0x79: /* ld a, c */ + REG_A = REG_C; + break; + case 0x7A: /* ld a, d */ + REG_A = REG_D; + break; + case 0x7B: /* ld a, e */ + REG_A = REG_E; + break; + case 0x7C: /* ld a, h */ + REG_A = ix->byte.high; + break; + case 0x7D: /* ld a, l */ + REG_A = ix->byte.low; + break; + case 0x47: /* ld b, a */ + REG_B = REG_A; + break; + case 0x40: /* ld b, b */ + REG_B = REG_B; + break; + case 0x41: /* ld b, c */ + REG_B = REG_C; + break; + case 0x42: /* ld b, d */ + REG_B = REG_D; + break; + case 0x43: /* ld b, e */ + REG_B = REG_E; + break; + case 0x44: /* ld b, h */ + REG_B = ix->byte.high; + break; + case 0x45: /* ld b, l */ + REG_B = ix->byte.low; + break; + case 0x4F: /* ld c, a */ + REG_C = REG_A; + break; + case 0x48: /* ld c, b */ + REG_C = REG_B; + break; + case 0x49: /* ld c, c */ + REG_C = REG_C; + break; + case 0x4A: /* ld c, d */ + REG_C = REG_D; + break; + case 0x4B: /* ld c, e */ + REG_C = REG_E; + break; + case 0x4C: /* ld c, h */ + REG_C = ix->byte.high; + break; + case 0x4D: /* ld c, l */ + REG_C = ix->byte.low; + break; + case 0x57: /* ld d, a */ + REG_D = REG_A; + break; + case 0x50: /* ld d, b */ + REG_D = REG_B; + break; + case 0x51: /* ld d, c */ + REG_D = REG_C; + break; + case 0x52: /* ld d, d */ + REG_D = REG_D; + break; + case 0x53: /* ld d, e */ + REG_D = REG_E; + break; + case 0x54: /* ld d, h */ + REG_D = ix->byte.high; + break; + case 0x55: /* ld d, l */ + REG_D = ix->byte.low; + break; + case 0x5F: /* ld e, a */ + REG_E = REG_A; + break; + case 0x58: /* ld e, b */ + REG_E = REG_B; + break; + case 0x59: /* ld e, c */ + REG_E = REG_C; + break; + case 0x5A: /* ld e, d */ + REG_E = REG_D; + break; + case 0x5B: /* ld e, e */ + REG_E = REG_E; + break; + case 0x5C: /* ld e, h */ + REG_E = ix->byte.high; + break; + case 0x5D: /* ld e, l */ + REG_E = ix->byte.low; + break; + case 0x67: /* ld h, a */ + ix->byte.high = REG_A; + break; + case 0x60: /* ld h, b */ + ix->byte.high = REG_B; + break; + case 0x61: /* ld h, c */ + ix->byte.high = REG_C; + break; + case 0x62: /* ld h, d */ + ix->byte.high = REG_D; + break; + case 0x63: /* ld h, e */ + ix->byte.high = REG_E; + break; + case 0x64: /* ld h, h */ + ix->byte.high = ix->byte.high; + break; + case 0x65: /* ld h, l */ + ix->byte.high = ix->byte.low; + break; + case 0x6F: /* ld l, a */ + ix->byte.low = REG_A; + break; + case 0x68: /* ld l, b */ + ix->byte.low = REG_B; + break; + case 0x69: /* ld l, c */ + ix->byte.low = REG_C; + break; + case 0x6A: /* ld l, d */ + ix->byte.low = REG_D; + break; + case 0x6B: /* ld l, e */ + ix->byte.low = REG_E; + break; + case 0x6C: /* ld l, h */ + ix->byte.low = ix->byte.high; + break; + case 0x6D: /* ld l, l */ + ix->byte.low = ix->byte.low; + break; + + case 0x02: /* ld (bc), a */ + mem_write(REG_BC, REG_A); + break; + case 0x12: /* ld (de), a */ + mem_write(REG_DE, REG_A); + break; + case 0x77: /* ld (hl), a */ + mem_write(get_hl_addr(ix), REG_A); + break; + case 0x70: /* ld (hl), b */ + mem_write(get_hl_addr(ix), REG_B); + break; + case 0x71: /* ld (hl), c */ + mem_write(get_hl_addr(ix), REG_C); + break; + case 0x72: /* ld (hl), d */ + mem_write(get_hl_addr(ix), REG_D); + break; + case 0x73: /* ld (hl), e */ + mem_write(get_hl_addr(ix), REG_E); + break; + case 0x74: /* ld (hl), h */ + mem_write(get_hl_addr(ix), REG_H); + break; + case 0x75: /* ld (hl), l */ + mem_write(get_hl_addr(ix), REG_L); + break; + + case 0x7E: /* ld a, (hl) */ + REG_A = mem_read(get_hl_addr(ix)); + break; + case 0x46: /* ld b, (hl) */ + REG_B = mem_read(get_hl_addr(ix)); + break; + case 0x4E: /* ld c, (hl) */ + REG_C = mem_read(get_hl_addr(ix)); + break; + case 0x56: /* ld d, (hl) */ + REG_D = mem_read(get_hl_addr(ix)); + break; + case 0x5E: /* ld e, (hl) */ + REG_E = mem_read(get_hl_addr(ix)); + break; + case 0x66: /* ld h, (hl) */ + REG_H = mem_read(get_hl_addr(ix)); + break; + case 0x6E: /* ld l, (hl) */ + REG_L = mem_read(get_hl_addr(ix)); + break; + + case 0x3E: /* ld a, value */ + REG_A = mem_fetch(REG_PC++); + break; + case 0x06: /* ld b, value */ + REG_B = mem_fetch(REG_PC++); + break; + case 0x0E: /* ld c, value */ + REG_C = mem_fetch(REG_PC++); + break; + case 0x16: /* ld d, value */ + REG_D = mem_fetch(REG_PC++); + break; + case 0x1E: /* ld e, value */ + REG_E = mem_fetch(REG_PC++); + break; + case 0x26: /* ld h, value */ + ix->byte.high = mem_fetch(REG_PC++); + break; + case 0x2E: /* ld l, value */ + ix->byte.low = mem_fetch(REG_PC++); + break; + + case 0x01: /* ld bc, value */ + REG_BC = mem_fetch_word(REG_PC); + REG_PC += 2; + break; + case 0x11: /* ld de, value */ + REG_DE = mem_fetch_word(REG_PC); + REG_PC += 2; + break; + case 0x21: /* ld hl, value */ + ix->word = mem_fetch_word(REG_PC); + REG_PC += 2; + break; + case 0x31: /* ld sp, value */ + REG_SP = mem_fetch_word(REG_PC); + REG_PC += 2; + break; + + case 0x3A: /* ld a, (address) */ + /* this one is missing from Zaks */ + REG_A = mem_read(mem_fetch_word(REG_PC)); + REG_PC += 2; + break; + + case 0x0A: /* ld a, (bc) */ + REG_A = mem_read(REG_BC); + break; + case 0x1A: /* ld a, (de) */ + REG_A = mem_read(REG_DE); + break; + + case 0x32: /* ld (address), a */ + mem_write(mem_fetch_word(REG_PC), REG_A); + REG_PC += 2; + break; + + case 0x22: /* ld (address), hl */ + mem_write_word(mem_fetch_word(REG_PC), ix->word); + REG_PC += 2; + break; + + case 0x36: /* ld (hl), value */ + { + uint16_t addr = get_hl_addr(ix); + mem_write(addr, mem_fetch(REG_PC++)); + break; + } + + case 0x2A: /* ld hl, (address) */ + ix->word = mem_read_word(mem_fetch_word(REG_PC)); + REG_PC += 2; + break; + + case 0xF9: /* ld sp, hl */ + REG_SP = ix->word; + break; + + case 0x00: /* nop */ + break; + + case 0xF6: /* or value */ + do_or_byte(mem_fetch(REG_PC++)); + break; + + case 0xB7: /* or a */ + do_or_byte(REG_A); + break; + case 0xB0: /* or b */ + do_or_byte(REG_B); + break; + case 0xB1: /* or c */ + do_or_byte(REG_C); + break; + case 0xB2: /* or d */ + do_or_byte(REG_D); + break; + case 0xB3: /* or e */ + do_or_byte(REG_E); + break; + case 0xB4: /* or h */ + do_or_byte(ix->byte.high); + break; + case 0xB5: /* or l */ + do_or_byte(ix->byte.low); + break; + + case 0xB6: /* or (hl) */ + do_or_byte(mem_read(get_hl_addr(ix))); + break; + + case 0xD3: /* out (port), a */ + z80_out(mem_fetch(REG_PC++), REG_A); + break; + + case 0xC1: /* pop bc */ + REG_BC = mem_read_word(REG_SP); + REG_SP += 2; + break; + case 0xD1: /* pop de */ + REG_DE = mem_read_word(REG_SP); + REG_SP += 2; + break; + case 0xE1: /* pop hl */ + ix->word = mem_read_word(REG_SP); + REG_SP += 2; + break; + case 0xF1: /* pop af */ + REG_AF = mem_read_word(REG_SP); + REG_SP += 2; + break; + + case 0xC5: /* push bc */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_BC); + break; + case 0xD5: /* push de */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_DE); + break; + case 0xE5: /* push hl */ + REG_SP -= 2; + mem_write_word(REG_SP, ix->word); + break; + case 0xF5: /* push af */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_AF); + break; + + case 0xC9: /* ret */ + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + break; + + case 0xC0: /* ret nz */ + if (!ZERO_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + case 0xC8: /* ret z */ + if (ZERO_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + case 0xD0: /* ret nc */ + if (!CARRY_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + case 0xD8: /* ret c */ + if (CARRY_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + case 0xE0: /* ret po */ + if (!PARITY_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + case 0xE8: /* ret pe */ + if (PARITY_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + case 0xF0: /* ret p */ + if (!SIGN_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + case 0xF8: /* ret m */ + if (SIGN_FLAG) { + REG_PC = mem_read_word(REG_SP); + REG_SP += 2; + TSTATE += 6; + } + break; + + case 0x17: /* rla */ + do_rla(); + break; + + case 0x07: /* rlca */ + do_rlca(); + break; + + case 0x1F: /* rra */ + do_rra(); + break; + + case 0x0F: /* rrca */ + do_rrca(); + break; + + case 0xC7: /* rst 00h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x00; + break; + case 0xCF: /* rst 08h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x08; + break; + case 0xD7: /* rst 10h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x10; + break; + case 0xDF: /* rst 18h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x18; + break; + case 0xE7: /* rst 20h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x20; + break; + case 0xEF: /* rst 28h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x28; + break; + case 0xF7: /* rst 30h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x30; + break; + case 0xFF: /* rst 38h */ + REG_SP -= 2; + mem_write_word(REG_SP, REG_PC); + REG_PC = 0x38; + break; + + case 0x37: /* scf */ + REG_F = (REG_F | CARRY_MASK) & ~(SUBTRACT_MASK | HALF_CARRY_MASK); + break; + + case 0x9F: /* sbc a, a */ + do_sbc_byte(REG_A); + break; + case 0x98: /* sbc a, b */ + do_sbc_byte(REG_B); + break; + case 0x99: /* sbc a, c */ + do_sbc_byte(REG_C); + break; + case 0x9A: /* sbc a, d */ + do_sbc_byte(REG_D); + break; + case 0x9B: /* sbc a, e */ + do_sbc_byte(REG_E); + break; + case 0x9C: /* sbc a, h */ + do_sbc_byte(ix->byte.high); + break; + case 0x9D: /* sbc a, l */ + do_sbc_byte(ix->byte.low); + break; + case 0xDE: /* sbc a, value */ + do_sbc_byte(mem_fetch(REG_PC++)); + break; + case 0x9E: /* sbc a, (hl) */ + do_sbc_byte(mem_read(get_hl_addr(ix))); + break; + + case 0x97: /* sub a, a */ + do_sub_byte(REG_A); + break; + case 0x90: /* sub a, b */ + do_sub_byte(REG_B); + break; + case 0x91: /* sub a, c */ + do_sub_byte(REG_C); + break; + case 0x92: /* sub a, d */ + do_sub_byte(REG_D); + break; + case 0x93: /* sub a, e */ + do_sub_byte(REG_E); + break; + case 0x94: /* sub a, h */ + do_sub_byte(ix->byte.high); + break; + case 0x95: /* sub a, l */ + do_sub_byte(ix->byte.low); + break; + case 0xD6: /* sub a, value */ + do_sub_byte(mem_fetch(REG_PC++)); + break; + case 0x96: /* sub a, (hl) */ + do_sub_byte(mem_read(get_hl_addr(ix))); + break; + + case 0xEE: /* xor value */ + do_xor_byte(mem_fetch(REG_PC++)); + break; + + case 0xAF: /* xor a */ + do_xor_byte(REG_A); + break; + case 0xA8: /* xor b */ + do_xor_byte(REG_B); + break; + case 0xA9: /* xor c */ + do_xor_byte(REG_C); + break; + case 0xAA: /* xor d */ + do_xor_byte(REG_D); + break; + case 0xAB: /* xor e */ + do_xor_byte(REG_E); + break; + case 0xAC: /* xor h */ + do_xor_byte(ix->byte.high); + break; + case 0xAD: /* xor l */ + do_xor_byte(ix->byte.low); + break; + case 0xAE: /* xor (hl) */ + do_xor_byte(mem_read(get_hl_addr(ix))); + break; + } } while (continuous); return halted; } - -void -z80_reset(void) +void z80_reset(void) { REG_PC = 0; z80_state.i = 0; @@ -3698,19 +3583,19 @@ static void diffstate(void) static struct z80_state_struct old_state; if (!tracing(TRACE_CPU)) - return; - - BREG(A,af.byte.high); - WREG(BC,bc); - WREG(DE,de); - WREG(HL,hl); - WREG(IX,ix); - WREG(IY,iy); - WREG(SP,sp); + return; + + BREG(A, af.byte.high); + WREG(BC, bc); + WREG(DE, de); + WREG(HL, hl); + WREG(IX, ix); + WREG(IY, iy); + WREG(SP, sp); /* WREG(PC,pc); */ - BREG(F,af.byte.low); - WREG(AFx,af_prime); - WREG(BCx,bc_prime); - WREG(DEx,de_prime); - WREG(HLx,hl_prime); + BREG(F, af.byte.low); + WREG(AFx, af_prime); + WREG(BCx, bc_prime); + WREG(DEx, de_prime); + WREG(HLx, hl_prime); } @@ -21,8 +21,7 @@ #include <SDL.h> -struct twobyte -{ +struct twobyte { #if WORDS_LITTLEENDIAN uint8_t low, high; #else @@ -31,23 +30,21 @@ struct twobyte }; /* for implementing registers which can be seen as bytes or words: */ -typedef union -{ +typedef union { struct twobyte byte; uint16_t word; } wordregister; -typedef void (*eoifunc)(uint8_t, void *); +typedef void (*eoifunc) (uint8_t, void *); struct eoi { eoifunc func; void *arg; - int trigger; /* Vector to call EOI for, otherwise -1 */ + int trigger; /* Vector to call EOI for, otherwise -1 */ }; struct z80_irq; -struct z80_state_struct -{ +struct z80_state_struct { wordregister af; wordregister bc; wordregister de; @@ -62,17 +59,17 @@ struct z80_state_struct wordregister de_prime; wordregister hl_prime; - uint8_t i; /* interrupt-page address register */ - uint8_t rc; /* counting part of register R (bits 6-0) */ - uint8_t rf; /* fixed part of register R (bit 7) */ + uint8_t i; /* interrupt-page address register */ + uint8_t rc; /* counting part of register R (bits 6-0) */ + uint8_t rf; /* fixed part of register R (bit 7) */ uint8_t interrupt_mode; bool iff1, iff2, ei_shadow, signal_eoi; - bool nmi_in_progress; /* to prevent multiple simultaneous NMIs */ - volatile bool nminterrupt; /* used to signal a non maskable interrupt */ + bool nmi_in_progress; /* to prevent multiple simultaneous NMIs */ + volatile bool nminterrupt; /* used to signal a non maskable interrupt */ - uint64_t tc; /* T-state (clock cycle) counter */ + uint64_t tc; /* T-state (clock cycle) counter */ }; #define Z80_ADDRESS_LIMIT (1 << 16) @@ -169,11 +166,11 @@ extern struct z80_state_struct z80_state; /* Signal an NMI */ static inline void z80_nmi(void) { - z80_state.nminterrupt = true; + z80_state.nminterrupt = true; } extern void z80_reset(void); -extern int z80_run(bool,bool); +extern int z80_run(bool, bool); extern uint8_t mem_read(uint16_t); extern uint8_t mem_fetch(uint16_t); extern uint8_t mem_fetch_m1(uint16_t); @@ -190,7 +187,7 @@ extern int disassemble(int); extern int DAsm(uint16_t pc, char *T, int *target); extern bool z80_poll_external(void); -extern uint8_t ram[]; /* Array for plain RAM */ +extern uint8_t ram[]; /* Array for plain RAM */ extern void mem_init(unsigned int flags, const char *memfile); #define MEMFL_NOBASIC 1 diff --git a/z80asm/gnulib/getopt.c b/z80asm/gnulib/getopt.c index 1347f14..b56e722 100644 --- a/z80asm/gnulib/getopt.c +++ b/z80asm/gnulib/getopt.c @@ -26,11 +26,11 @@ /* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. Ditto for AIX 3.2 and <stdlib.h>. */ #ifndef _NO_PROTO -# define _NO_PROTO +#define _NO_PROTO #endif #ifdef HAVE_CONFIG_H -# include <config.h> +#include <config.h> #endif #include <stdio.h> @@ -46,44 +46,43 @@ #define GETOPT_INTERFACE_VERSION 2 #if !defined _LIBC && defined __GLIBC__ && __GLIBC__ >= 2 -# include <gnu-versions.h> -# if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION -# define ELIDE_CODE -# endif +#include <gnu-versions.h> +#if _GNU_GETOPT_INTERFACE_VERSION == GETOPT_INTERFACE_VERSION +#define ELIDE_CODE +#endif #endif #ifndef ELIDE_CODE - /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ /* Don't include stdlib.h for non-GNU C libraries because some of them contain conflicting prototypes for getopt. */ -# include <stdlib.h> -# include <unistd.h> -#endif /* GNU C library. */ +#include <stdlib.h> +#include <unistd.h> +#endif /* GNU C library. */ #include <string.h> #ifdef VMS -# include <unixlib.h> +#include <unixlib.h> #endif #ifdef _LIBC -# include <libintl.h> +#include <libintl.h> #else /* This is for other GNU distributions with internationalized messages. */ -# include "gettext.h" +#include "gettext.h" #endif #define _(msgid) gettext (msgid) #if defined _LIBC && defined USE_IN_LIBIO -# include <wchar.h> +#include <wchar.h> #endif #ifndef attribute_hidden -# define attribute_hidden +#define attribute_hidden #endif /* This version of `getopt' appears to the caller like standard Unix `getopt' @@ -180,9 +179,8 @@ int optopt = '?'; of the value of `ordering'. In the case of RETURN_IN_ORDER, only `--' can cause `getopt' to return -1 with `optind' != ARGC. */ -static enum -{ - REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +static enum { + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER } ordering; /* Value of POSIXLY_CORRECT environment variable. */ @@ -207,28 +205,28 @@ extern char **__libc_argv; /* Bash 2.0 gives us an environment variable containing flags indicating ARGV elements that should not be considered arguments. */ -# ifdef USE_NONOPTION_FLAGS +#ifdef USE_NONOPTION_FLAGS /* Defined in getopt_init.c */ extern char *__getopt_nonoption_flags; static int nonoption_flags_max_len; static int nonoption_flags_len; -# endif +#endif -# ifdef USE_NONOPTION_FLAGS -# define SWAP_FLAGS(ch1, ch2) \ +#ifdef USE_NONOPTION_FLAGS +#define SWAP_FLAGS(ch1, ch2) \ if (nonoption_flags_len > 0) \ { \ char __tmp = __getopt_nonoption_flags[ch1]; \ __getopt_nonoption_flags[ch1] = __getopt_nonoption_flags[ch2]; \ __getopt_nonoption_flags[ch2] = __tmp; \ } -# else -# define SWAP_FLAGS(ch1, ch2) -# endif -#else /* !_LIBC */ -# define SWAP_FLAGS(ch1, ch2) -#endif /* _LIBC */ +#else +#define SWAP_FLAGS(ch1, ch2) +#endif +#else /* !_LIBC */ +#define SWAP_FLAGS(ch1, ch2) +#endif /* _LIBC */ /* Exchange two adjacent subsequences of ARGV. One subsequence is elements [first_nonopt,last_nonopt) @@ -239,148 +237,130 @@ static int nonoption_flags_len; `first_nonopt' and `last_nonopt' are relocated so that they describe the new indices of the non-options in ARGV after they are moved. */ -static void -exchange (char **argv) +static void exchange(char **argv) { - int bottom = first_nonopt; - int middle = last_nonopt; - int top = optind; - char *tem; + int bottom = first_nonopt; + int middle = last_nonopt; + int top = optind; + char *tem; - /* Exchange the shorter segment with the far end of the longer segment. - That puts the shorter segment into the right place. - It leaves the longer segment in the right place overall, - but it consists of two parts that need to be swapped next. */ + /* Exchange the shorter segment with the far end of the longer segment. + That puts the shorter segment into the right place. + It leaves the longer segment in the right place overall, + but it consists of two parts that need to be swapped next. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS - /* First make sure the handling of the `__getopt_nonoption_flags' - string can work normally. Our top argument must be in the range - of the string. */ - if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) - { - /* We must extend the array. The user plays games with us and - presents new arguments. */ - char *new_str = malloc (top + 1); - if (new_str == NULL) - nonoption_flags_len = nonoption_flags_max_len = 0; - else - { - memset (__mempcpy (new_str, __getopt_nonoption_flags, - nonoption_flags_max_len), - '\0', top + 1 - nonoption_flags_max_len); - nonoption_flags_max_len = top + 1; - __getopt_nonoption_flags = new_str; - } + /* First make sure the handling of the `__getopt_nonoption_flags' + string can work normally. Our top argument must be in the range + of the string. */ + if (nonoption_flags_len > 0 && top >= nonoption_flags_max_len) { + /* We must extend the array. The user plays games with us and + presents new arguments. */ + char *new_str = malloc(top + 1); + if (new_str == NULL) + nonoption_flags_len = nonoption_flags_max_len = 0; + else { + memset(__mempcpy(new_str, __getopt_nonoption_flags, + nonoption_flags_max_len), + '\0', top + 1 - nonoption_flags_max_len); + nonoption_flags_max_len = top + 1; + __getopt_nonoption_flags = new_str; + } } #endif - while (top > middle && middle > bottom) - { - if (top - middle > middle - bottom) - { - /* Bottom segment is the short one. */ - int len = middle - bottom; - register int i; - - /* Swap it with the top part of the top segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[top - (middle - bottom) + i]; - argv[top - (middle - bottom) + i] = tem; - SWAP_FLAGS (bottom + i, top - (middle - bottom) + i); - } - /* Exclude the moved bottom segment from further swapping. */ - top -= len; - } - else - { - /* Top segment is the short one. */ - int len = top - middle; - register int i; - - /* Swap it with the bottom part of the bottom segment. */ - for (i = 0; i < len; i++) - { - tem = argv[bottom + i]; - argv[bottom + i] = argv[middle + i]; - argv[middle + i] = tem; - SWAP_FLAGS (bottom + i, middle + i); - } - /* Exclude the moved top segment from further swapping. */ - bottom += len; - } + while (top > middle && middle > bottom) { + if (top - middle > middle - bottom) { + /* Bottom segment is the short one. */ + int len = middle - bottom; + register int i; + + /* Swap it with the top part of the top segment. */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[top - (middle - bottom) + i]; + argv[top - (middle - bottom) + i] = tem; + SWAP_FLAGS(bottom + i, top - (middle - bottom) + i); + } + /* Exclude the moved bottom segment from further swapping. */ + top -= len; + } else { + /* Top segment is the short one. */ + int len = top - middle; + register int i; + + /* Swap it with the bottom part of the bottom segment. */ + for (i = 0; i < len; i++) { + tem = argv[bottom + i]; + argv[bottom + i] = argv[middle + i]; + argv[middle + i] = tem; + SWAP_FLAGS(bottom + i, middle + i); + } + /* Exclude the moved top segment from further swapping. */ + bottom += len; + } } - /* Update records for the slots the non-options now occupy. */ + /* Update records for the slots the non-options now occupy. */ - first_nonopt += (optind - last_nonopt); - last_nonopt = optind; + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; } /* Initialize the internal data when the first call is made. */ -static const char * -_getopt_initialize (int argc, char *const *argv, const char *optstring) +static const char *_getopt_initialize(int argc, char *const *argv, + const char *optstring) { - /* Start processing options with ARGV-element 1 (since ARGV-element 0 - is the program name); the sequence of previously skipped - non-option ARGV-elements is empty. */ + /* Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ - first_nonopt = last_nonopt = optind; + first_nonopt = last_nonopt = optind; - nextchar = NULL; + nextchar = NULL; - posixly_correct = getenv ("POSIXLY_CORRECT"); + posixly_correct = getenv("POSIXLY_CORRECT"); - /* Determine how to handle the ordering of options and nonoptions. */ + /* Determine how to handle the ordering of options and nonoptions. */ - if (optstring[0] == '-') - { - ordering = RETURN_IN_ORDER; - ++optstring; - } - else if (optstring[0] == '+') - { - ordering = REQUIRE_ORDER; - ++optstring; - } - else if (posixly_correct != NULL) - ordering = REQUIRE_ORDER; - else - ordering = PERMUTE; + if (optstring[0] == '-') { + ordering = RETURN_IN_ORDER; + ++optstring; + } else if (optstring[0] == '+') { + ordering = REQUIRE_ORDER; + ++optstring; + } else if (posixly_correct != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; #if defined _LIBC && defined USE_NONOPTION_FLAGS - if (posixly_correct == NULL - && argc == __libc_argc && argv == __libc_argv) - { - if (nonoption_flags_max_len == 0) - { - if (__getopt_nonoption_flags == NULL - || __getopt_nonoption_flags[0] == '\0') - nonoption_flags_max_len = -1; - else - { - const char *orig_str = __getopt_nonoption_flags; - int len = nonoption_flags_max_len = strlen (orig_str); - if (nonoption_flags_max_len < argc) - nonoption_flags_max_len = argc; - __getopt_nonoption_flags = - (char *) malloc (nonoption_flags_max_len); - if (__getopt_nonoption_flags == NULL) - nonoption_flags_max_len = -1; - else - memset (__mempcpy (__getopt_nonoption_flags, orig_str, len), - '\0', nonoption_flags_max_len - len); - } - } - nonoption_flags_len = nonoption_flags_max_len; - } - else - nonoption_flags_len = 0; + if (posixly_correct == NULL && argc == __libc_argc && argv == __libc_argv) { + if (nonoption_flags_max_len == 0) { + if (__getopt_nonoption_flags == NULL + || __getopt_nonoption_flags[0] == '\0') + nonoption_flags_max_len = -1; + else { + const char *orig_str = __getopt_nonoption_flags; + int len = nonoption_flags_max_len = strlen(orig_str); + if (nonoption_flags_max_len < argc) + nonoption_flags_max_len = argc; + __getopt_nonoption_flags = + (char *)malloc(nonoption_flags_max_len); + if (__getopt_nonoption_flags == NULL) + nonoption_flags_max_len = -1; + else + memset(__mempcpy(__getopt_nonoption_flags, orig_str, len), + '\0', nonoption_flags_max_len - len); + } + } + nonoption_flags_len = nonoption_flags_max_len; + } else + nonoption_flags_len = 0; #endif - return optstring; + return optstring; } /* Scan elements of ARGV (whose length is ARGC) for option characters @@ -440,760 +420,667 @@ _getopt_initialize (int argc, char *const *argv, const char *optstring) long-named options. */ int -_getopt_internal (int argc, char *const *argv, - const char *optstring, const struct option *longopts, - int *longind, int long_only) +_getopt_internal(int argc, char *const *argv, + const char *optstring, const struct option *longopts, + int *longind, int long_only) { - int print_errors = opterr; - if (optstring[0] == ':') - print_errors = 0; + int print_errors = opterr; + if (optstring[0] == ':') + print_errors = 0; - if (argc < 1) - return -1; + if (argc < 1) + return -1; - optarg = NULL; + optarg = NULL; - if (optind == 0 || !__getopt_initialized) - { - if (optind == 0) - optind = 1; /* Don't scan ARGV[0], the program name. */ - optstring = _getopt_initialize (argc, argv, optstring); - __getopt_initialized = 1; + if (optind == 0 || !__getopt_initialized) { + if (optind == 0) + optind = 1; /* Don't scan ARGV[0], the program name. */ + optstring = _getopt_initialize(argc, argv, optstring); + __getopt_initialized = 1; } - /* Test whether ARGV[optind] points to a non-option argument. - Either it does not have option syntax, or there is an environment flag - from the shell indicating it is not an option. The later information - is only used when the used in the GNU libc. */ + /* Test whether ARGV[optind] points to a non-option argument. + Either it does not have option syntax, or there is an environment flag + from the shell indicating it is not an option. The later information + is only used when the used in the GNU libc. */ #if defined _LIBC && defined USE_NONOPTION_FLAGS -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0' \ || (optind < nonoption_flags_len \ && __getopt_nonoption_flags[optind] == '1')) #else -# define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') +#define NONOPTION_P (argv[optind][0] != '-' || argv[optind][1] == '\0') #endif - if (nextchar == NULL || *nextchar == '\0') - { - /* Advance to the next ARGV-element. */ - - /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been - moved back by the user (who may also have changed the arguments). */ - if (last_nonopt > optind) - last_nonopt = optind; - if (first_nonopt > optind) - first_nonopt = optind; - - if (ordering == PERMUTE) - { - /* If we have just processed some options following some non-options, - exchange them so that the options come first. */ - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (last_nonopt != optind) - first_nonopt = optind; - - /* Skip any additional non-options - and extend the range of non-options previously skipped. */ - - while (optind < argc && NONOPTION_P) - optind++; - last_nonopt = optind; - } - - /* The special ARGV-element `--' means premature end of options. - Skip it like a null option, - then exchange with previous non-options as if it were an option, - then skip everything else like a non-option. */ - - if (optind != argc && !strcmp (argv[optind], "--")) - { - optind++; - - if (first_nonopt != last_nonopt && last_nonopt != optind) - exchange ((char **) argv); - else if (first_nonopt == last_nonopt) - first_nonopt = optind; - last_nonopt = argc; - - optind = argc; - } - - /* If we have done all the ARGV-elements, stop the scan - and back over any non-options that we skipped and permuted. */ - - if (optind == argc) - { - /* Set the next-arg-index to point at the non-options - that we previously skipped, so the caller will digest them. */ - if (first_nonopt != last_nonopt) - optind = first_nonopt; - return -1; - } - - /* If we have come to a non-option and did not permute it, - either stop the scan or describe it to the caller and pass it by. */ - - if (NONOPTION_P) - { - if (ordering == REQUIRE_ORDER) - return -1; - optarg = argv[optind++]; - return 1; - } - - /* We have found another option-ARGV-element. - Skip the initial punctuation. */ - - nextchar = (argv[optind] + 1 - + (longopts != NULL && argv[optind][1] == '-')); + if (nextchar == NULL || *nextchar == '\0') { + /* Advance to the next ARGV-element. */ + + /* Give FIRST_NONOPT & LAST_NONOPT rational values if OPTIND has been + moved back by the user (who may also have changed the arguments). */ + if (last_nonopt > optind) + last_nonopt = optind; + if (first_nonopt > optind) + first_nonopt = optind; + + if (ordering == PERMUTE) { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **)argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc && NONOPTION_P) + optind++; + last_nonopt = optind; + } + + /* The special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp(argv[optind], "--")) { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange((char **)argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return -1; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if (NONOPTION_P) { + if (ordering == REQUIRE_ORDER) + return -1; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Skip the initial punctuation. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); } - /* Decode the current option-ARGV-element. */ - - /* Check whether the ARGV-element is a long option. - - If long_only and the ARGV-element has the form "-f", where f is - a valid short option, don't consider it an abbreviated form of - a long option that starts with f. Otherwise there would be no - way to give the -f short option. - - On the other hand, if there's a long option "fubar" and - the ARGV-element is "-fu", do consider that an abbreviation of - the long option, just like "--fu", and not "-f" with arg "u". - - This distinction seems to be the most useful approach. */ - - if (longopts != NULL - && (argv[optind][1] == '-' - || (long_only - && (argv[optind][2] || !strchr (optstring, argv[optind][1]))))) - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = -1; - int option_index; - - for (nameend = nextchar; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) - == (unsigned int) strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else if (long_only - || pfound->has_arg != p->has_arg - || pfound->flag != p->flag - || pfound->val != p->val) - /* Second or later nonexact match found. */ - ambig = 1; - } - - if (ambig && !exact) - { - if (print_errors) - { + /* Decode the current option-ARGV-element. */ + + /* Check whether the ARGV-element is a long option. + + If long_only and the ARGV-element has the form "-f", where f is + a valid short option, don't consider it an abbreviated form of + a long option that starts with f. Otherwise there would be no + way to give the -f short option. + + On the other hand, if there's a long option "fubar" and + the ARGV-element is "-fu", do consider that an abbreviation of + the long option, just like "--fu", and not "-f" with arg "u". + + This distinction seems to be the most useful approach. */ + + if (longopts != NULL + && (argv[optind][1] == '-' + || (long_only + && (argv[optind][2] || !strchr(optstring, argv[optind][1]))))) { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = -1; + int option_index; + + for (nameend = nextchar; *nameend && *nameend != '='; nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) { + if ((unsigned int)(nameend - nextchar) + == (unsigned int)strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if (pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else if (long_only + || pfound->has_arg != p->has_arg + || pfound->flag != p->flag || pfound->val != p->val) + /* Second or later nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; + char *buf; - if (__asprintf (&buf, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]) >= 0) - { + if (__asprintf(&buf, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]) >= 0) { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); - free (buf); - } + free(buf); + } #else - fprintf (stderr, _("%s: option `%s' is ambiguous\n"), - argv[0], argv[optind]); + fprintf(stderr, _("%s: option `%s' is ambiguous\n"), + argv[0], argv[optind]); #endif - } - nextchar += strlen (nextchar); - optind++; - optopt = 0; - return '?'; - } - - if (pfound != NULL) - { - option_index = indfound; - optind++; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (print_errors) - { + } + nextchar += strlen(nextchar); + optind++; + optopt = 0; + return '?'; + } + + if (pfound != NULL) { + option_index = indfound; + optind++; + if (*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; + char *buf; + int n; #endif - if (argv[optind - 1][1] == '-') - { - /* --option */ + if (argv[optind - 1][1] == '-') { + /* --option */ #if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); + n = __asprintf(&buf, _("\ +%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #else - fprintf (stderr, _("\ -%s: option `--%s' doesn't allow an argument\n"), - argv[0], pfound->name); + fprintf(stderr, _("\ +%s: option `--%s' doesn't allow an argument\n"), argv[0], pfound->name); #endif - } - else - { - /* +option or -option */ + } else { + /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], - pfound->name); + n = __asprintf(&buf, _("\ +%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); #else - fprintf (stderr, _("\ -%s: option `%c%s' doesn't allow an argument\n"), - argv[0], argv[optind - 1][0], pfound->name); + fprintf(stderr, _("\ +%s: option `%c%s' doesn't allow an argument\n"), argv[0], argv[optind - 1][0], pfound->name); #endif - } + } #if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + if (n >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #endif - } - - nextchar += strlen (nextchar); - - optopt = pfound->val; - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (print_errors) - { + } + + nextchar += strlen(nextchar); + + optopt = pfound->val; + return '?'; + } + } else if (pfound->has_arg == 1) { + if (optind < argc) + optarg = argv[optind++]; + else { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]) >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + char *buf; + + if (__asprintf(&buf, _("\ +%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]) >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); #endif - } - nextchar += strlen (nextchar); - optopt = pfound->val; - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - - /* Can't find it as a long option. If this is not getopt_long_only, - or the option starts with '--' or is not a valid short - option, then it's an error. - Otherwise interpret it as a short option. */ - if (!long_only || argv[optind][1] == '-' - || strchr (optstring, *nextchar) == NULL) - { - if (print_errors) - { + } + nextchar += strlen(nextchar); + optopt = pfound->val; + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' + || strchr(optstring, *nextchar) == NULL) { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; + char *buf; + int n; #endif - if (argv[optind][1] == '-') - { - /* --option */ + if (argv[optind][1] == '-') { + /* --option */ #if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); + n = __asprintf(&buf, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); #else - fprintf (stderr, _("%s: unrecognized option `--%s'\n"), - argv[0], nextchar); + fprintf(stderr, _("%s: unrecognized option `--%s'\n"), + argv[0], nextchar); #endif - } - else - { - /* +option or -option */ + } else { + /* +option or -option */ #if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); + n = __asprintf(&buf, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); #else - fprintf (stderr, _("%s: unrecognized option `%c%s'\n"), - argv[0], argv[optind][0], nextchar); + fprintf(stderr, _("%s: unrecognized option `%c%s'\n"), + argv[0], argv[optind][0], nextchar); #endif - } + } #if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + if (n >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #endif - } - nextchar = (char *) ""; - optind++; - optopt = 0; - return '?'; - } + } + nextchar = (char *)""; + optind++; + optopt = 0; + return '?'; + } } - /* Look at and handle the next short option-character. */ + /* Look at and handle the next short option-character. */ - { - char c = *nextchar++; - char *temp = strchr (optstring, c); + { + char c = *nextchar++; + char *temp = strchr(optstring, c); - /* Increment `optind' when we start to process its last character. */ - if (*nextchar == '\0') - ++optind; + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; - if (temp == NULL || c == ':') - { - if (print_errors) - { + if (temp == NULL || c == ':') { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - int n; + char *buf; + int n; #endif - if (posixly_correct) - { - /* 1003.2 specifies the format of this message. */ + if (posixly_correct) { + /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: illegal option -- %c\n"), - argv[0], c); + n = __asprintf(&buf, _("%s: illegal option -- %c\n"), + argv[0], c); #else - fprintf (stderr, _("%s: illegal option -- %c\n"), argv[0], c); + fprintf(stderr, _("%s: illegal option -- %c\n"), argv[0], + c); #endif - } - else - { + } else { #if defined _LIBC && defined USE_IN_LIBIO - n = __asprintf (&buf, _("%s: invalid option -- %c\n"), - argv[0], c); + n = __asprintf(&buf, _("%s: invalid option -- %c\n"), + argv[0], c); #else - fprintf (stderr, _("%s: invalid option -- %c\n"), argv[0], c); + fprintf(stderr, _("%s: invalid option -- %c\n"), argv[0], + c); #endif - } + } #if defined _LIBC && defined USE_IN_LIBIO - if (n >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + if (n >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #endif - } - optopt = c; - return '?'; - } - /* Convenience. Treat POSIX -W foo same as long option --foo */ - if (temp[0] == 'W' && temp[1] == ';') - { - char *nameend; - const struct option *p; - const struct option *pfound = NULL; - int exact = 0; - int ambig = 0; - int indfound = 0; - int option_index; - - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ + } + optopt = c; + return '?'; + } + /* Convenience. Treat POSIX -W foo same as long option --foo */ + if (temp[0] == 'W' && temp[1] == ';') { + char *nameend; + const struct option *p; + const struct option *pfound = NULL; + int exact = 0; + int ambig = 0; + int indfound = 0; + int option_index; + + /* This is an option that requires an argument. */ + if (*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } else if (optind == argc) { + if (print_errors) { + /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, - _("%s: option requires an argument -- %c\n"), - argv[0], c) >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + char *buf; + + if (__asprintf(&buf, + _("%s: option requires an argument -- %c\n"), + argv[0], c) >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #else - fprintf (stderr, _("%s: option requires an argument -- %c\n"), - argv[0], c); + fprintf(stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); #endif - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - return c; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - - /* optarg is now the argument, see if it's in the - table of longopts. */ - - for (nextchar = nameend = optarg; *nameend && *nameend != '='; nameend++) - /* Do nothing. */ ; - - /* Test all long options for either exact match - or abbreviated matches. */ - for (p = longopts, option_index = 0; p->name; p++, option_index++) - if (!strncmp (p->name, nextchar, nameend - nextchar)) - { - if ((unsigned int) (nameend - nextchar) == strlen (p->name)) - { - /* Exact match found. */ - pfound = p; - indfound = option_index; - exact = 1; - break; - } - else if (pfound == NULL) - { - /* First nonexact match found. */ - pfound = p; - indfound = option_index; - } - else - /* Second or later nonexact match found. */ - ambig = 1; - } - if (ambig && !exact) - { - if (print_errors) - { + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + return c; + } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + + /* optarg is now the argument, see if it's in the + table of longopts. */ + + for (nextchar = nameend = optarg; *nameend && *nameend != '='; + nameend++) + /* Do nothing. */ ; + + /* Test all long options for either exact match + or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; p++, option_index++) + if (!strncmp(p->name, nextchar, nameend - nextchar)) { + if ((unsigned int)(nameend - nextchar) == strlen(p->name)) { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } else if (pfound == NULL) { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } else + /* Second or later nonexact match found. */ + ambig = 1; + } + if (ambig && !exact) { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]) >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + char *buf; + + if (__asprintf(&buf, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]) >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #else - fprintf (stderr, _("%s: option `-W %s' is ambiguous\n"), - argv[0], argv[optind]); + fprintf(stderr, _("%s: option `-W %s' is ambiguous\n"), + argv[0], argv[optind]); #endif - } - nextchar += strlen (nextchar); - optind++; - return '?'; - } - if (pfound != NULL) - { - option_index = indfound; - if (*nameend) - { - /* Don't test has_arg with >, because some C compilers don't - allow it to be used on enums. */ - if (pfound->has_arg) - optarg = nameend + 1; - else - { - if (print_errors) - { + } + nextchar += strlen(nextchar); + optind++; + return '?'; + } + if (pfound != NULL) { + option_index = indfound; + if (*nameend) { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = nameend + 1; + else { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name) >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + char *buf; + + if (__asprintf(&buf, _("\ +%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name) >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #else - fprintf (stderr, _("\ -%s: option `-W %s' doesn't allow an argument\n"), - argv[0], pfound->name); + fprintf(stderr, _("\ +%s: option `-W %s' doesn't allow an argument\n"), argv[0], pfound->name); #endif - } - - nextchar += strlen (nextchar); - return '?'; - } - } - else if (pfound->has_arg == 1) - { - if (optind < argc) - optarg = argv[optind++]; - else - { - if (print_errors) - { + } + + nextchar += strlen(nextchar); + return '?'; + } + } else if (pfound->has_arg == 1) { + if (optind < argc) + optarg = argv[optind++]; + else { + if (print_errors) { #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]) >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + char *buf; + + if (__asprintf(&buf, _("\ +%s: option `%s' requires an argument\n"), argv[0], argv[optind - 1]) >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #else - fprintf (stderr, - _("%s: option `%s' requires an argument\n"), - argv[0], argv[optind - 1]); + fprintf(stderr, + _("%s: option `%s' requires an argument\n"), + argv[0], argv[optind - 1]); #endif - } - nextchar += strlen (nextchar); - return optstring[0] == ':' ? ':' : '?'; - } - } - nextchar += strlen (nextchar); - if (longind != NULL) - *longind = option_index; - if (pfound->flag) - { - *(pfound->flag) = pfound->val; - return 0; - } - return pfound->val; - } - nextchar = NULL; - return 'W'; /* Let the application handle it. */ - } - if (temp[1] == ':') - { - if (temp[2] == ':') - { - /* This is an option that accepts an argument optionally. */ - if (*nextchar != '\0') - { - optarg = nextchar; - optind++; - } - else - optarg = NULL; - nextchar = NULL; - } - else - { - /* This is an option that requires an argument. */ - if (*nextchar != '\0') - { - optarg = nextchar; - /* If we end this ARGV-element by taking the rest as an arg, - we must advance to the next element now. */ - optind++; - } - else if (optind == argc) - { - if (print_errors) - { - /* 1003.2 specifies the format of this message. */ + } + nextchar += strlen(nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen(nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + nextchar = NULL; + return 'W'; /* Let the application handle it. */ + } + if (temp[1] == ':') { + if (temp[2] == ':') { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') { + optarg = nextchar; + optind++; + } else + optarg = NULL; + nextchar = NULL; + } else { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } else if (optind == argc) { + if (print_errors) { + /* 1003.2 specifies the format of this message. */ #if defined _LIBC && defined USE_IN_LIBIO - char *buf; - - if (__asprintf (&buf, _("\ -%s: option requires an argument -- %c\n"), - argv[0], c) >= 0) - { - if (_IO_fwide (stderr, 0) > 0) - __fwprintf (stderr, L"%s", buf); - else - fputs (buf, stderr); - - free (buf); - } + char *buf; + + if (__asprintf(&buf, _("\ +%s: option requires an argument -- %c\n"), argv[0], c) >= 0) { + if (_IO_fwide(stderr, 0) > 0) + __fwprintf(stderr, L"%s", buf); + else + fputs(buf, stderr); + + free(buf); + } #else - fprintf (stderr, - _("%s: option requires an argument -- %c\n"), - argv[0], c); + fprintf(stderr, + _("%s: option requires an argument -- %c\n"), + argv[0], c); #endif - } - optopt = c; - if (optstring[0] == ':') - c = ':'; - else - c = '?'; - } - else - /* We already incremented `optind' once; - increment it again when taking next ARGV-elt as argument. */ - optarg = argv[optind++]; - nextchar = NULL; - } - } - return c; - } + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } } -int -getopt (int argc, char *const *argv, const char *optstring) +int getopt(int argc, char *const *argv, const char *optstring) { - return _getopt_internal (argc, argv, optstring, - (const struct option *) 0, - (int *) 0, - 0); + return _getopt_internal(argc, argv, optstring, + (const struct option *)0, (int *)0, 0); } -#endif /* Not ELIDE_CODE. */ +#endif /* Not ELIDE_CODE. */ #ifdef TEST /* Compile with -DTEST to make an executable for use in testing the above definition of `getopt'. */ -int -main (int argc, char **argv) +int main(int argc, char **argv) { - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - - c = getopt (argc, argv, "abc:d:0123456789"); - if (c == -1) - break; - - switch (c) - { - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } + int c; + int digit_optind = 0; + + while (1) { + int this_option_optind = optind ? optind : 1; + + c = getopt(argc, argv, "abc:d:0123456789"); + if (c == -1) + break; + + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } } - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); } - exit (0); + exit(0); } #endif /* TEST */ diff --git a/z80asm/gnulib/getopt.h b/z80asm/gnulib/getopt.h index d75535b..bd0a4eb 100644 --- a/z80asm/gnulib/getopt.h +++ b/z80asm/gnulib/getopt.h @@ -22,7 +22,7 @@ #ifndef _GETOPT_H #ifndef __need_getopt -# define _GETOPT_H 1 +#define _GETOPT_H 1 #endif /* If __GNU_LIBRARY__ is not already defined, either we are being used @@ -33,7 +33,7 @@ if it's from glibc. (Why ctype.h? It's guaranteed to exist and it doesn't flood the namespace with stuff the way some other headers do.) */ #if !defined __GNU_LIBRARY__ -# include <ctype.h> +#include <ctype.h> #endif #ifdef __cplusplus @@ -46,7 +46,7 @@ extern "C" { Also, when `ordering' is RETURN_IN_ORDER, each non-option ARGV-element is returned here. */ -extern char *optarg; + extern char *optarg; /* Index in ARGV of the next element to be scanned. This is used for communication to and from the caller @@ -60,16 +60,16 @@ extern char *optarg; Otherwise, `optind' communicates from one call to the next how much of ARGV has been scanned so far. */ -extern int optind; + extern int optind; /* Callers store zero here to inhibit the error message `getopt' prints for unrecognized options. */ -extern int opterr; + extern int opterr; /* Set to an option character which was unrecognized. */ -extern int optopt; + extern int optopt; #ifndef __need_getopt /* Describe the long-named options requested by the application. @@ -93,23 +93,21 @@ extern int optopt; one). For long options that have a zero `flag' field, `getopt' returns the contents of the `val' field. */ -struct option -{ - const char *name; - /* has_arg can't be an enum because some compilers complain about - type mismatches in all the code that assumes it is an int. */ - int has_arg; - int *flag; - int val; -}; + struct option { + const char *name; + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; + }; /* Names for the values of the `has_arg' field of `struct option'. */ -# define no_argument 0 -# define required_argument 1 -# define optional_argument 2 -#endif /* need getopt */ - +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 +#endif /* need getopt */ /* Get definitions and prototypes for functions to process the arguments in ARGV (ARGC of them, minus the program name) for @@ -138,28 +136,28 @@ struct option /* Many other libraries have conflicting prototypes for getopt, with differences in the consts, in stdlib.h. To avoid compilation errors, only prototype getopt for the GNU C library. */ -extern int getopt (int ___argc, char *const *___argv, const char *__shortopts); + extern int getopt(int ___argc, char *const *___argv, + const char *__shortopts); #ifndef __need_getopt -extern int getopt_long (int ___argc, char *const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind); -extern int getopt_long_only (int ___argc, char *const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind); + extern int getopt_long(int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind); + extern int getopt_long_only(int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, + int *__longind); /* Internal only. Users should not call this directly. */ -extern int _getopt_internal (int ___argc, char *const *___argv, - const char *__shortopts, - const struct option *__longopts, int *__longind, - int __long_only); + extern int _getopt_internal(int ___argc, char *const *___argv, + const char *__shortopts, + const struct option *__longopts, int *__longind, + int __long_only); #endif #ifdef __cplusplus } #endif - /* Make sure we later can get all the definitions and declarations. */ #undef __need_getopt - -#endif /* getopt.h */ +#endif /* getopt.h */ diff --git a/z80asm/gnulib/getopt1.c b/z80asm/gnulib/getopt1.c index 3288c72..34d76fd 100644 --- a/z80asm/gnulib/getopt1.c +++ b/z80asm/gnulib/getopt1.c @@ -24,9 +24,9 @@ #endif #ifdef _LIBC -# include <getopt.h> +#include <getopt.h> #else -# include "getopt.h" +#include "getopt.h" #endif #include <stdio.h> @@ -49,7 +49,6 @@ #ifndef ELIDE_CODE - /* This needs to come after some library #include to get __GNU_LIBRARY__ defined. */ #ifdef __GNU_LIBRARY__ @@ -61,13 +60,12 @@ #endif int -getopt_long (int argc, - char *const *argv, - const char *options, - const struct option *long_options, - int *opt_index) +getopt_long(int argc, + char *const *argv, + const char *options, + const struct option *long_options, int *opt_index) { - return _getopt_internal (argc, argv, options, long_options, opt_index, 0); + return _getopt_internal(argc, argv, options, long_options, opt_index, 0); } /* Like getopt_long, but '-' as well as '--' can indicate a long option. @@ -76,110 +74,100 @@ getopt_long (int argc, instead. */ int -getopt_long_only (int argc, - char *const *argv, - const char *options, - const struct option *long_options, - int *opt_index) +getopt_long_only(int argc, + char *const *argv, + const char *options, + const struct option *long_options, int *opt_index) { - return _getopt_internal (argc, argv, options, long_options, opt_index, 1); + return _getopt_internal(argc, argv, options, long_options, opt_index, 1); } -# ifdef _LIBC -libc_hidden_def (getopt_long) -libc_hidden_def (getopt_long_only) -# endif - -#endif /* Not ELIDE_CODE. */ - -#ifdef TEST - +#ifdef _LIBC +libc_hidden_def(getopt_long) + libc_hidden_def(getopt_long_only) +#endif +#endif /* Not ELIDE_CODE. */ +#ifdef TEST #include <stdio.h> - -int -main (int argc, char **argv) +int main(int argc, char **argv) { - int c; - int digit_optind = 0; - - while (1) - { - int this_option_optind = optind ? optind : 1; - int option_index = 0; - static struct option long_options[] = - { - {"add", 1, 0, 0}, - {"append", 0, 0, 0}, - {"delete", 1, 0, 0}, - {"verbose", 0, 0, 0}, - {"create", 0, 0, 0}, - {"file", 1, 0, 0}, - {0, 0, 0, 0} - }; - - c = getopt_long (argc, argv, "abc:d:0123456789", - long_options, &option_index); - if (c == -1) - break; - - switch (c) - { - case 0: - printf ("option %s", long_options[option_index].name); - if (optarg) - printf (" with arg %s", optarg); - printf ("\n"); - break; - - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - if (digit_optind != 0 && digit_optind != this_option_optind) - printf ("digits occur in two different argv-elements.\n"); - digit_optind = this_option_optind; - printf ("option %c\n", c); - break; - - case 'a': - printf ("option a\n"); - break; - - case 'b': - printf ("option b\n"); - break; - - case 'c': - printf ("option c with value `%s'\n", optarg); - break; - - case 'd': - printf ("option d with value `%s'\n", optarg); - break; - - case '?': - break; - - default: - printf ("?? getopt returned character code 0%o ??\n", c); - } + int c; + int digit_optind = 0; + + while (1) { + int this_option_optind = optind ? optind : 1; + int option_index = 0; + static struct option long_options[] = { + {"add", 1, 0, 0}, + {"append", 0, 0, 0}, + {"delete", 1, 0, 0}, + {"verbose", 0, 0, 0}, + {"create", 0, 0, 0}, + {"file", 1, 0, 0}, + {0, 0, 0, 0} + }; + + c = getopt_long(argc, argv, "abc:d:0123456789", + long_options, &option_index); + if (c == -1) + break; + + switch (c) { + case 0: + printf("option %s", long_options[option_index].name); + if (optarg) + printf(" with arg %s", optarg); + printf("\n"); + break; + + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf("option %c\n", c); + break; + + case 'a': + printf("option a\n"); + break; + + case 'b': + printf("option b\n"); + break; + + case 'c': + printf("option c with value `%s'\n", optarg); + break; + + case 'd': + printf("option d with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf("?? getopt returned character code 0%o ??\n", c); + } } - if (optind < argc) - { - printf ("non-option ARGV-elements: "); - while (optind < argc) - printf ("%s ", argv[optind++]); - printf ("\n"); + if (optind < argc) { + printf("non-option ARGV-elements: "); + while (optind < argc) + printf("%s ", argv[optind++]); + printf("\n"); } - exit (0); + exit(0); } #endif /* TEST */ diff --git a/z80asm/gnulib/gettext.h b/z80asm/gnulib/gettext.h index 835732e..a21bbd5 100644 --- a/z80asm/gnulib/gettext.h +++ b/z80asm/gnulib/gettext.h @@ -22,7 +22,7 @@ #if ENABLE_NLS /* Get declarations of GNU message catalog functions. */ -# include <libintl.h> +#include <libintl.h> #else @@ -33,7 +33,7 @@ and also including <libintl.h> would fail on SunOS 4, whereas <locale.h> is OK. */ #if defined(__sun) -# include <locale.h> +#include <locale.h> #endif /* Disabled NLS. @@ -41,18 +41,18 @@ for invalid uses of the value returned from these functions. On pre-ANSI systems without 'const', the config.h file is supposed to contain "#define const". */ -# define gettext(Msgid) ((const char *) (Msgid)) -# define dgettext(Domainname, Msgid) ((const char *) (Msgid)) -# define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) -# define ngettext(Msgid1, Msgid2, N) \ +#define gettext(Msgid) ((const char *) (Msgid)) +#define dgettext(Domainname, Msgid) ((const char *) (Msgid)) +#define dcgettext(Domainname, Msgid, Category) ((const char *) (Msgid)) +#define ngettext(Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# define dngettext(Domainname, Msgid1, Msgid2, N) \ +#define dngettext(Domainname, Msgid1, Msgid2, N) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ +#define dcngettext(Domainname, Msgid1, Msgid2, N, Category) \ ((N) == 1 ? (const char *) (Msgid1) : (const char *) (Msgid2)) -# define textdomain(Domainname) ((const char *) (Domainname)) -# define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) -# define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) +#define textdomain(Domainname) ((const char *) (Domainname)) +#define bindtextdomain(Domainname, Dirname) ((const char *) (Dirname)) +#define bind_textdomain_codeset(Domainname, Codeset) ((const char *) (Codeset)) #endif diff --git a/z80asm/z80asm.c b/z80asm/z80asm.c index a681aac..d896b09 100644 --- a/z80asm/z80asm.c +++ b/z80asm/z80asm.c @@ -30,147 +30,135 @@ /* defines which are not function-specific */ #ifndef BUFLEN -#define BUFLEN 300 /* size of readbuffer for file i/o */ +#define BUFLEN 300 /* size of readbuffer for file i/o */ #endif #ifndef MAX_INCLUDE -#define MAX_INCLUDE 200 /* stack size for include command and macros */ +#define MAX_INCLUDE 200 /* stack size for include command and macros */ #endif /* types */ /* mnemonics. THESE MUST BE IN THE SAME ORDER AS const char *mnemonic[]! */ -enum mnemonic -{ - CALL, CPDR, CPIR, DJNZ, HALT, INDR, INIR, LDDR, LDIR, OTDR, OTIR, OUTD, - OUTI, PUSH, RETI, RETN, RLCA, RRCA, DEFB, DEFW, DEFS, DEFM, - ADC, ADD, AND, BIT, CCF, CPD, CPI, CPL, DAA, DEC, EQU, EXX, INC, IND, INI, - LDD, LDI, NEG, NOP, OUT, POP, RES, RET, RLA, RLC, RLD, RRA, RRC, RRD, RST, - SBC, SCF, SET, SLA, SLL, SLI, SRA, SRL, SUB, XOR, ORG, - CP, DI, EI, EX, IM, IN, JP, JR, LD, OR, RL, RR, DB, DW, DS, DM, - INCLUDE, INCBIN, IF, ELSE, ENDIF, END, MACRO, ENDM, SEEK +enum mnemonic { + CALL, CPDR, CPIR, DJNZ, HALT, INDR, INIR, LDDR, LDIR, OTDR, OTIR, OUTD, + OUTI, PUSH, RETI, RETN, RLCA, RRCA, DEFB, DEFW, DEFS, DEFM, + ADC, ADD, AND, BIT, CCF, CPD, CPI, CPL, DAA, DEC, EQU, EXX, INC, IND, INI, + LDD, LDI, NEG, NOP, OUT, POP, RES, RET, RLA, RLC, RLD, RRA, RRC, RRD, RST, + SBC, SCF, SET, SLA, SLL, SLI, SRA, SRL, SUB, XOR, ORG, + CP, DI, EI, EX, IM, IN, JP, JR, LD, OR, RL, RR, DB, DW, DS, DM, + INCLUDE, INCBIN, IF, ELSE, ENDIF, END, MACRO, ENDM, SEEK }; /* types of reference */ -enum reftype -{ - TYPE_BSR, /* bit value (0-7) for bit, set and res */ - TYPE_DS, /* ds reference (byte count and value) */ - TYPE_RST, /* rst reference: val & 0x38 == val */ - TYPE_ABSW, /* absolute word (2 bytes) */ - TYPE_ABSB, /* absolute byte */ - TYPE_RELB, /* relative byte */ - TYPE_LABEL /* equ expression */ +enum reftype { + TYPE_BSR, /* bit value (0-7) for bit, set and res */ + TYPE_DS, /* ds reference (byte count and value) */ + TYPE_RST, /* rst reference: val & 0x38 == val */ + TYPE_ABSW, /* absolute word (2 bytes) */ + TYPE_ABSB, /* absolute byte */ + TYPE_RELB, /* relative byte */ + TYPE_LABEL /* equ expression */ }; /* filetypes that can appear on the input. object files are on the todo list */ -enum filetype -{ - FILETYPE_ASM +enum filetype { + FILETYPE_ASM }; /* labels (will be malloced) */ -struct label -{ - struct label *next, *prev; /* linked list */ - int value; /* value */ - int valid; /* if it is valid, or not yet computed */ - int busy; /* if it is currently being computed */ - struct reference *ref; /* mallocced memory to value for computation */ - char name[1]; /* space with name in it */ +struct label { + struct label *next, *prev; /* linked list */ + int value; /* value */ + int valid; /* if it is valid, or not yet computed */ + int busy; /* if it is currently being computed */ + struct reference *ref; /* mallocced memory to value for computation */ + char name[1]; /* space with name in it */ }; /* files that were given on the commandline */ -struct infile -{ - const char *name; - enum filetype type; +struct infile { + const char *name; + enum filetype type; }; /* filenames must be remembered for references */ -struct name -{ - struct name *next, *prev; - char name[1]; +struct name { + struct name *next, *prev; + char name[1]; }; /* the include path */ -struct includedir -{ - struct includedir *next; - char name[1]; +struct includedir { + struct includedir *next; + char name[1]; }; /* macro stuff */ -struct macro_arg -{ - struct macro_arg *next; - unsigned pos; - unsigned which; +struct macro_arg { + struct macro_arg *next; + unsigned pos; + unsigned which; }; -struct macro_line -{ - struct macro_line *next; - char *line; - struct macro_arg *args; +struct macro_line { + struct macro_line *next; + char *line; + struct macro_arg *args; }; -struct macro -{ - struct macro *next; - char *name; - unsigned numargs; - char **args; - struct macro_line *lines; +struct macro { + struct macro *next; + char *name; + unsigned numargs; + char **args; + struct macro_line *lines; }; /* elements on the context stack */ -struct stack -{ - const char *name; /* filename (for errors). may be malloced */ - struct includedir *dir; /* directory where it comes from, if any */ - FILE *file; /* the handle */ - int line; /* the current line number (for errors) */ - int shouldclose; /* if this file should be closed when done */ - struct label *labels; /* local labels for this stack level */ - /* if file is NULL, this is a macro entry */ - struct macro *macro; - struct macro_line *macro_line; - char **macro_args; /* arguments given to the macro */ +struct stack { + const char *name; /* filename (for errors). may be malloced */ + struct includedir *dir; /* directory where it comes from, if any */ + FILE *file; /* the handle */ + int line; /* the current line number (for errors) */ + int shouldclose; /* if this file should be closed when done */ + struct label *labels; /* local labels for this stack level */ + /* if file is NULL, this is a macro entry */ + struct macro *macro; + struct macro_line *macro_line; + char **macro_args; /* arguments given to the macro */ }; /* these structs will be malloced for each reference */ -struct reference -{ - struct reference *next, *prev; - enum reftype type; /* type of reference */ - long oseekpos; /* position in outfile for data */ - long lseekpos; /* position in listfile for data */ - char delimiter; /* delimiter for parser */ - int addr, line; /* address and line of reference */ - int comma; /* comma when reference was set */ - int count; /* only for ds: number of items */ - int infile; /* index in infile[], current infile */ - int done; /* if this reference has been computed */ - int computed_value; /* value (only valid if done = true) */ - int level; /* maximum stack level of labels to use */ - char input[1]; /* variable size buffer containing formula */ +struct reference { + struct reference *next, *prev; + enum reftype type; /* type of reference */ + long oseekpos; /* position in outfile for data */ + long lseekpos; /* position in listfile for data */ + char delimiter; /* delimiter for parser */ + int addr, line; /* address and line of reference */ + int comma; /* comma when reference was set */ + int count; /* only for ds: number of items */ + int infile; /* index in infile[], current infile */ + int done; /* if this reference has been computed */ + int computed_value; /* value (only valid if done = true) */ + int level; /* maximum stack level of labels to use */ + char input[1]; /* variable size buffer containing formula */ }; /* global variables */ /* mnemonics, used as argument to indx() in assemble */ const char *mnemonics[] = { - "call", "cpdr", "cpir", "djnz", "halt", "indr", "inir", "lddr", "ldir", - "otdr", "otir", "outd", "outi", "push", "reti", "retn", "rlca", "rrca", - "defb", "defw", "defs", "defm", - "adc", "add", "and", "bit", "ccf", "cpd", "cpi", "cpl", "daa", "dec", "equ", - "exx", "inc", "ind", "ini", "ldd", "ldi", "neg", "nop", "out", "pop", - "res", "ret", "rla", "rlc", "rld", "rra", "rrc", "rrd", "rst", "sbc", - "scf", "set", "sla", "sll", "sli", "sra", "srl", "sub", "xor", "org", - "cp", "di", "ei", "ex", "im", "in", "jp", "jr", "ld", "or", "rl", "rr", - "db", "dw", "ds", "dm", - "include", "incbin", "if", "else", "endif", "end", "macro", "endm", - "seek", NULL + "call", "cpdr", "cpir", "djnz", "halt", "indr", "inir", "lddr", "ldir", + "otdr", "otir", "outd", "outi", "push", "reti", "retn", "rlca", "rrca", + "defb", "defw", "defs", "defm", + "adc", "add", "and", "bit", "ccf", "cpd", "cpi", "cpl", "daa", "dec", "equ", + "exx", "inc", "ind", "ini", "ldd", "ldi", "neg", "nop", "out", "pop", + "res", "ret", "rla", "rlc", "rld", "rra", "rrc", "rrd", "rst", "sbc", + "scf", "set", "sla", "sll", "sli", "sra", "srl", "sub", "xor", "org", + "cp", "di", "ei", "ex", "im", "in", "jp", "jr", "ld", "or", "rl", "rr", + "db", "dw", "ds", "dm", + "include", "incbin", "if", "else", "endif", "end", "macro", "endm", + "seek", NULL }; /* linked lists */ @@ -230,566 +218,505 @@ static int define_macro = 0; /* file (and macro) stack */ static int sp; -static struct stack stack[MAX_INCLUDE]; /* maximum level of includes */ +static struct stack stack[MAX_INCLUDE]; /* maximum level of includes */ /* Produce output even with errors. */ static int use_force = 0; /* print an error message, including current line and file */ -static void -printerr (const char *fmt, ...) +static void printerr(const char *fmt, ...) { - int msp = (sp < 0) ? 0 : sp; - va_list l; - va_start (l, fmt); - fprintf (stderr, "%s%s:%d: ", stack[msp].dir ? stack[msp].dir->name : "", - stack[msp].name, stack[msp].line); - vfprintf (stderr, fmt, l); - va_end (l); - errors++; + int msp = (sp < 0) ? 0 : sp; + va_list l; + va_start(l, fmt); + fprintf(stderr, "%s%s:%d: ", stack[msp].dir ? stack[msp].dir->name : "", + stack[msp].name, stack[msp].line); + vfprintf(stderr, fmt, l); + va_end(l); + errors++; } /* skip over spaces in string */ -static const char * -delspc (const char *ptr) +static const char *delspc(const char *ptr) { - while (*ptr && isspace (*ptr)) - ptr++; - if (*ptr == ';') - ptr = ""; - return ptr; + while (*ptr && isspace(*ptr)) + ptr++; + if (*ptr == ';') + ptr = ""; + return ptr; } /* read away a comma, error if there is none */ -static void -rd_comma (const char **p) +static void rd_comma(const char **p) { - *p = delspc (*p); - if (**p != ',') - { - printerr ("`,' expected. Remainder of line: %s\n", *p); - return; + *p = delspc(*p); + if (**p != ',') { + printerr("`,' expected. Remainder of line: %s\n", *p); + return; } - *p = delspc ((*p) + 1); + *p = delspc((*p) + 1); } /* look ahead for a comma, no error if not found */ -static int -has_argument (const char **p) +static int has_argument(const char **p) { - const char *q = delspc (*p); - return (*q == ','); + const char *q = delspc(*p); + return (*q == ','); } /* During assembly, many literals are not parsed. Instead, they are saved * until all labels are read. After that, they are parsed. This function * is used during assembly, to find the place where the command continues. */ -static void -skipword (const char **pos, char delimiter) -{ - int depth = 0; - char c; - while (1) - { - switch (c = (*((*pos)++))) - { - case '\0': - if (depth > 0) - { - printerr ("unexpected end of line\n"); - } - (*pos)--; - return; - case '(': - depth++; - break; - case ')': - if (--depth < 0) - { - if (delimiter == ')') - return; - printerr ("unexpected `)'\n"); - } - break; - default: - if (delimiter == c && depth == 0) - { - return; - } - } +static void skipword(const char **pos, char delimiter) +{ + int depth = 0; + char c; + while (1) { + switch (c = (*((*pos)++))) { + case '\0': + if (depth > 0) { + printerr("unexpected end of line\n"); + } + (*pos)--; + return; + case '(': + depth++; + break; + case ')': + if (--depth < 0) { + if (delimiter == ')') + return; + printerr("unexpected `)'\n"); + } + break; + default: + if (delimiter == c && depth == 0) { + return; + } + } } } /* callback function for argument parser, used to open output files. */ -static FILE * -openfile (int *done, /* flag to check that a file is opened only once. */ - const char *type, /* name of filetype for error message */ - FILE * def, /* default value, in case "-" is specified */ - const char *name, /* filename to open */ - const char *flags) /* open flags */ -{ - FILE *retval; - if (*done) - { - fprintf (stderr, "Error: more than one %s specified\n", type); - exit (1); +static FILE *openfile(int *done, /* flag to check that a file is opened only once. */ + const char *type, /* name of filetype for error message */ + FILE * def, /* default value, in case "-" is specified */ + const char *name, /* filename to open */ + const char *flags) +{ /* open flags */ + FILE *retval; + if (*done) { + fprintf(stderr, "Error: more than one %s specified\n", type); + exit(1); } - *done = 1; - if (def && (!name || (name[0] == '-' && name[1] == 0))) - { - return def; + *done = 1; + if (def && (!name || (name[0] == '-' && name[1] == 0))) { + return def; } - if (!name || !name[0]) - { - fprintf (stderr, "Error: no %s specified\n", type); - exit (1); + if (!name || !name[0]) { + fprintf(stderr, "Error: no %s specified\n", type); + exit(1); } - if (!(retval = fopen (name, flags))) - { - fprintf (stderr, "Unable to open %s %s: %s\n", - type, name, strerror (errno)); - exit (1); + if (!(retval = fopen(name, flags))) { + fprintf(stderr, "Unable to open %s %s: %s\n", + type, name, strerror(errno)); + exit(1); } - return retval; + return retval; } /* open an included file, searching the path */ -static FILE * -open_include_file (const char *name, struct includedir **dir, - const char *flags) -{ - FILE *result; - struct includedir *i; - /* always try the current directory first */ - result = fopen (name, flags); - if (result) - { - if (dir) - *dir = NULL; - return result; - } - for (i = firstincludedir; i != NULL; i = i->next) - { - char *tmp = malloc (strlen (i->name) + strlen (name) + 1); - if (!tmp) - { - printerr ("not enough memory trying to open include file\n"); - return NULL; - } - strcpy (tmp, i->name); - strcat (tmp, name); - result = fopen (tmp, flags); - free (tmp); - if (result) - { - if (dir) - *dir = i; - return result; - } - } - return NULL; +static FILE *open_include_file(const char *name, struct includedir **dir, + const char *flags) +{ + FILE *result; + struct includedir *i; + /* always try the current directory first */ + result = fopen(name, flags); + if (result) { + if (dir) + *dir = NULL; + return result; + } + for (i = firstincludedir; i != NULL; i = i->next) { + char *tmp = malloc(strlen(i->name) + strlen(name) + 1); + if (!tmp) { + printerr("not enough memory trying to open include file\n"); + return NULL; + } + strcpy(tmp, i->name); + strcat(tmp, name); + result = fopen(tmp, flags); + free(tmp); + if (result) { + if (dir) + *dir = i; + return result; + } + } + return NULL; } /* queue a file to be opened for reading */ -static void -open_infile (const char *name) +static void open_infile(const char *name) { - infile = realloc (infile, sizeof (struct infile) * (infilecount + 1)); - if (!infile) - { - fprintf (stderr, "Error: insufficient memory\n"); - exit (1); + infile = realloc(infile, sizeof(struct infile) * (infilecount + 1)); + if (!infile) { + fprintf(stderr, "Error: insufficient memory\n"); + exit(1); } - /* only asm is currently supported */ - infile[infilecount].type = FILETYPE_ASM; - infile[infilecount].name = name; - if (verbose >= 5) - fprintf (stderr, "queued inputfile %s\n", infile[infilecount].name); - infilecount++; + /* only asm is currently supported */ + infile[infilecount].type = FILETYPE_ASM; + infile[infilecount].name = name; + if (verbose >= 5) + fprintf(stderr, "queued inputfile %s\n", infile[infilecount].name); + infilecount++; } /* add a directory to the include search path */ -static void -add_include (const char *name) -{ - struct includedir *i; - i = malloc (sizeof (struct includedir) + strlen (name) + 1); - if (!i) - { - fprintf (stderr, "Error: insufficient memory\n"); - exit (1); - } - strcpy (i->name, name); - if (name[strlen (name) - 1] != '/') - strcat (i->name, "/"); - i->next = firstincludedir; - firstincludedir = i; -} - -static void -try_use_real_file (FILE * real, FILE ** backup) -{ - fpos_t pos; - if (fgetpos (real, &pos) == 0) - { - *backup = real; - return; - } - if (!(*backup = tmpfile ())) - { - fprintf (stderr, "Error: Unable to open temporary file: %s\n", - strerror (errno)); - exit (1); - } -} - -static void -flush_to_real_file (FILE * real, FILE * tmp) -{ - int l, size, len = 0; - char buf[BUFLEN]; - if (tmp == real) - { - return; - } - rewind (tmp); - while (1) - { - clearerr (tmp); - errno = 0; - len = fread (buf, 1, BUFLEN, tmp); - if (len == 0 && feof (tmp)) - break; - if (len <= 0) - { - fprintf (stderr, "error reading temp file: %s\n", strerror (errno)); - exit (1); - } - l = 0; - while (l < len) - { - clearerr (real); - size = fwrite (&buf[l], 1, len - l, real); - if (size <= 0) - { - fprintf (stderr, "error writing final file: %s\n", - strerror (errno)); - exit (1); - } - l += size; - } +static void add_include(const char *name) +{ + struct includedir *i; + i = malloc(sizeof(struct includedir) + strlen(name) + 1); + if (!i) { + fprintf(stderr, "Error: insufficient memory\n"); + exit(1); + } + strcpy(i->name, name); + if (name[strlen(name) - 1] != '/') + strcat(i->name, "/"); + i->next = firstincludedir; + firstincludedir = i; +} + +static void try_use_real_file(FILE * real, FILE ** backup) +{ + fpos_t pos; + if (fgetpos(real, &pos) == 0) { + *backup = real; + return; + } + if (!(*backup = tmpfile())) { + fprintf(stderr, "Error: Unable to open temporary file: %s\n", + strerror(errno)); + exit(1); + } +} + +static void flush_to_real_file(FILE * real, FILE * tmp) +{ + int l, size, len = 0; + char buf[BUFLEN]; + if (tmp == real) { + return; + } + rewind(tmp); + while (1) { + clearerr(tmp); + errno = 0; + len = fread(buf, 1, BUFLEN, tmp); + if (len == 0 && feof(tmp)) + break; + if (len <= 0) { + fprintf(stderr, "error reading temp file: %s\n", strerror(errno)); + exit(1); + } + l = 0; + while (l < len) { + clearerr(real); + size = fwrite(&buf[l], 1, len - l, real); + if (size <= 0) { + fprintf(stderr, "error writing final file: %s\n", + strerror(errno)); + exit(1); + } + l += size; + } } } /* parse commandline arguments */ -static void -parse_commandline (int argc, char **argv) -{ - const struct option opts[] = { - {"help", no_argument, NULL, 'h'}, - {"version", no_argument, NULL, 'V'}, - {"verbose", no_argument, NULL, 'v'}, - {"list", optional_argument, NULL, 'l'}, - {"label", optional_argument, NULL, 'L'}, - {"input", required_argument, NULL, 'i'}, - {"output", required_argument, NULL, 'o'}, - {"label-prefix", required_argument, NULL, 'p'}, - {"includepath", required_argument, NULL, 'I'}, - {"force", no_argument, NULL, 'f'}, - {NULL, 0, NULL, 0} - }; - const char *short_opts = "hVvl:L:i:o:p:I:f"; - int done = 0, i, out = 0; - infile = NULL; - while (!done) - { - switch (getopt_long (argc, argv, short_opts, opts, NULL)) - { - case 'h': - /* split in two, to avoid too long string constant */ - printf ("Usage: %s [options] [input files]\n" - "\n" - "Possible options are:\n" - "-h\t--help\t\tDisplay this help text and exit.\n" - "-V\t--version\tDisplay version information and exit.\n" - "-v\t--verbose\tBe verbose. " - "Specify again to be more verbose.\n" - "-l\t--list\t\tWrite a list file.\n" - "-L\t--label\t\tWrite a label file.\n", argv[0]); - printf ("-p\t--label-prefix\tprefix all labels with this prefix.\n" - "-i\t--input\t\tSpecify an input file (-i may be omitted).\n" - "-o\t--output\tSpecify the output file.\n" - "-I\t--includepath\tAdd a directory to the include path.\n" - "Please send bug reports and feature requests to " - "<shevek@fmf.nl>\n"); - exit (0); - case 'V': - printf ("Z80 assembler version " VERSION "\n" - "Copyright (C) 2002-2005 Bas Wijnen " - "<shevek@fmf.nl>.\n" - "Copyright (C) 2005 Jan Wilmans " - "<jw@dds.nl>.\n" - "This program comes with ABSOLUTELY NO WARRANTY.\n" - "You may distribute copies of the program under the terms\n" - "of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the\n" - "License, or (at your option) any later version.\n\n" - "For more information about these matters, see the file\n" - "named COPYING.\n"); - exit (0); - case 'v': - verbose++; - if (verbose >= 5) - fprintf (stderr, "Verbosity increased to level %d\n", verbose); - break; - case 'o': - realoutputfile - = openfile (&out, "output file", stdout, optarg, "wb"); - realoutputfilename = optarg; - if (verbose >= 5) - fprintf (stderr, "Opened outputfile\n"); - break; - case 'i': - open_infile (optarg); - break; - case 'l': - reallistfile - = openfile (&havelist, "list file", stderr, optarg, "w"); - if (verbose >= 5) - fprintf (stderr, "Opened list file\n"); - break; - case 'L': - labelfile = openfile (&label, "label file", stderr, optarg, "w"); - labelfilename = optarg; - if (verbose >= 5) - fprintf (stderr, "Opened label file\n"); - break; - case 'p': - labelprefix = optarg; - break; - case 'I': - add_include (optarg); - break; - case 'f': - use_force = 1; - break; - case -1: - done = 1; - break; - default: - /* errors are handled by getopt_long */ - break; - } - } - for (i = optind; i < argc; ++i) - open_infile (argv[i]); - if (!infilecount) - open_infile ("-"); - if (!out) - realoutputfile = openfile (&out, "output file", stdout, "a.bin", "wb"); - try_use_real_file (realoutputfile, &outfile); - if (havelist) - try_use_real_file (reallistfile, &listfile); +static void parse_commandline(int argc, char **argv) +{ + const struct option opts[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {"verbose", no_argument, NULL, 'v'}, + {"list", optional_argument, NULL, 'l'}, + {"label", optional_argument, NULL, 'L'}, + {"input", required_argument, NULL, 'i'}, + {"output", required_argument, NULL, 'o'}, + {"label-prefix", required_argument, NULL, 'p'}, + {"includepath", required_argument, NULL, 'I'}, + {"force", no_argument, NULL, 'f'}, + {NULL, 0, NULL, 0} + }; + const char *short_opts = "hVvl:L:i:o:p:I:f"; + int done = 0, i, out = 0; + infile = NULL; + while (!done) { + switch (getopt_long(argc, argv, short_opts, opts, NULL)) { + case 'h': + /* split in two, to avoid too long string constant */ + printf("Usage: %s [options] [input files]\n" + "\n" + "Possible options are:\n" + "-h\t--help\t\tDisplay this help text and exit.\n" + "-V\t--version\tDisplay version information and exit.\n" + "-v\t--verbose\tBe verbose. " + "Specify again to be more verbose.\n" + "-l\t--list\t\tWrite a list file.\n" + "-L\t--label\t\tWrite a label file.\n", argv[0]); + printf("-p\t--label-prefix\tprefix all labels with this prefix.\n" + "-i\t--input\t\tSpecify an input file (-i may be omitted).\n" + "-o\t--output\tSpecify the output file.\n" + "-I\t--includepath\tAdd a directory to the include path.\n" + "Please send bug reports and feature requests to " + "<shevek@fmf.nl>\n"); + exit(0); + case 'V': + printf("Z80 assembler version " VERSION "\n" + "Copyright (C) 2002-2005 Bas Wijnen " + "<shevek@fmf.nl>.\n" + "Copyright (C) 2005 Jan Wilmans " + "<jw@dds.nl>.\n" + "This program comes with ABSOLUTELY NO WARRANTY.\n" + "You may distribute copies of the program under the terms\n" + "of the GNU General Public License as published by\n" + "the Free Software Foundation; either version 2 of the\n" + "License, or (at your option) any later version.\n\n" + "For more information about these matters, see the file\n" + "named COPYING.\n"); + exit(0); + case 'v': + verbose++; + if (verbose >= 5) + fprintf(stderr, "Verbosity increased to level %d\n", verbose); + break; + case 'o': + realoutputfile + = openfile(&out, "output file", stdout, optarg, "wb"); + realoutputfilename = optarg; + if (verbose >= 5) + fprintf(stderr, "Opened outputfile\n"); + break; + case 'i': + open_infile(optarg); + break; + case 'l': + reallistfile + = openfile(&havelist, "list file", stderr, optarg, "w"); + if (verbose >= 5) + fprintf(stderr, "Opened list file\n"); + break; + case 'L': + labelfile = openfile(&label, "label file", stderr, optarg, "w"); + labelfilename = optarg; + if (verbose >= 5) + fprintf(stderr, "Opened label file\n"); + break; + case 'p': + labelprefix = optarg; + break; + case 'I': + add_include(optarg); + break; + case 'f': + use_force = 1; + break; + case -1: + done = 1; + break; + default: + /* errors are handled by getopt_long */ + break; + } + } + for (i = optind; i < argc; ++i) + open_infile(argv[i]); + if (!infilecount) + open_infile("-"); + if (!out) + realoutputfile = openfile(&out, "output file", stdout, "a.bin", "wb"); + try_use_real_file(realoutputfile, &outfile); + if (havelist) + try_use_real_file(reallistfile, &listfile); } /* find any of the list[] entries as the start of ptr and return index */ -static int -indx (const char **ptr, const char **list, int error) -{ - int i, l; - *ptr = delspc (*ptr); - if (!**ptr) - { - if (error) - { - printerr ("unexpected end of line\n"); - return 0; - } - else - return 0; - } - if (comma > 1) - rd_comma (ptr); - for (i = 0; list[i]; i++) - { - l = strlen (list[i]); - if (list[i][0] && !strncasecmp (*ptr, list[i], l) - && (!isalnum ((*ptr)[l]) || !isalnum (list[i][l - 1]))) - { - (*ptr) += l; - if (verbose >= 4) - fprintf (stderr, "%5d (0x%04x): Piece of code found:%s\n", - stack[sp].line, addr, list[i]); - if (verbose >= 6) - fprintf (stderr, "%5d (0x%04x): Remainder of line=%s.\n", - stack[sp].line, addr, *ptr); - comma++; - return i + 1; - } - } - if (error) - { - printerr ("parse error. Remainder of line=%s\n", *ptr); - if (verbose >= 3) - { - fprintf (stderr, "When looking for any of:\n"); - for (i = 0; list[i]; i++) - fprintf (stderr, "%s\t", list[i]); - fprintf (stderr, "\n"); - } +static int indx(const char **ptr, const char **list, int error) +{ + int i, l; + *ptr = delspc(*ptr); + if (!**ptr) { + if (error) { + printerr("unexpected end of line\n"); + return 0; + } else + return 0; + } + if (comma > 1) + rd_comma(ptr); + for (i = 0; list[i]; i++) { + l = strlen(list[i]); + if (list[i][0] && !strncasecmp(*ptr, list[i], l) + && (!isalnum((*ptr)[l]) || !isalnum(list[i][l - 1]))) { + (*ptr) += l; + if (verbose >= 4) + fprintf(stderr, "%5d (0x%04x): Piece of code found:%s\n", + stack[sp].line, addr, list[i]); + if (verbose >= 6) + fprintf(stderr, "%5d (0x%04x): Remainder of line=%s.\n", + stack[sp].line, addr, *ptr); + comma++; + return i + 1; + } + } + if (error) { + printerr("parse error. Remainder of line=%s\n", *ptr); + if (verbose >= 3) { + fprintf(stderr, "When looking for any of:\n"); + for (i = 0; list[i]; i++) + fprintf(stderr, "%s\t", list[i]); + fprintf(stderr, "\n"); + } } - return 0; + return 0; } /* read a mnemonic */ -static int -readcommand (const char **p) +static int readcommand(const char **p) { - return indx (p, mnemonics, 0); + return indx(p, mnemonics, 0); } -static int rd_label (const char **p, int *exists, struct label **previous, - int level); +static int rd_label(const char **p, int *exists, struct label **previous, + int level); /* try to read a label and optionally store it in the list */ -static void -readlabel (const char **p, int store) -{ - const char *c, *d, *pos, *dummy; - int i, j; - struct label *buf, *previous, **thefirstlabel; - for (d = *p; *d && *d != ';'; ++d) - { - } - for (c = *p; !strchr (" \r\n\t", *c) && c < d; ++c) - { - } - pos = strchr (*p, ':'); - if (!pos || pos >= c) - return; - if (pos == *p) - { - printerr ("`:' found without a label"); - return; - } - if (!store) - { - *p = pos + 1; - return; - } - c = pos + 1; - dummy = *p; - j = rd_label (&dummy, &i, &previous, sp); - if (i || j) - { - printerr ("duplicate definition of label %s\n", *p); - *p = c; - return; - } - if (NULL == (buf = malloc (sizeof (struct label) + c - *p))) - { - printerr ("not enough memory to store label %s\n", *p); - *p = c; - return; - } - strncpy (buf->name, *p, c - *p - 1); - buf->name[c - *p - 1] = 0; - if (verbose >= 3) - fprintf (stderr, "%5d (0x%04x): Label found: %s\n", stack[sp].line, - addr, buf->name); - *p = c; - buf->value = addr; - lastlabel = buf; - if (buf->name[0] == '.') - thefirstlabel = &stack[sp].labels; - else - thefirstlabel = &firstlabel; - if (previous) - buf->next = previous->next; - else - buf->next = *thefirstlabel; - buf->prev = previous; - buf->valid = 1; - buf->busy = 0; - buf->ref = NULL; - if (buf->prev) - buf->prev->next = buf; - else - *thefirstlabel = buf; - if (buf->next) - buf->next->prev = buf; -} - -static void new_reference (const char *data, int type, char delimiter, - int ds_count); +static void readlabel(const char **p, int store) +{ + const char *c, *d, *pos, *dummy; + int i, j; + struct label *buf, *previous, **thefirstlabel; + for (d = *p; *d && *d != ';'; ++d) { + } + for (c = *p; !strchr(" \r\n\t", *c) && c < d; ++c) { + } + pos = strchr(*p, ':'); + if (!pos || pos >= c) + return; + if (pos == *p) { + printerr("`:' found without a label"); + return; + } + if (!store) { + *p = pos + 1; + return; + } + c = pos + 1; + dummy = *p; + j = rd_label(&dummy, &i, &previous, sp); + if (i || j) { + printerr("duplicate definition of label %s\n", *p); + *p = c; + return; + } + if (NULL == (buf = malloc(sizeof(struct label) + c - *p))) { + printerr("not enough memory to store label %s\n", *p); + *p = c; + return; + } + strncpy(buf->name, *p, c - *p - 1); + buf->name[c - *p - 1] = 0; + if (verbose >= 3) + fprintf(stderr, "%5d (0x%04x): Label found: %s\n", stack[sp].line, + addr, buf->name); + *p = c; + buf->value = addr; + lastlabel = buf; + if (buf->name[0] == '.') + thefirstlabel = &stack[sp].labels; + else + thefirstlabel = &firstlabel; + if (previous) + buf->next = previous->next; + else + buf->next = *thefirstlabel; + buf->prev = previous; + buf->valid = 1; + buf->busy = 0; + buf->ref = NULL; + if (buf->prev) + buf->prev->next = buf; + else + *thefirstlabel = buf; + if (buf->next) + buf->next->prev = buf; +} + +static void new_reference(const char *data, int type, char delimiter, + int ds_count); /* write one byte to the outfile, and add it to the list file as well */ -static void -write_one_byte (int b, int list) -{ - if (verbose >= 4) - fprintf (stderr, - "%5d (0x%04x): write_one_byte called with argument 0x%02x\n", - stack[sp].line, addr, b); - b &= 0xff; - putc (b, outfile); - if (list && havelist) - { - fprintf (listfile, " %02x", b); - listdepth += 3; +static void write_one_byte(int b, int list) +{ + if (verbose >= 4) + fprintf(stderr, + "%5d (0x%04x): write_one_byte called with argument 0x%02x\n", + stack[sp].line, addr, b); + b &= 0xff; + putc(b, outfile); + if (list && havelist) { + fprintf(listfile, " %02x", b); + listdepth += 3; } - addr++; + addr++; } /* write byte to outfile and possibly some index things as well */ -static void -wrtb (int b) -{ - if (verbose >= 4) - fprintf (stderr, "%5d (0x%04x): wrtb called with argument 0x%02x\n", - stack[sp].line, addr, b); - if (indexed) - { - if (verbose >= 5) - fprintf (stderr, "%5d (0x%04x): writing indexed byte 0x%02x\n", - stack[sp].line, addr, indexed); - write_one_byte (indexed, 1); - indexed = 0; - } - if (writebyte) - { - if (verbose >= 5) - fprintf (stderr, "%5d (0x%04x): using a xor on byte because there is " - "a writebyte.\n", stack[sp].line, addr); - b ^= 0x40; - } - if (verbose >= 5) - fprintf (stderr, "%5d (0x%04x): writing byte 0x%02x\n", stack[sp].line, - addr, b); - if (bitsetres && b != 0xCB) - { - new_reference (bitsetres, TYPE_BSR, ',', b); - bitsetres = NULL; - } - else - { - write_one_byte (b, 1); - } - if (indexjmp) - { - if (verbose >= 5) - fprintf (stderr, "%5d (0x%04x): Making reference for index/jump %s\n", - stack[sp].line, addr, indexjmp); - new_reference (indexjmp, TYPE_ABSB, ')', 1); - indexjmp = NULL; - } - if (writebyte) - { - if (verbose >= 5) - fprintf (stderr, "%5d (0x%04x): writing argument byte for padding\n", - stack[sp].line, addr); - writebyte = 0; - new_reference (readbyte, TYPE_ABSB, mem_delimiter, 1); +static void wrtb(int b) +{ + if (verbose >= 4) + fprintf(stderr, "%5d (0x%04x): wrtb called with argument 0x%02x\n", + stack[sp].line, addr, b); + if (indexed) { + if (verbose >= 5) + fprintf(stderr, "%5d (0x%04x): writing indexed byte 0x%02x\n", + stack[sp].line, addr, indexed); + write_one_byte(indexed, 1); + indexed = 0; + } + if (writebyte) { + if (verbose >= 5) + fprintf(stderr, + "%5d (0x%04x): using a xor on byte because there is " + "a writebyte.\n", stack[sp].line, addr); + b ^= 0x40; + } + if (verbose >= 5) + fprintf(stderr, "%5d (0x%04x): writing byte 0x%02x\n", stack[sp].line, + addr, b); + if (bitsetres && b != 0xCB) { + new_reference(bitsetres, TYPE_BSR, ',', b); + bitsetres = NULL; + } else { + write_one_byte(b, 1); + } + if (indexjmp) { + if (verbose >= 5) + fprintf(stderr, + "%5d (0x%04x): Making reference for index/jump %s\n", + stack[sp].line, addr, indexjmp); + new_reference(indexjmp, TYPE_ABSB, ')', 1); + indexjmp = NULL; + } + if (writebyte) { + if (verbose >= 5) + fprintf(stderr, "%5d (0x%04x): writing argument byte for padding\n", + stack[sp].line, addr); + writebyte = 0; + new_reference(readbyte, TYPE_ABSB, mem_delimiter, 1); } } @@ -807,307 +734,276 @@ wrtb (int b) * ~ + - (unary) rd_factor */ -static int -rd_number (const char **p, const char **endp, int base) -{ - int result = 0, i; - char *c, num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; - if (verbose >= 6) - fprintf (stderr, "%5d (0x%04x): Starting to read number of base %d" - "(string=%s).\n", stack[sp].line, addr, base, *p); - num[base] = '\0'; - *p = delspc (*p); - while (**p && (c = strchr (num, tolower (**p)))) - { - i = c - num; - if (verbose >= 7) - fprintf (stderr, "%5d (0x%04x): Digit found:%1x.\n", stack[sp].line, - addr, i); - result = result * base + i; - (*p)++; - } - if (endp) - *endp = *p; - *p = delspc (*p); - if (verbose >= 7) - fprintf (stderr, "%5d (0x%04x): rd_number returned %d (%04x).\n", - stack[sp].line, addr, result, result); - return result; -} - -static int -rd_otherbasenumber (const char **p) -{ - char c; - if (verbose >= 6) - fprintf (stderr, - "%5d (0x%04x): Starting to read basenumber (string=%s).\n", - stack[sp].line, addr, *p); - (*p)++; - if (!**p) - { - printerr ("unexpected end of line after `@'\n"); - return 0; - } - if (**p == '0' || !isalnum (**p)) - { - printerr ("base must be between 1 and z\n"); - return 0; +static int rd_number(const char **p, const char **endp, int base) +{ + int result = 0, i; + char *c, num[] = "0123456789abcdefghijklmnopqrstuvwxyz"; + if (verbose >= 6) + fprintf(stderr, "%5d (0x%04x): Starting to read number of base %d" + "(string=%s).\n", stack[sp].line, addr, base, *p); + num[base] = '\0'; + *p = delspc(*p); + while (**p && (c = strchr(num, tolower(**p)))) { + i = c - num; + if (verbose >= 7) + fprintf(stderr, "%5d (0x%04x): Digit found:%1x.\n", stack[sp].line, + addr, i); + result = result * base + i; + (*p)++; + } + if (endp) + *endp = *p; + *p = delspc(*p); + if (verbose >= 7) + fprintf(stderr, "%5d (0x%04x): rd_number returned %d (%04x).\n", + stack[sp].line, addr, result, result); + return result; +} + +static int rd_otherbasenumber(const char **p) +{ + char c; + if (verbose >= 6) + fprintf(stderr, + "%5d (0x%04x): Starting to read basenumber (string=%s).\n", + stack[sp].line, addr, *p); + (*p)++; + if (!**p) { + printerr("unexpected end of line after `@'\n"); + return 0; } - c = **p; - (*p)++; - if (isalpha (**p)) - return rd_number (p, NULL, tolower (c) - 'a' + 1); - return rd_number (p, NULL, c - '0' + 1); -} - -static int -rd_character (const char **p) -{ - int i; - if (verbose >= 6) - fprintf (stderr, - "%5d (0x%04x): Starting to read character (string=%s).\n", - stack[sp].line, addr, *p); - i = **p; - if (!i) - { - printerr ("unexpected end of line in string constant\n"); - return 0; + if (**p == '0' || !isalnum(**p)) { + printerr("base must be between 1 and z\n"); + return 0; } - if (i == '\\') - { - (*p)++; - if (**p >= '0' && **p <= '7') - { - int b, num_digits; - i = 0; - if ((*p)[1] >= '0' && (*p)[1] <= '7') - { - if (**p <= '3' && (*p)[2] >= '0' && (*p)[2] <= '7') - num_digits = 3; - else - num_digits = 2; - } - else - num_digits = 1; - for (b = 0; b < num_digits; ++b) - { - int bit = (*p)[num_digits - 1 - b] - '0'; - i += (1 << (b * 3)) * bit; - } - *p += num_digits; - } - else - { - switch (**p) - { - case 'n': - i = 10; - break; - case 'r': - i = 13; - break; - case 't': - i = 9; - break; - case 'a': - i = 7; - break; - case '\'': - printerr ("empty literal character\n"); - return 0; - case 0: - printerr ("unexpected end of line after " - "backslash in string constant\n"); - return 0; - default: - i = **p; - } - (*p)++; - } - } - else + c = **p; (*p)++; - if (verbose >= 7) - fprintf (stderr, "%5d (0x%04x): rd_character returned %d (%c).\n", - stack[sp].line, addr, i, i); - return i; -} - -static int rd_expr (const char **p, char delimiter, int *valid, int level); - -static int -compute_ref (struct reference *ref, int allow_invalid) -{ - const char *ptr; - int valid = 0; - int backup_addr = addr; - int backup_comma = comma; - int backup_file = file; - int backup_sp = sp; - sp = ref->level; - addr = ref->addr; - comma = ref->comma; - file = ref->infile; - if (verbose >= 3) - fprintf (stderr, "%5d (0x%04x): Making reference to %s (done=%d, " - "computed=%d)\n", - stack[sp].line, addr, ref->input, ref->done, - ref->computed_value); - ptr = ref->input; - if (!ref->done) - { - ref->computed_value = rd_expr (&ptr, ref->delimiter, - allow_invalid ? &valid : NULL, - ref->level); - if (valid) - ref->done = 1; - } - if (verbose >= 4) - fprintf (stderr, "%5d (0x%04x): Reference is %d (0x%04x).\n", - stack[sp].line, addr, ref->computed_value, ref->computed_value); - sp = backup_sp; - addr = backup_addr; - comma = backup_comma; - file = backup_file; - return ref->computed_value; + if (isalpha(**p)) + return rd_number(p, NULL, tolower(c) - 'a' + 1); + return rd_number(p, NULL, c - '0' + 1); +} + +static int rd_character(const char **p) +{ + int i; + if (verbose >= 6) + fprintf(stderr, + "%5d (0x%04x): Starting to read character (string=%s).\n", + stack[sp].line, addr, *p); + i = **p; + if (!i) { + printerr("unexpected end of line in string constant\n"); + return 0; + } + if (i == '\\') { + (*p)++; + if (**p >= '0' && **p <= '7') { + int b, num_digits; + i = 0; + if ((*p)[1] >= '0' && (*p)[1] <= '7') { + if (**p <= '3' && (*p)[2] >= '0' && (*p)[2] <= '7') + num_digits = 3; + else + num_digits = 2; + } else + num_digits = 1; + for (b = 0; b < num_digits; ++b) { + int bit = (*p)[num_digits - 1 - b] - '0'; + i += (1 << (b * 3)) * bit; + } + *p += num_digits; + } else { + switch (**p) { + case 'n': + i = 10; + break; + case 'r': + i = 13; + break; + case 't': + i = 9; + break; + case 'a': + i = 7; + break; + case '\'': + printerr("empty literal character\n"); + return 0; + case 0: + printerr("unexpected end of line after " + "backslash in string constant\n"); + return 0; + default: + i = **p; + } + (*p)++; + } + } else + (*p)++; + if (verbose >= 7) + fprintf(stderr, "%5d (0x%04x): rd_character returned %d (%c).\n", + stack[sp].line, addr, i, i); + return i; } -static int -check_label (struct label *labels, const char **p, struct label **ret, - struct label **previous, int force_skip) -{ - struct label *l; - const char *c; - unsigned s2; - *p = delspc (*p); - for (c = *p; isalnum (*c) || *c == '_' || *c == '.'; ++c) - { - } - s2 = c - *p; - for (l = labels; l; l = l->next) - { - unsigned s1, s; - int cmp; - s1 = strlen (l->name); - s = s1 < s2 ? s1 : s2; - cmp = strncmp (l->name, *p, s); - if (cmp > 0 || (cmp == 0 && s1 > s)) - { - if (force_skip) - *p = c; - return 0; - } - if (cmp < 0 || s2 > s) - { - if (previous) - *previous = l; - continue; - } - *p = c; - /* if label is not valid, compute it */ - if (l->ref) - { - compute_ref (l->ref, 1); - if (!l->ref->done) - { - /* label was not valid, and isn't computable. tell the - * caller that it doesn't exist, so it will try again later. - * Set ret to show actual existence. */ - if (verbose >= 6) - fprintf (stderr, - "%5d (0x%04x): returning invalid label %s.\n", - stack[sp].line, addr, l->name); - *ret = l; - return 0; - } - } - *ret = l; - return 1; - } - if (force_skip) - *p = c; - return 0; +static int rd_expr(const char **p, char delimiter, int *valid, int level); + +static int compute_ref(struct reference *ref, int allow_invalid) +{ + const char *ptr; + int valid = 0; + int backup_addr = addr; + int backup_comma = comma; + int backup_file = file; + int backup_sp = sp; + sp = ref->level; + addr = ref->addr; + comma = ref->comma; + file = ref->infile; + if (verbose >= 3) + fprintf(stderr, "%5d (0x%04x): Making reference to %s (done=%d, " + "computed=%d)\n", + stack[sp].line, addr, ref->input, ref->done, + ref->computed_value); + ptr = ref->input; + if (!ref->done) { + ref->computed_value = rd_expr(&ptr, ref->delimiter, + allow_invalid ? &valid : NULL, + ref->level); + if (valid) + ref->done = 1; + } + if (verbose >= 4) + fprintf(stderr, "%5d (0x%04x): Reference is %d (0x%0 |