mirror of
https://github.com/pevans/erc-c.git
synced 2024-12-21 23:29:16 +00:00
Switch to vm_di for option variable storage
Things like disk1, disk2, width/height, etc.
This commit is contained in:
parent
58190f0c9b
commit
4d4fbdf79a
@ -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 *);
|
||||
|
@ -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
|
||||
|
12
src/apple2.c
12
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;
|
||||
|
@ -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);
|
||||
|
||||
|
99
src/option.c
99
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.
|
||||
*/
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user