From 332216b193e9bc0d59c4ce906139096587545a1c Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Mon, 23 Mar 2015 21:11:09 -0400 Subject: [PATCH] Work on parsing headers. --- src/logging.h | 3 +++ src/rom.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/rom.h | 9 ++++--- 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/logging.h b/src/logging.h index f5df66e..f95398b 100644 --- a/src/logging.h +++ b/src/logging.h @@ -30,6 +30,9 @@ #ifdef DEBUG_MODE #define DEBUG(...) LOG_MSG("[DEBUG]", {}, {}, __VA_ARGS__) #define DEBUG_ERRNO(...) LOG_MSG("[DEBUG]", PRINT_ERRNO(), {}, __VA_ARGS__) +#else +#define DEBUG(...) {} +#define DEBUG_ERRNO(...) {} #endif #define OUT_OF_MEMORY() FATAL("couldn't allocate enough memory") diff --git a/src/rom.c b/src/rom.c index 2113200..7686ea9 100644 --- a/src/rom.c +++ b/src/rom.c @@ -1,6 +1,7 @@ /* Copyright (C) 2014-2015 Ben Kurtovic Released under the terms of the MIT License. See LICENSE for details. */ +#include #include #include #include @@ -11,17 +12,76 @@ #include "rom.h" #include "logging.h" +#define NUM_LOCATIONS 3 +#define MAGIC_LEN 8 +#define HEADER_SIZE 16 + +static size_t header_locations[NUM_LOCATIONS] = {0x7ff0, 0x1ff0, 0x3ff0}; +static const char header_magic[MAGIC_LEN + 1] = "TMR SEGA"; + /* Return whether or not the given ROM image size is valid. */ static bool validate_size(off_t size) { + if (size & (size - 1)) + return false; // Ensure size is a power of two + off_t kbytes = size >> 10; - if (kbytes << 10 != size) - return false; - if (kbytes < 8 || kbytes > 1024) - return false; - return !(kbytes & (kbytes - 1)); + return kbytes >= 8 && kbytes <= 1024; +} + +#ifdef DEBUG_MODE +/* + DEBUG FUNCTION: Print out the header to stdout. +*/ +static void print_header(const char *header) +{ + char header_hex[3 * HEADER_SIZE], header_chr[3 * HEADER_SIZE]; + + for (int i = 0; i < HEADER_SIZE; i++) { + snprintf(&header_hex[3 * i], 3, "%02x", header[i]); + if (isprint(header[i])) + snprintf(&header_chr[3 * i], 3, "%2c", header[i]); + else { + header_chr[3 * i] = ' '; + header_chr[3 * i + 1] = '?'; + } + header_hex[3 * i + 2] = header_chr[3 * i + 2] = ' '; + } + header_hex[3 * HEADER_SIZE - 1] = header_chr[3 * HEADER_SIZE - 1] = '\0'; + DEBUG("- header dump (hex): %s", header_hex) + DEBUG("- header dump (chr): %s", header_chr) +} +#endif + +/* + Read a ROM image's header, and return whether or not it is valid. +*/ +static bool read_header(ROM *rom) +{ + size_t location, i; + const char *header; + + DEBUG("- looking for header:") + for (i = 0; i < NUM_LOCATIONS; i++) { + location = header_locations[i]; + DEBUG(" - trying location 0x%zx:", location) + header = &rom->data[location]; + if (memcmp(header, header_magic, MAGIC_LEN)) { + DEBUG(" - magic not present") + } + else { + DEBUG(" - magic found") +#ifdef DEBUG_MODE + print_header(header); +#endif + // TODO: parse header + return true; + } + } + DEBUG(" - could not find header") + return false; } /* @@ -61,8 +121,10 @@ const char* rom_open(ROM **rom_ptr, const char *path) if (!(rom->name = malloc(sizeof(char) * (strlen(path) + 1)))) OUT_OF_MEMORY() strcpy(rom->name, path); + DEBUG("Loading ROM %s:", rom->name) // Set rom->size: + DEBUG("- size: %lld", st.st_size) if (!validate_size(st.st_size)) { rom_close(rom); fclose(fp); @@ -78,8 +140,14 @@ const char* rom_open(ROM **rom_ptr, const char *path) fclose(fp); return rom_err_badread; } - fclose(fp); + + // Parse the header: + if (!read_header(rom)) { + rom_close(rom); + return rom_err_badheader; + } + *rom_ptr = rom; return NULL; } diff --git a/src/rom.h b/src/rom.h index 3b3333f..efb7269 100644 --- a/src/rom.h +++ b/src/rom.h @@ -5,10 +5,11 @@ /* 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"; +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"; +static const char* rom_err_badheader = "Invalid header"; /* Structs */