@@ -1,190 +1,42 @@ | |||||
/* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com> | /* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com> | ||||
Released under the terms of the MIT License. See LICENSE for details. */ | Released under the terms of the MIT License. See LICENSE for details. */ | ||||
#include <dirent.h> | |||||
#include <errno.h> | |||||
#include <stdbool.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | |||||
#include <sys/types.h> | |||||
#include "src/errors.h" | |||||
#include "src/config.h" | |||||
#include "src/logging.h" | |||||
#include "src/rom.h" | #include "src/rom.h" | ||||
#include "src/version.h" | |||||
#define ROMS_DIR "roms" | |||||
/* Print command-line help/usage. */ | |||||
static void print_help(const char *arg1) | |||||
{ | |||||
printf("%s [-h] [-v] [-f] [-s <n>] [<rom_path>] ...\n" | |||||
"\n" | |||||
"basic options:\n" | |||||
" -h, --help show this help message and exit\n" | |||||
" -v, --version show crater's version number and exit\n" | |||||
" -f, --fullscreen enable fullscreen mode\n" | |||||
" -s, --scale <n> scale the game screen by an integer factor\n" | |||||
" (applies to windowed mode only)\n" | |||||
" <rom_path> path to the rom file to execute; if not given, will look\n" | |||||
" in the roms/ directory and prompt the user\n" | |||||
"\n" | |||||
"advanced options:\n" | |||||
" -g, --debug display information about emulation state while running,\n" | |||||
" including register and memory values; can also pause\n" | |||||
" emulation, set breakpoints, and change state\n" | |||||
" -a, --assemble <in> <out> convert z80 assembly source code into a\n" | |||||
" binary file that can be run by crater\n" | |||||
" -d, --disassemble <in> <out> convert a binary file into z80 assembly code\n", | |||||
arg1); | |||||
} | |||||
/* Print crater's version. */ | |||||
static void print_version() | |||||
{ | |||||
printf("crater %s\n", CRATER_VERSION); | |||||
} | |||||
/* Parse the command-line arguments for any special flags. */ | |||||
static void parse_args(int argc, char *argv[]) | |||||
{ | |||||
char *arg; | |||||
int i; | |||||
for (i = 1; i < argc; i++) { | |||||
arg = argv[i]; | |||||
if (arg[0] != '-') | |||||
continue; | |||||
do | |||||
arg++; | |||||
while (arg[0] == '-'); | |||||
if (!strcmp(arg, "h") || !strcmp(arg, "help")) { | |||||
print_help(argv[0]); | |||||
exit(0); | |||||
} else if (!strcmp(arg, "v") || !strcmp(arg, "version")) { | |||||
print_version(); | |||||
exit(0); | |||||
// f fullscreen | |||||
// s scale | |||||
// g debug | |||||
// a assemble | |||||
// d disassemble | |||||
} else { | |||||
FATAL("unknown argument: %s", argv[i]) | |||||
} | |||||
} | |||||
} | |||||
/* Return whether the given string ends with the given suffix. */ | |||||
static bool ends_with(const char *input, const char *suffix) | |||||
{ | |||||
size_t ilen = strlen(input), slen = strlen(suffix); | |||||
if (ilen < slen) | |||||
return false; | |||||
return strcmp(input + (ilen - slen), suffix) == 0; | |||||
} | |||||
/* Load all potential ROM files in roms/ into a data structure. */ | |||||
static int get_rom_paths(char ***path_ptr) | |||||
{ | |||||
DIR *dirp; | |||||
struct dirent *entry; | |||||
char **paths = NULL, *path; | |||||
int psize = 8, npaths = 0; | |||||
dirp = opendir(ROMS_DIR); | |||||
if (dirp) { | |||||
paths = malloc(sizeof(char*) * psize); | |||||
if (!paths) | |||||
OUT_OF_MEMORY() | |||||
while ((entry = readdir(dirp))) { | |||||
path = entry->d_name; | |||||
if (ends_with(path, ".gg") || ends_with(path, ".bin")) { | |||||
if (npaths >= psize) { | |||||
paths = realloc(paths, sizeof(char*) * (psize *= 2)); | |||||
if (!paths) | |||||
OUT_OF_MEMORY() | |||||
} | |||||
paths[npaths] = malloc(sizeof(char*) * | |||||
(strlen(path) + strlen(ROMS_DIR) + 1)); | |||||
if (!paths[npaths]) | |||||
OUT_OF_MEMORY() | |||||
strcpy(paths[npaths], ROMS_DIR "/"); | |||||
strcat(paths[npaths], path); | |||||
npaths++; | |||||
} | |||||
} | |||||
closedir(dirp); | |||||
} else { | |||||
WARN_ERRNO("couldn't open 'roms/'") | |||||
} | |||||
*path_ptr = paths; | |||||
return npaths; | |||||
} | |||||
/* Find all potential ROM files in the roms/ directory, then ask the user which | |||||
one they want to run. */ | |||||
static char* get_rom_path_from_user() | |||||
{ | |||||
char **paths, *path, *input = NULL; | |||||
int npaths, i; | |||||
long int index; | |||||
size_t size = 0; | |||||
ssize_t len; | |||||
npaths = get_rom_paths(&paths); | |||||
for (i = 0; i < npaths; i++) | |||||
printf("[%2d] %s\n", i + 1, paths[i]); | |||||
if (npaths) | |||||
printf("Enter a ROM number from above, or the path to a ROM image: "); | |||||
else | |||||
printf("Enter the path to a ROM image: "); | |||||
len = getline(&input, &size, stdin); | |||||
if (!input) | |||||
OUT_OF_MEMORY() | |||||
if (len > 0 && input[len - 1] == '\n') | |||||
input[len - 1] = '\0'; | |||||
index = strtol(input, NULL, 10); | |||||
if (index < 1 || index > npaths) | |||||
path = input; | |||||
else | |||||
path = paths[index - 1]; | |||||
for (i = 0; i < npaths; i++) { | |||||
if (paths[i] != path) | |||||
free(paths[i]); | |||||
} | |||||
if (paths) | |||||
free(paths); | |||||
return path; | |||||
} | |||||
/* | |||||
Main function. | |||||
*/ | |||||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||
{ | { | ||||
char *rom_path; | |||||
rom_type *rom; | |||||
Config *config; | |||||
ROM *rom; | |||||
int retval; | |||||
retval = config_create(&config, argc, argv); | |||||
if (retval != CONFIG_OK) | |||||
return retval == CONFIG_EXIT_SUCCESS ? EXIT_SUCCESS : EXIT_FAILURE; | |||||
parse_args(argc, argv); | |||||
printf("crater: a Sega Game Gear emulator\n\n"); | printf("crater: a Sega Game Gear emulator\n\n"); | ||||
rom_path = argc > 1 ? argv[1] : get_rom_path_from_user(); | |||||
if (rom_path[0] == '\0') | |||||
FATAL("no image given") | |||||
if (!(rom = rom_open(rom_path))) { | |||||
#ifdef DEBUG_MODE | |||||
config_dump_args(config); | |||||
#endif | |||||
if (!(rom = rom_open(config->rom_path))) { | |||||
if (errno == ENOMEM) | if (errno == ENOMEM) | ||||
OUT_OF_MEMORY() | OUT_OF_MEMORY() | ||||
else | else | ||||
FATAL_ERRNO("couldn't load ROM image '%s'", rom_path) | |||||
FATAL_ERRNO("couldn't load ROM image '%s'", config->rom_path) | |||||
} | } | ||||
if (argc <= 1) | |||||
free(rom_path); | |||||
printf("Loaded ROM image: %s.\n", rom->name); | printf("Loaded ROM image: %s.\n", rom->name); | ||||
// TODO: start from here | // TODO: start from here | ||||
rom_close(rom); | rom_close(rom); | ||||
return 0; | |||||
config_destroy(config); | |||||
return EXIT_SUCCESS; | |||||
} | } |
@@ -0,0 +1,340 @@ | |||||
/* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
Released under the terms of the MIT License. See LICENSE for details. */ | |||||
#include <dirent.h> | |||||
#include <errno.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
#include <sys/types.h> | |||||
#include "config.h" | |||||
#include "logging.h" | |||||
#include "version.h" | |||||
#define ROMS_DIR "roms" | |||||
/* | |||||
Print command-line help/usage. | |||||
*/ | |||||
static void print_help(const char *arg1) | |||||
{ | |||||
printf("%s [-h] [-v] [-f] [-s <n>] [<rom_path>] ...\n" | |||||
"\n" | |||||
"basic options:\n" | |||||
" -h, --help show this help message and exit\n" | |||||
" -v, --version show crater's version number and exit\n" | |||||
" -f, --fullscreen enable fullscreen mode\n" | |||||
" -s, --scale <n> scale the game screen by an integer factor\n" | |||||
" (applies to windowed mode only)\n" | |||||
" <rom_path> path to the rom file to execute; if not given, will look\n" | |||||
" in the roms/ directory and prompt the user\n" | |||||
"\n" | |||||
"advanced options:\n" | |||||
" -g, --debug display information about emulation state while running,\n" | |||||
" including register and memory values; can also pause\n" | |||||
" emulation, set breakpoints, and change state\n" | |||||
" -a, --assemble <in> <out> convert z80 assembly source code into a\n" | |||||
" binary file that can be run by crater\n" | |||||
" -d, --disassemble <in> <out> convert a binary file into z80 assembly code\n", | |||||
arg1); | |||||
} | |||||
/* | |||||
Print crater's version. | |||||
*/ | |||||
static void print_version() | |||||
{ | |||||
printf("crater %s\n", CRATER_VERSION); | |||||
} | |||||
/* | |||||
Return whether the given string ends with the given suffix. | |||||
*/ | |||||
static bool ends_with(const char *input, const char *suffix) | |||||
{ | |||||
size_t ilen = strlen(input), slen = strlen(suffix); | |||||
if (ilen < slen) | |||||
return false; | |||||
return strcmp(input + (ilen - slen), suffix) == 0; | |||||
} | |||||
/* | |||||
Load all potential ROM files in roms/ into a data structure. | |||||
*/ | |||||
static int get_rom_paths(char ***path_ptr) | |||||
{ | |||||
DIR *dirp; | |||||
struct dirent *entry; | |||||
char **paths = NULL, *path; | |||||
int psize = 8, npaths = 0; | |||||
dirp = opendir(ROMS_DIR); | |||||
if (dirp) { | |||||
paths = malloc(sizeof(char*) * psize); | |||||
if (!paths) | |||||
OUT_OF_MEMORY() | |||||
while ((entry = readdir(dirp))) { | |||||
path = entry->d_name; | |||||
if (ends_with(path, ".gg") || ends_with(path, ".bin")) { | |||||
if (npaths >= psize) { | |||||
paths = realloc(paths, sizeof(char*) * (psize *= 2)); | |||||
if (!paths) | |||||
OUT_OF_MEMORY() | |||||
} | |||||
paths[npaths] = malloc(sizeof(char*) * | |||||
(strlen(path) + strlen(ROMS_DIR) + 1)); | |||||
if (!paths[npaths]) | |||||
OUT_OF_MEMORY() | |||||
strcpy(paths[npaths], ROMS_DIR "/"); | |||||
strcat(paths[npaths], path); | |||||
npaths++; | |||||
} | |||||
} | |||||
closedir(dirp); | |||||
} else { | |||||
WARN_ERRNO("couldn't open 'roms/'") | |||||
} | |||||
*path_ptr = paths; | |||||
return npaths; | |||||
} | |||||
/* | |||||
Find all potential ROM files in the roms/ directory, then ask the user | |||||
which one they want to run. | |||||
*/ | |||||
static char* get_rom_path_from_user() | |||||
{ | |||||
char **paths, *path, *input = NULL; | |||||
int npaths, i; | |||||
long int index; | |||||
size_t size = 0; | |||||
ssize_t len; | |||||
npaths = get_rom_paths(&paths); | |||||
for (i = 0; i < npaths; i++) | |||||
printf("[%2d] %s\n", i + 1, paths[i]); | |||||
if (npaths) | |||||
printf("Enter a ROM number from above, or the path to a ROM image: "); | |||||
else | |||||
printf("Enter the path to a ROM image: "); | |||||
len = getline(&input, &size, stdin); | |||||
if (!input) | |||||
OUT_OF_MEMORY() | |||||
if (len > 0 && input[len - 1] == '\n') | |||||
input[len - 1] = '\0'; | |||||
index = strtol(input, NULL, 10); | |||||
if (index < 1 || index > npaths) | |||||
path = input; | |||||
else | |||||
path = paths[index - 1]; | |||||
for (i = 0; i < npaths; i++) { | |||||
if (paths[i] != path) | |||||
free(paths[i]); | |||||
} | |||||
if (paths) | |||||
free(paths); | |||||
return path; | |||||
} | |||||
/* | |||||
Parse the command-line arguments for any special flags. | |||||
*/ | |||||
static int parse_args(Config *config, int argc, char *argv[]) | |||||
{ | |||||
char *arg, *path; | |||||
int i, paths_read = 0; | |||||
for (i = 1; i < argc; i++) { | |||||
arg = argv[i]; | |||||
if (arg[0] != '-') { | |||||
// Parsing a path or other variable: | |||||
if (paths_read >= 2) { | |||||
ERROR("too many arguments given - emulator mode accepts one " | |||||
"ROM file,\nand assembler mode accepts one input file " | |||||
"and one output file") | |||||
return CONFIG_EXIT_FAILURE; | |||||
} | |||||
path = malloc(sizeof(char) * (strlen(arg) + 1)); | |||||
strcpy(path, arg); | |||||
if (paths_read == 1) { | |||||
/* If this is the second path given, it can only be an output | |||||
file for the assembler. If the assembler is not enabled by | |||||
subsequent arguments, we'll throw an error. */ | |||||
config->dst_path = path; | |||||
} else { | |||||
/* Otherwise, put the argument in the expected place. If we put | |||||
it in rom_path and the assembler is enabled by later | |||||
arguments, we'll move it. */ | |||||
if (config->assemble || config->disassemble) | |||||
config->src_path = path; | |||||
else | |||||
config->rom_path = path; | |||||
} | |||||
paths_read++; | |||||
continue; | |||||
} | |||||
// Parsing an option: | |||||
do | |||||
arg++; | |||||
while (arg[0] == '-'); | |||||
if (!strcmp(arg, "h") || !strcmp(arg, "help")) { | |||||
print_help(argv[0]); | |||||
return CONFIG_EXIT_SUCCESS; | |||||
} else if (!strcmp(arg, "v") || !strcmp(arg, "version")) { | |||||
print_version(); | |||||
return CONFIG_EXIT_SUCCESS; | |||||
} else if (!strcmp(arg, "f") || !strcmp(arg, "fullscreen")) { | |||||
config->fullscreen = true; | |||||
} else if (!strcmp(arg, "s") || !strcmp(arg, "scale")) { | |||||
if (i++ >= argc) { | |||||
ERROR("the scale option requires an argument") | |||||
return CONFIG_EXIT_FAILURE; | |||||
} | |||||
arg = argv[i]; | |||||
long scale = strtol(arg, NULL, 10); | |||||
if (scale <= 0 || scale > SCALE_MAX) { | |||||
ERROR("scale factor of %s is not an integer or is out of range", arg) | |||||
return CONFIG_EXIT_FAILURE; | |||||
} | |||||
} else if (!strcmp(arg, "g") || !strcmp(arg, "debug")) { | |||||
config->debug = true; | |||||
} else if (!strcmp(arg, "a") || !strcmp(arg, "assemble")) { | |||||
if (paths_read >= 1) { | |||||
config->src_path = config->rom_path; | |||||
config->rom_path = NULL; | |||||
} | |||||
config->assemble = true; | |||||
} else if (!strcmp(arg, "d") || !strcmp(arg, "disassemble")) { | |||||
if (paths_read >= 1) { | |||||
config->src_path = config->rom_path; | |||||
config->rom_path = NULL; | |||||
} | |||||
config->disassemble = true; | |||||
} else { | |||||
ERROR("unknown argument: %s", argv[i]) | |||||
return CONFIG_EXIT_FAILURE; | |||||
} | |||||
} | |||||
if (!config->assemble && !config->disassemble && paths_read >= 2) { | |||||
ERROR("too many arguments given - emulator mode accepts one ROM file") | |||||
return CONFIG_EXIT_FAILURE; | |||||
} | |||||
if (!config->assemble && !config->disassemble && paths_read == 0) { | |||||
path = get_rom_path_from_user(); | |||||
if (path[0] == '\0') { | |||||
ERROR("no ROM image given") | |||||
return CONFIG_EXIT_FAILURE; | |||||
} | |||||
config->rom_path = path; | |||||
} | |||||
return CONFIG_OK; | |||||
} | |||||
/* | |||||
Ensure that the combination of arguments in a config object are valid. | |||||
*/ | |||||
bool sanity_check(Config* config) | |||||
{ | |||||
if (config->fullscreen && config->scale) { | |||||
ERROR("cannot specify a scale in fullscreen mode") | |||||
return false; | |||||
} else if (config->assemble && config->disassemble) { | |||||
ERROR("cannot assemble and disassemble at the same time") | |||||
return false; | |||||
} else if ((config->assemble || config->disassemble) && | |||||
(config->debug || config->fullscreen || config->scale)) { | |||||
ERROR("cannot specify emulator options in assembler mode") | |||||
return false; | |||||
} else if ((config->assemble || config->disassemble) && | |||||
!(config->src_path && config->dst_path)) { | |||||
ERROR("assembler mode requires both an input and an output file") | |||||
return false; | |||||
} | |||||
return true; | |||||
} | |||||
/* | |||||
Create a new config object and load default values into it. | |||||
*/ | |||||
int config_create(Config** config_ptr, int argc, char* argv[]) | |||||
{ | |||||
Config *config; | |||||
int retval; | |||||
if (!(config = malloc(sizeof(Config)))) { | |||||
OUT_OF_MEMORY() | |||||
return CONFIG_EXIT_FAILURE; | |||||
} | |||||
config->debug = false; | |||||
config->assemble = false; | |||||
config->disassemble = false; | |||||
config->fullscreen = false; | |||||
config->scale = 1; | |||||
config->rom_path = NULL; | |||||
config->src_path = NULL; | |||||
config->dst_path = NULL; | |||||
retval = parse_args(config, argc, argv); | |||||
if (retval == CONFIG_OK && !sanity_check(config)) | |||||
retval = CONFIG_EXIT_FAILURE; | |||||
if (retval != CONFIG_OK) { | |||||
config_destroy(config); | |||||
return retval; | |||||
} | |||||
*config_ptr = config; | |||||
return CONFIG_OK; | |||||
} | |||||
/* | |||||
Destroy a config object previously created with config_create(). | |||||
*/ | |||||
void config_destroy(Config *config) | |||||
{ | |||||
if (config->rom_path) | |||||
free(config->rom_path); | |||||
if (config->src_path) | |||||
free(config->src_path); | |||||
if (config->dst_path) | |||||
free(config->dst_path); | |||||
free(config); | |||||
} | |||||
#ifdef DEBUG_MODE | |||||
/* | |||||
DEBUG FUNCTION: Print out all config arguments to stdout. | |||||
*/ | |||||
void config_dump_args(Config* config) | |||||
{ | |||||
DEBUG("Dumping arguments:") | |||||
DEBUG("- fullscreen: %d", config->fullscreen) | |||||
DEBUG("- scale: %d", config->scale) | |||||
DEBUG("- debug: %d", config->debug) | |||||
DEBUG("- assemble: %d", config->assemble) | |||||
DEBUG("- disassemble: %d", config->disassemble) | |||||
if (config->rom_path) | |||||
DEBUG("- rom_path: %s", config->rom_path) | |||||
else | |||||
DEBUG("- rom_path: NULL") | |||||
if (config->src_path) | |||||
DEBUG("- src_path: %s", config->src_path) | |||||
else | |||||
DEBUG("- src_path: NULL") | |||||
if (config->dst_path) | |||||
DEBUG("- dst_path: %s", config->dst_path) | |||||
else | |||||
DEBUG("- dst_path: NULL") | |||||
} | |||||
#endif |
@@ -0,0 +1,38 @@ | |||||
/* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
Released under the terms of the MIT License. See LICENSE for details. */ | |||||
#pragma once | |||||
#include <stdbool.h> | |||||
#define CONFIG_OK 0 | |||||
#define CONFIG_EXIT_SUCCESS 1 | |||||
#define CONFIG_EXIT_FAILURE 2 | |||||
/* | |||||
We need some sort of maximum scale - with a native resolution of 160 x 144, | |||||
a scale factor of 1024 will let us go up to 163,840 x 147,456 pixels. | |||||
No one has a screen this large. | |||||
*/ | |||||
#define SCALE_MAX 1024 | |||||
/* Structs */ | |||||
typedef struct { | |||||
bool debug; | |||||
bool assemble; | |||||
bool disassemble; | |||||
bool fullscreen; | |||||
unsigned scale; | |||||
char *rom_path; | |||||
char *src_path; | |||||
char *dst_path; | |||||
} Config; | |||||
/* Functions */ | |||||
int config_create(Config**, int, char*[]); | |||||
void config_destroy(Config*); | |||||
#ifdef DEBUG_MODE | |||||
void config_dump_args(Config*); | |||||
#endif |
@@ -1,27 +0,0 @@ | |||||
/* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
Released under the terms of the MIT License. See LICENSE for details. */ | |||||
#pragma once | |||||
#include <errno.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
/* Internal usage only */ | |||||
#define LOG_MSG(level, extra, after, ...) { \ | |||||
fprintf(stderr, level ": " __VA_ARGS__); \ | |||||
extra; \ | |||||
fprintf(stderr, ".\n"); \ | |||||
after; \ | |||||
} | |||||
#define PRINT_ERRNO() fprintf(stderr, ": %s", strerror(errno)) | |||||
/* Public error logging macros */ | |||||
#define FATAL(...) LOG_MSG("Error", {}, exit(EXIT_FAILURE), __VA_ARGS__) | |||||
#define FATAL_ERRNO(...) LOG_MSG("Error", PRINT_ERRNO(), exit(EXIT_FAILURE), __VA_ARGS__) | |||||
#define WARN(...) LOG_MSG("Warning", {}, {}, __VA_ARGS__) | |||||
#define WARN_ERRNO(...) LOG_MSG("Warning", PRINT_ERRNO(), {}, __VA_ARGS__) | |||||
#define OUT_OF_MEMORY() FATAL("couldn't allocate enough memory") |
@@ -0,0 +1,35 @@ | |||||
/* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com> | |||||
Released under the terms of the MIT License. See LICENSE for details. */ | |||||
#pragma once | |||||
#include <errno.h> | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <string.h> | |||||
/* Internal usage only */ | |||||
#define LOG_MSG(level, extra, tail, after, ...) { \ | |||||
fprintf(stderr, level ": " __VA_ARGS__); \ | |||||
extra; \ | |||||
fprintf(stderr, tail ? ".\n" : "\n"); \ | |||||
after; \ | |||||
} | |||||
#define PRINT_ERRNO() fprintf(stderr, ": %s", strerror(errno)) | |||||
/* Public logging macros */ | |||||
#define FATAL(...) LOG_MSG("Error", {}, 1, exit(EXIT_FAILURE), __VA_ARGS__) | |||||
#define FATAL_ERRNO(...) LOG_MSG("Error", PRINT_ERRNO(), 1, exit(EXIT_FAILURE), __VA_ARGS__) | |||||
#define ERROR(...) LOG_MSG("Error", {}, 1, {}, __VA_ARGS__) | |||||
#define ERROR_ERRNO(...) LOG_MSG("Error", PRINT_ERRNO(), 1, {}, __VA_ARGS__) | |||||
#define WARN(...) LOG_MSG("Warning", {}, 1, {}, __VA_ARGS__) | |||||
#define WARN_ERRNO(...) LOG_MSG("Warning", PRINT_ERRNO(), 1, {}, __VA_ARGS__) | |||||
#ifdef DEBUG_MODE | |||||
#define DEBUG(...) LOG_MSG("[DEBUG]", {}, 0, {}, __VA_ARGS__) | |||||
#define DEBUG_ERRNO(...) LOG_MSG("[DEBUG]", PRINT_ERRNO(), 0, {}, __VA_ARGS__) | |||||
#endif | |||||
#define OUT_OF_MEMORY() FATAL("couldn't allocate enough memory") |
@@ -9,11 +9,13 @@ | |||||
#include "rom.h" | #include "rom.h" | ||||
/* Create and return a ROM object located at the given path. Return NULL if | |||||
there was an error; errno will be set appropriately. */ | |||||
rom_type* rom_open(const char *path) | |||||
/* | |||||
Create and return a ROM object located at the given path. Return NULL if | |||||
there was an error; errno will be set appropriately. | |||||
*/ | |||||
ROM* rom_open(const char *path) | |||||
{ | { | ||||
rom_type *rom; | |||||
ROM *rom; | |||||
FILE* fp; | FILE* fp; | ||||
struct stat s; | struct stat s; | ||||
@@ -31,7 +33,7 @@ rom_type* rom_open(const char *path) | |||||
return NULL; | return NULL; | ||||
} | } | ||||
if (!(rom = malloc(sizeof(rom_type)))) { | |||||
if (!(rom = malloc(sizeof(ROM)))) { | |||||
fclose(fp); | fclose(fp); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -44,8 +46,10 @@ rom_type* rom_open(const char *path) | |||||
return rom; | return rom; | ||||
} | } | ||||
/* Free a ROM object previously created with rom_open(). */ | |||||
void rom_close(rom_type *rom) | |||||
/* | |||||
Free a ROM object previously created with rom_open(). | |||||
*/ | |||||
void rom_close(ROM *rom) | |||||
{ | { | ||||
free(rom); | free(rom); | ||||
} | } |
@@ -8,9 +8,9 @@ | |||||
typedef struct { | typedef struct { | ||||
char* name; | char* name; | ||||
char* data; | char* data; | ||||
} rom_type; | |||||
} ROM; | |||||
/* Functions */ | /* Functions */ | ||||
rom_type* rom_open(const char*); | |||||
void rom_close(rom_type*); | |||||
ROM* rom_open(const char*); | |||||
void rom_close(ROM*); |
@@ -10,4 +10,4 @@ | |||||
typedef struct { | typedef struct { | ||||
int pc; | int pc; | ||||
} z80_type; | |||||
} Z80; |