From 9397107e214184c41a264f21edc5d419da69d069 Mon Sep 17 00:00:00 2001 From: Ben Kurtovic Date: Fri, 24 Apr 2015 13:17:16 -0500 Subject: [PATCH] Fix MMU mirroring algo, support reading 48 KB ROMs. --- src/assembler.c | 6 +++--- src/mmu.c | 21 +++++++++++++++++---- src/rom.c | 28 ++++++++-------------------- src/util.c | 2 +- 4 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/assembler.c b/src/assembler.c index bae4d35..ffc88a2 100644 --- a/src/assembler.c +++ b/src/assembler.c @@ -91,7 +91,7 @@ static ErrorInfo* check_layout( { const ASMLine *clash = NULL; - if (loc->offset + loc->length >= size) { + if (loc->offset + loc->length > size) { clash = &bounds_sentinel; } else { for (size_t i = 0; i < loc->length; i++) { @@ -226,7 +226,7 @@ static ErrorInfo* resolve_defaults(AssemblerState *state) const ASMInstruction *inst = state->instructions; while (inst) { size_t bound = inst->loc.offset + inst->loc.length; - if (bound >= state->rom_size) + if (bound > state->rom_size) state->rom_size = bounding_rom_size(bound); inst = inst->next; } @@ -234,7 +234,7 @@ static ErrorInfo* resolve_defaults(AssemblerState *state) const ASMData *data = state->data; while (data) { size_t bound = data->loc.offset + data->loc.length; - if (bound >= state->rom_size) + if (bound > state->rom_size) state->rom_size = bounding_rom_size(bound); data = data->next; } diff --git a/src/mmu.c b/src/mmu.c index b79cdd6..64f83a5 100644 --- a/src/mmu.c +++ b/src/mmu.c @@ -52,15 +52,28 @@ void mmu_load_rom(MMU *mmu, const uint8_t *data, size_t size) if (size % MMU_ROM_BANK_SIZE) return; - size_t banks = size / MMU_ROM_BANK_SIZE; + size_t banks = size / MMU_ROM_BANK_SIZE, bank, mirror; if (banks > MMU_NUM_ROM_BANKS) banks = MMU_NUM_ROM_BANKS; - for (size_t bank = 0; bank < banks; bank++) { - for (size_t mirror = bank; mirror < banks; mirror += bank + 1) { + for (bank = 0; bank < banks; bank++) { + for (mirror = bank; mirror < MMU_NUM_ROM_BANKS; mirror += banks) mmu->rom_banks[mirror] = data + (bank * MMU_ROM_BANK_SIZE); + } + +#ifdef DEBUG_MODE + char temp_str[64]; + DEBUG("Dumping MMU bank table:") + for (size_t group = 0; group < MMU_NUM_ROM_BANKS / 8; group++) { + for (size_t elem = 0; elem < 8; elem++) { + bank = 8 * group + elem; + snprintf(temp_str + 6 * elem, 7, "%02zX=%02zX ", bank, + (mmu->rom_banks[bank] - data) >> 14); } + temp_str[47] = '\0'; + DEBUG("- %s", temp_str) } +#endif } /* @@ -68,7 +81,7 @@ void mmu_load_rom(MMU *mmu, const uint8_t *data, size_t size) */ static inline void map_slot(MMU *mmu, size_t slot, size_t bank) { - DEBUG("MMU mapping memory slot %zu to bank %zu", slot, bank) + DEBUG("MMU mapping memory slot %zu to bank 0x%02zX", slot, bank) mmu->map_slots[slot] = mmu->rom_banks[bank]; } diff --git a/src/rom.c b/src/rom.c index de3e07f..4a65c88 100644 --- a/src/rom.c +++ b/src/rom.c @@ -20,18 +20,6 @@ static size_t header_locations[NUM_LOCATIONS] = {0x7FF0, 0x3FF0, 0x1FF0}; 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; - return kbytes >= 8 && kbytes <= 1024; -} - #ifdef DEBUG_MODE /* DEBUG FUNCTION: Print out the header to stdout. @@ -96,15 +84,14 @@ static uint16_t compute_checksum(const uint8_t *data, size_t size, uint8_t range #ifdef DEBUG_MODE /* - DEBUG FUNCTION: Return the ROM's size as a string, according to its header. + DEBUG FUNCTION: Given a ROM size, return a pretty string. */ -static const char* parse_reported_size(uint8_t value) +static const char* size_to_string(size_t size) { static char buffer[SIZE_CODE_BUF]; - size_t size = size_code_to_bytes(value); if (!size) - strncpy(buffer, "Unknown", SIZE_CODE_BUF); + strncpy(buffer, "unknown", SIZE_CODE_BUF); else if (size >= (1 << 20)) snprintf(buffer, SIZE_CODE_BUF, "%zu MB", size >> 20); else @@ -162,7 +149,8 @@ static bool parse_header(ROM *rom, const uint8_t *header) DEBUG(" - version: %u", rom->version) DEBUG(" - region code: %u (%s)", rom->region_code, rom_region(rom) ? rom_region(rom) : "unknown") - DEBUG(" - reported size: %s", parse_reported_size(header[0xF] & 0xF)) + DEBUG(" - reported size: %s", + size_to_string(size_code_to_bytes(header[0xF] & 0xF))) return true; } @@ -191,7 +179,7 @@ static bool find_and_read_header(ROM *rom) return parse_header(rom, header); } } - DEBUG(" - could not find header") + DEBUG(" - couldn't find header") return false; } @@ -240,8 +228,8 @@ const char* rom_open(ROM **rom_ptr, const char *path) DEBUG("Loading ROM %s:", rom->name) // Set rom->size: - DEBUG("- size: %lld", st.st_size) - if (!validate_size(st.st_size)) { + DEBUG("- size: %lld bytes (%s)", st.st_size, size_to_string(st.st_size)) + if (size_bytes_to_code(st.st_size) == INVALID_SIZE_CODE) { rom_close(rom); fclose(fp); return rom_err_badsize; diff --git a/src/util.c b/src/util.c index 050c7a9..1be96bc 100644 --- a/src/util.c +++ b/src/util.c @@ -126,7 +126,7 @@ size_t size_code_to_bytes(uint8_t code) uint8_t size_bytes_to_code(size_t bytes) { if (bytes & ((1 << 10) - 1)) - return 0; // Not an even number of KB + return INVALID_SIZE_CODE; // Not an even number of KB switch (bytes >> 10) { case 8: return 0xA;