| @@ -91,7 +91,7 @@ static ErrorInfo* check_layout( | |||||
| { | { | ||||
| const ASMLine *clash = NULL; | const ASMLine *clash = NULL; | ||||
| if (loc->offset + loc->length >= size) { | |||||
| if (loc->offset + loc->length > size) { | |||||
| clash = &bounds_sentinel; | clash = &bounds_sentinel; | ||||
| } else { | } else { | ||||
| for (size_t i = 0; i < loc->length; i++) { | for (size_t i = 0; i < loc->length; i++) { | ||||
| @@ -226,7 +226,7 @@ static ErrorInfo* resolve_defaults(AssemblerState *state) | |||||
| const ASMInstruction *inst = state->instructions; | const ASMInstruction *inst = state->instructions; | ||||
| while (inst) { | while (inst) { | ||||
| size_t bound = inst->loc.offset + inst->loc.length; | 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); | state->rom_size = bounding_rom_size(bound); | ||||
| inst = inst->next; | inst = inst->next; | ||||
| } | } | ||||
| @@ -234,7 +234,7 @@ static ErrorInfo* resolve_defaults(AssemblerState *state) | |||||
| const ASMData *data = state->data; | const ASMData *data = state->data; | ||||
| while (data) { | while (data) { | ||||
| size_t bound = data->loc.offset + data->loc.length; | 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); | state->rom_size = bounding_rom_size(bound); | ||||
| data = data->next; | data = data->next; | ||||
| } | } | ||||
| @@ -52,15 +52,28 @@ void mmu_load_rom(MMU *mmu, const uint8_t *data, size_t size) | |||||
| if (size % MMU_ROM_BANK_SIZE) | if (size % MMU_ROM_BANK_SIZE) | ||||
| return; | 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) | if (banks > MMU_NUM_ROM_BANKS) | ||||
| 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); | 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) | 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]; | mmu->map_slots[slot] = mmu->rom_banks[bank]; | ||||
| } | } | ||||
| @@ -20,18 +20,6 @@ | |||||
| static size_t header_locations[NUM_LOCATIONS] = {0x7FF0, 0x3FF0, 0x1FF0}; | static size_t header_locations[NUM_LOCATIONS] = {0x7FF0, 0x3FF0, 0x1FF0}; | ||||
| static const char header_magic[MAGIC_LEN + 1] = "TMR SEGA"; | 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 | #ifdef DEBUG_MODE | ||||
| /* | /* | ||||
| DEBUG FUNCTION: Print out the header to stdout. | 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 | #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]; | static char buffer[SIZE_CODE_BUF]; | ||||
| size_t size = size_code_to_bytes(value); | |||||
| if (!size) | if (!size) | ||||
| strncpy(buffer, "Unknown", SIZE_CODE_BUF); | |||||
| strncpy(buffer, "unknown", SIZE_CODE_BUF); | |||||
| else if (size >= (1 << 20)) | else if (size >= (1 << 20)) | ||||
| snprintf(buffer, SIZE_CODE_BUF, "%zu MB", size >> 20); | snprintf(buffer, SIZE_CODE_BUF, "%zu MB", size >> 20); | ||||
| else | else | ||||
| @@ -162,7 +149,8 @@ static bool parse_header(ROM *rom, const uint8_t *header) | |||||
| DEBUG(" - version: %u", rom->version) | DEBUG(" - version: %u", rom->version) | ||||
| DEBUG(" - region code: %u (%s)", rom->region_code, | DEBUG(" - region code: %u (%s)", rom->region_code, | ||||
| rom_region(rom) ? rom_region(rom) : "unknown") | 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; | return true; | ||||
| } | } | ||||
| @@ -191,7 +179,7 @@ static bool find_and_read_header(ROM *rom) | |||||
| return parse_header(rom, header); | return parse_header(rom, header); | ||||
| } | } | ||||
| } | } | ||||
| DEBUG(" - could not find header") | |||||
| DEBUG(" - couldn't find header") | |||||
| return false; | return false; | ||||
| } | } | ||||
| @@ -240,8 +228,8 @@ const char* rom_open(ROM **rom_ptr, const char *path) | |||||
| DEBUG("Loading ROM %s:", rom->name) | DEBUG("Loading ROM %s:", rom->name) | ||||
| // Set rom->size: | // 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); | rom_close(rom); | ||||
| fclose(fp); | fclose(fp); | ||||
| return rom_err_badsize; | return rom_err_badsize; | ||||
| @@ -126,7 +126,7 @@ size_t size_code_to_bytes(uint8_t code) | |||||
| uint8_t size_bytes_to_code(size_t bytes) | uint8_t size_bytes_to_code(size_t bytes) | ||||
| { | { | ||||
| if (bytes & ((1 << 10) - 1)) | 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) { | switch (bytes >> 10) { | ||||
| case 8: return 0xA; | case 8: return 0xA; | ||||