From afe764d0346ef341e8a8897d5ef2259fb305794f Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 23 Mar 2015 19:17:29 -0400 Subject: [PATCH] Improve ROM loading. --- crater.c | 19 ++++++++-------- makefile | 5 ++++- src/rom.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++---------------- src/rom.h | 10 ++++++++- 4 files changed, 80 insertions(+), 31 deletions(-) diff --git a/crater.c b/crater.c index fb3333f..6177669 100644 --- a/crater.c +++ b/crater.c @@ -37,19 +37,18 @@ int main(int argc, char *argv[]) retval = retval ? EXIT_SUCCESS : EXIT_FAILURE; } else { ROM *rom; + const char* errmsg; - printf("crater: a Sega Game Gear emulator\n\n"); - if (!(rom = rom_open(config->rom_path))) { - if (errno == ENOMEM) - OUT_OF_MEMORY() - else - FATAL_ERRNO("couldn't load ROM image '%s'", config->rom_path) - } - printf("Loaded ROM image: %s\n", rom->name); + if ((errmsg = rom_open(&rom, config->rom_path))) { + ERROR("couldn't load ROM image '%s': %s", config->rom_path, errmsg) + retval = EXIT_FAILURE; + } else { + printf("crater: emulating: %s\n", rom->name); - // TODO: emulate game here... + // TODO: emulate game here... - rom_close(rom); + rom_close(rom); + } } config_destroy(config); diff --git a/makefile b/makefile index 1db52d4..d4330b6 100644 --- a/makefile +++ b/makefile @@ -26,13 +26,16 @@ ifdef DEBUG MODE = debug endif -.PHONY: all clean +.PHONY: all clean test all: $(BNRY) clean: $(RM) $(BUILD) $(PROGRAM) $(PROGRAM)$(DEVEXT) +test: + @echo "not implemented yet" + $(DIRS): $(MKDIR) $@ diff --git a/src/rom.c b/src/rom.c index e684be6..2113200 100644 --- a/src/rom.c +++ b/src/rom.c @@ -2,51 +2,86 @@ Released under the terms of the MIT License. See LICENSE for details. */ #include +#include #include #include #include #include #include "rom.h" +#include "logging.h" /* - Create and return a ROM object located at the given path. Return NULL if - there was an error; errno will be set appropriately. + Return whether or not the given ROM image size is valid. */ -ROM* rom_open(const char *path) +static bool validate_size(off_t size) +{ + off_t kbytes = size >> 10; + if (kbytes << 10 != size) + return false; + if (kbytes < 8 || kbytes > 1024) + return false; + return !(kbytes & (kbytes - 1)); +} + +/* + Create and load a ROM image located at the given path. + + rom_ptr will point to the new object if created successfully, and NULL will + be returned. Otherwise, rom_ptr will not be modified and an error string + will be returned. The error string should not be freed. +*/ +const char* rom_open(ROM **rom_ptr, const char *path) { ROM *rom; FILE* fp; - struct stat s; + struct stat st; if (!(fp = fopen(path, "r"))) - return NULL; + return strerror(errno); - if (fstat(fileno(fp), &s)) { + if (fstat(fileno(fp), &st)) { fclose(fp); - return NULL; + return strerror(errno); } - if (!(s.st_mode & S_IFREG)) { - errno = (s.st_mode & S_IFDIR) ? EISDIR : ENOENT; + if (!(st.st_mode & S_IFREG)) { fclose(fp); - return NULL; + return (st.st_mode & S_IFDIR) ? rom_err_isdir : rom_err_notfile; } - if (!(rom = malloc(sizeof(ROM)))) { + if (!(rom = malloc(sizeof(ROM)))) + OUT_OF_MEMORY() + + // Set defaults: + rom->name = NULL; + rom->data = NULL; + rom->size = 0; + + // Set rom->name: + if (!(rom->name = malloc(sizeof(char) * (strlen(path) + 1)))) + OUT_OF_MEMORY() + strcpy(rom->name, path); + + // Set rom->size: + if (!validate_size(st.st_size)) { + rom_close(rom); fclose(fp); - return NULL; + return rom_err_badsize; } - rom->name = malloc(sizeof(char) * (strlen(path) + 1)); - if (!rom->name) { + rom->size = st.st_size; + + // Set rom->data: + if (!(rom->data = malloc(sizeof(char) * st.st_size))) + OUT_OF_MEMORY() + if (!(fread(rom->data, st.st_size, 1, fp))) { + rom_close(rom); fclose(fp); - return NULL; + return rom_err_badread; } - strcpy(rom->name, path); - - // TODO: load data from file into a buffer fclose(fp); - return rom; + *rom_ptr = rom; + return NULL; } /* @@ -54,5 +89,9 @@ ROM* rom_open(const char *path) */ void rom_close(ROM *rom) { + if (rom->name) + free(rom->name); + if (rom->data) + free(rom->data); free(rom); } diff --git a/src/rom.h b/src/rom.h index 5d493cc..3b3333f 100644 --- a/src/rom.h +++ b/src/rom.h @@ -3,14 +3,22 @@ #pragma once +/* Error strings */ + +static const char* rom_err_isdir = "Is a directory"; +static const char* rom_err_notfile = "Is not a regular file"; +static const char* rom_err_badsize = "Invalid size"; +static const char* rom_err_badread = "Couldn't read the entire file"; + /* Structs */ typedef struct { char* name; char* data; + unsigned size; } ROM; /* Functions */ -ROM* rom_open(const char*); +const char* rom_open(ROM**, const char*); void rom_close(ROM*);