|
|
@@ -1,6 +1,7 @@ |
|
|
|
/* Copyright (C) 2014-2015 Ben Kurtovic <ben.kurtovic@gmail.com> |
|
|
|
Released under the terms of the MIT License. See LICENSE for details. */ |
|
|
|
|
|
|
|
#include <ctype.h> |
|
|
|
#include <errno.h> |
|
|
|
#include <stdbool.h> |
|
|
|
#include <stdio.h> |
|
|
@@ -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; |
|
|
|
} |
|
|
|