From 4d4fbdf79a463529d5ba968ed81db049812c5079 Mon Sep 17 00:00:00 2001 From: Peter Evans Date: Wed, 7 Mar 2018 20:25:39 -0600 Subject: [PATCH] Switch to vm_di for option variable storage Things like disk1, disk2, width/height, etc. --- include/option.h | 4 +- include/vm_di.h | 12 ++++++ src/apple2.c | 12 +++--- src/main.c | 6 ++- src/option.c | 99 ++++++++++++++---------------------------------- tests/apple2.c | 16 +++++++- tests/option.c | 80 ++++++-------------------------------- 7 files changed, 76 insertions(+), 153 deletions(-) diff --git a/include/option.h b/include/option.h index 3787d53..e51cd63 100644 --- a/include/option.h +++ b/include/option.h @@ -17,10 +17,8 @@ enum option_flags { extern bool option_flag(int); extern FILE *option_get_input(int); extern const char *option_get_error(); -extern int option_get_height(); -extern int option_get_width(); extern int option_parse(int, char **); -extern int option_read_file(int, const char *); +extern int option_read_file(FILE **, const char *); extern int option_set_size(const char *); extern void option_print_help(); extern void option_set_error(const char *); diff --git a/include/vm_di.h b/include/vm_di.h index a789d03..b68ca3d 100644 --- a/include/vm_di.h +++ b/include/vm_di.h @@ -7,6 +7,18 @@ enum vm_di_entry { VM_REFLECT, VM_OUTPUT, + // These are the physical width and height of the emulator window + VM_WIDTH, + VM_HEIGHT, + + // These are file streams that correspond to disk inputs; e.g., in + // an apple context, these would be from disk drives 1 and 2 + VM_DISK1, + VM_DISK2, + + // The log file to which we will output our disassembly + VM_DISASM_LOG, + // This value is the size of the DI container we will construct. As // you can see, it's quite a bit higher than what would be implied // by the number of enum values currently defined--and it is so we diff --git a/src/apple2.c b/src/apple2.c index 76a5409..62a151c 100644 --- a/src/apple2.c +++ b/src/apple2.c @@ -235,7 +235,7 @@ apple2_boot(apple2 *mach) int err; // Do we have any disks? - stream = option_get_input(1); + stream = (FILE *)vm_di_get(VM_DISK1); if (stream) { err = apple2_dd_insert(mach->drive1, stream, DD_DOS33); if (err != OK) { @@ -244,7 +244,7 @@ apple2_boot(apple2 *mach) } } - stream = option_get_input(2); + stream = (FILE *)vm_di_get(VM_DISK2); if (stream) { err = apple2_dd_insert(mach->drive2, stream, DD_DOS33); if (err != OK) { @@ -341,13 +341,13 @@ apple2_free(apple2 *mach) void apple2_run_loop(apple2 *mach) { - FILE *out; + FILE *dlog; if (option_flag(OPTION_DISASSEMBLE)) { return; } - out = (FILE *)vm_di_get(VM_OUTPUT); + dlog = (FILE *)vm_di_get(VM_DISASM_LOG); while (vm_screen_active(mach->screen)) { if (vm_debug_broke(mach->cpu->PC)) { @@ -360,7 +360,7 @@ apple2_run_loop(apple2 *mach) mach->selected_drive->locked = true; } - mos6502_dis_opcode(mach->cpu, out, mach->cpu->PC); + mos6502_dis_opcode(mach->cpu, dlog, mach->cpu->PC); if (mach->selected_drive) { mach->selected_drive->locked = false; @@ -381,7 +381,7 @@ apple2_run_loop(apple2 *mach) mach->selected_drive->locked = true; } - mos6502_dis_opcode(mach->cpu, out, mach->cpu->PC); + mos6502_dis_opcode(mach->cpu, dlog, mach->cpu->PC); if (mach->selected_drive) { mach->selected_drive->locked = false; diff --git a/src/main.c b/src/main.c index 137e345..0c97a49 100644 --- a/src/main.c +++ b/src/main.c @@ -95,10 +95,12 @@ main(int argc, char **argv) // successfully or if we run `exit()` from elsewhere in the program. atexit(finish); + int *width = (int *)vm_di_get(VM_WIDTH); + int *height = (int *)vm_di_get(VM_HEIGHT); + // Let's build the basic machine, using the width and height // indicated by the user. - mach = apple2_create(option_get_width(), - option_get_height()); + mach = apple2_create(*width, *height); vm_di_set(VM_MACHINE, mach); diff --git a/src/option.c b/src/option.c index 0e01d91..5fcb6db 100644 --- a/src/option.c +++ b/src/option.c @@ -13,6 +13,7 @@ #include "option.h" #include "log.h" +#include "vm_di.h" /* * These are the file inputs we may have to the system. What their @@ -22,6 +23,8 @@ static FILE *input1 = NULL; static FILE *input2 = NULL; +static FILE *disasm_log = NULL; + /* * The size of our error buffer for anything we want to record while our * option parsing goes on. @@ -61,7 +64,7 @@ enum options { * Here are the options we support for program execution. */ static struct option long_options[] = { - { "disassemble", 0, NULL, DISASSEMBLE }, + { "disassemble", 1, NULL, DISASSEMBLE }, { "disk1", 1, NULL, DISK1 }, { "disk2", 1, NULL, DISK2 }, { "flash", 0, NULL, FLASH }, @@ -112,21 +115,32 @@ option_parse(int argc, char **argv) error_buffer[0] = '\0'; do { - int input_source = 0; - opt = getopt_long_only(argc, argv, "", long_options, &index); switch (opt) { case DISASSEMBLE: flags |= OPTION_DISASSEMBLE; + if (!option_read_file(&disasm_log, optarg)) { + return 0; + } + + vm_di_set(VM_DISASM_LOG, disasm_log); break; case DISK1: - input_source = 1; + if (!option_read_file(&input1, optarg)) { + return 0; + } + + vm_di_set(VM_DISK1, input1); break; case DISK2: - input_source = 2; + if (!option_read_file(&input2, optarg)) { + return 0; + } + + vm_di_set(VM_DISK2, input2); break; case FLASH: @@ -145,13 +159,6 @@ option_parse(int argc, char **argv) } break; } - - // We seem to have a request to load a file, so let's do so. - if (input_source) { - if (!option_read_file(input_source, optarg)) { - return 0; - } - } } while (opt != -1); return 1; @@ -164,62 +171,27 @@ option_parse(int argc, char **argv) * 0 if not. */ int -option_read_file(int source, const char *file) +option_read_file(FILE **stream, const char *file) { - FILE *stream; - if (!file) { snprintf(error_buffer, ERRBUF_SIZE, - "No file given for --disk%d\n", - source); + "No file given for --diskN\n"); return 0; } - stream = fopen(file, "r+"); - if (stream == NULL) { + *stream = fopen(file, "r+"); + if (*stream == NULL) { snprintf(error_buffer, ERRBUF_SIZE, - "--disk%d: %s", - source, + "--diskN: %s", strerror(errno)); return 0; } - option_set_input(source, stream); - return 1; } -/* - * Return the FILE stream for a given input, or NULL if none can be - * found. NULL may also be returned if the input has not previously been - * assigned. - */ -FILE * -option_get_input(int source) -{ - switch (source) { - case 1: return input1; - case 2: return input2; - } - - return NULL; -} - -/* - * Set the given input source to a given FILE stream. If the input - * source is invalid, then nothing is done. - */ -void -option_set_input(int source, FILE *stream) -{ - switch (source) { - case 1: input1 = stream; - case 2: input2 = stream; - } -} - /* * Print out a help message. You'll note this is not automatically * generated; it must be manually updated as we add other options. @@ -230,7 +202,7 @@ option_print_help() fprintf(stderr, "Usage: erc [options...]\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, "\ - --disassemble Print assembly notation from CPU memory\n\ + --disassemble=FILE Write assembly notation into FILE\n\ --disk1=FILE Load FILE into disk drive 1\n\ --disk2=FILE Load FILE into disk drive 2\n\ --flash Flash CPU memory with contents of drive 1\n\ @@ -255,6 +227,9 @@ option_set_size(const char *size) } else if (strcmp(size, "875x600") == 0) { width = 875; height = 600; + + vm_di_set(VM_WIDTH, &width); + vm_di_set(VM_HEIGHT, &height); return OK; } @@ -262,24 +237,6 @@ option_set_size(const char *size) return ERR_BADOPT; } -/* - * Return the window width we've been configured to use. - */ -int -option_get_width() -{ - return width; -} - -/* - * Return the window height we want. - */ -int -option_get_height() -{ - return height; -} - /* * Return true if the given option flag is set. */ diff --git a/tests/apple2.c b/tests/apple2.c index dc70875..5e621d5 100644 --- a/tests/apple2.c +++ b/tests/apple2.c @@ -3,6 +3,7 @@ #include "apple2.h" #include "mos6502.enums.h" #include "option.h" +#include "vm_di.h" static apple2 *mach; @@ -47,12 +48,23 @@ Test(apple2, boot) // ][e" at the bottom. cr_assert_eq(apple2_boot(mach), OK); + FILE *stream1, *stream2; + // And, as you may guess, it's ok to reboot the machine. - option_read_file(1, "../data/zero.img"); + option_read_file(&stream1, "../data/zero.img"); + vm_di_set(VM_DISK1, stream1); + cr_assert_eq(apple2_boot(mach), OK); - option_read_file(2, "../data/bad.img"); + option_read_file(&stream2, "../data/bad.img"); + vm_di_set(VM_DISK2, stream2); cr_assert_neq(apple2_boot(mach), OK); + + fclose(stream1); + fclose(stream2); + + vm_di_set(VM_DISK1, NULL); + vm_di_set(VM_DISK2, NULL); } Test(apple2, set_color) diff --git a/tests/option.c b/tests/option.c index 6fda0d3..c66451e 100644 --- a/tests/option.c +++ b/tests/option.c @@ -7,26 +7,11 @@ static void setup() { option_set_error(""); - option_set_input(1, NULL); - option_set_input(2, NULL); } static void teardown() { - FILE *stream; - - for (int i = 1; i <= OPTION_MAX_DISKS; i++) { - stream = option_get_input(i); - - if (stream - && stream != stdout - && stream != stderr - && stream != stdin - ) { - fclose(stream); - } - } } TestSuite(options, .init = setup, .fini = teardown); @@ -46,44 +31,30 @@ Test(option, error) cr_assert_str_eq(option_get_error(), str); } -/* Test(option, get_input) */ -/* Test(option, set_input) */ -Test(option, input) -{ - cr_assert_eq(option_get_input(1), NULL); - cr_assert_eq(option_get_input(2), NULL); - - option_set_input(2, stdout); - cr_assert_eq(option_get_input(2), stdout); - - option_set_input(3, stderr); - cr_assert_eq(option_get_input(3), NULL); -} - Test(option, read_file) { char *str = "so much FUN"; char *bad_file = "/tmp/BLEH"; char *file = "/tmp/erc-test.txt"; char buf[256]; - - cr_assert_eq(option_get_input(1), NULL); + FILE *stream_a; + FILE *stream_b; // Maybe we should use sterror(ENOENT)? - cr_assert_eq(option_read_file(1, bad_file), 0); - cr_assert_str_eq(option_get_error(), "--disk1: No such file or directory"); + cr_assert_eq(option_read_file(&stream_a, bad_file), 0); + cr_assert_str_eq(option_get_error(), "--diskN: No such file or directory"); option_set_error(""); - FILE *stream; - stream = fopen(file, "w"); - cr_assert_neq(stream, NULL); - fwrite(str, sizeof(char), strlen(str), stream); - fclose(stream); + stream_a = fopen(file, "w"); + cr_assert_neq(stream_a, NULL); + fwrite(str, sizeof(char), strlen(str), stream_a); + fclose(stream_a); - option_read_file(1, file); - fread(buf, sizeof(char), 255, option_get_input(1)); + option_read_file(&stream_b, file); + fread(buf, sizeof(char), 255, stream_b); cr_assert_str_eq(buf, str); + fclose(stream_b); unlink(file); } @@ -105,35 +76,6 @@ Test(option, parse) cr_assert_eq(option_parse(argc, argv), 0); } -/* - * The get_width and get_height tests also implicitly test the - * option_set_size() function (which is called by option_parse()). - * Test(option, set_size) - */ -Test(option, get_width) -{ - int argc = 2; - char *argv[] = { - "prog_name", - "--size=875x600", - }; - - cr_assert_eq(option_parse(argc, argv), 1); - cr_assert_eq(option_get_width(), 875); -} - -Test(option, get_height) -{ - int argc = 2; - char *argv[] = { - "prog_name", - "--size=875x600", - }; - - cr_assert_eq(option_parse(argc, argv), 1); - cr_assert_eq(option_get_height(), 600); -} - Test(option, flag) { int argc = 2;