1
0
mirror of https://github.com/pevans/erc-c.git synced 2024-06-25 12:29:34 +00:00

Switch to vm_di for option variable storage

Things like disk1, disk2, width/height, etc.
This commit is contained in:
Peter Evans 2018-03-07 20:25:39 -06:00
parent 58190f0c9b
commit 4d4fbdf79a
7 changed files with 76 additions and 153 deletions

View File

@ -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 *);

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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.
*/

View File

@ -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)

View File

@ -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;