diff --git a/CMakeLists.txt b/CMakeLists.txt index 1655cee..3b8ec2e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -140,6 +140,7 @@ if (NOT EMSCRIPTEN) else (EMSCRIPTEN) add_executable(binjgb src/memory.c + src/common.c src/emulator.c src/joypad.c src/rewind.c diff --git a/src/common.c b/src/common.c index 457ba8d..52f3b0c 100644 --- a/src/common.c +++ b/src/common.c @@ -33,6 +33,7 @@ static Result get_file_size(FILE* f, long* out_size) { ON_ERROR_RETURN; } +#ifndef __wasm__ Result file_read(const char* filename, FileData* out_file_data) { return file_read_aligned(filename, 1, out_file_data); } @@ -63,6 +64,16 @@ Result file_write(const char* filename, const FileData* file_data) { return OK; ON_ERROR_CLOSE_FILE_AND_RETURN; } +#endif + +void file_data_resize(FileData* file_data, size_t new_size) { + size_t old_size = file_data->size; + file_data->data = xrealloc(file_data->data, new_size); + if (new_size > old_size) { + memset(file_data->data + old_size, 0, new_size - old_size); + } + file_data->size = new_size; +} void file_data_delete(FileData* file_data) { xfree(file_data->data); diff --git a/src/common.h b/src/common.h index dbd522e..9513ba9 100644 --- a/src/common.h +++ b/src/common.h @@ -108,9 +108,12 @@ typedef struct JoypadButtons { } JoypadButtons; const char* replace_extension(const char* filename, const char* extension); +#ifndef __wasm__ Result file_read(const char* filename, FileData* out); Result file_read_aligned(const char* filename, size_t align, FileData* out); Result file_write(const char* filename, const FileData*); +#endif +void file_data_resize(FileData*, size_t new_size); void file_data_delete(FileData*); #ifdef __cplusplus diff --git a/src/emscripten/wrapper.c b/src/emscripten/wrapper.c index a0b3271..6ffc9e7 100644 --- a/src/emscripten/wrapper.c +++ b/src/emscripten/wrapper.c @@ -185,11 +185,6 @@ size_t get_file_data_size(FileData* file_data) { return file_data->size; } -void file_data_delete(FileData* file_data) { - xfree(file_data->data); - xfree(file_data); -} - void set_log_apu_writes(Emulator* e, Bool set) { s_config.log_apu_writes = set; emulator_set_config(e, &s_config); diff --git a/src/emulator.c b/src/emulator.c index 215b13d..7985bb7 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -1120,7 +1120,8 @@ static void set_cart_info(Emulator* e, u8 index) { } static Result get_cart_info(FileData* file_data, size_t offset, - CartInfo* cart_info, Bool require_logo_checksum) { + CartInfo* cart_info, Bool require_logo_checksum, + size_t* max_file_size) { /* Simple checksum on logo data so we don't have to include it here. :) */ u8* data = file_data->data + offset; size_t i; @@ -1159,38 +1160,46 @@ static Result get_cart_info(FileData* file_data, size_t offset, } u32 rom_byte_size = s_rom_bank_count[cart_info->rom_size] << ROM_BANK_SHIFT; - cart_info->size = rom_byte_size; - CHECK_MSG(file_data->size >= offset + rom_byte_size, - "File size too small (required %ld, got %ld)\n", - (long)(offset + rom_byte_size), (long)file_data->size); + *max_file_size = MAX(*max_file_size, offset + rom_byte_size); return OK; ON_ERROR_RETURN; } static Result get_cart_infos(Emulator* e) { + size_t file_size = e->file_data.size; + size_t max_file_size = file_size; u32 i; for (i = 0; i < MAX_CART_INFOS; ++i) { size_t offset = i << CART_INFO_SHIFT; if (offset + MINIMUM_ROM_SIZE > e->file_data.size) break; - if (SUCCESS( - get_cart_info(&e->file_data, offset, &e->cart_infos[i], TRUE))) { + if (SUCCESS(get_cart_info(&e->file_data, offset, &e->cart_infos[i], TRUE, + &max_file_size))) { if (s_cart_type_info[e->cart_infos[i].cart_type].mbc_type == MBC_TYPE_MMM01) { /* MMM01 has the cart header at the end. */ - set_cart_info(e, i); - return OK; + goto done; } e->cart_info_count++; } } // Maybe the logo checksum failed; try again without it required. if (e->cart_info_count == 0 && - SUCCESS(get_cart_info(&e->file_data, 0, &e->cart_infos[0], FALSE))) { + SUCCESS(get_cart_info(&e->file_data, 0, &e->cart_infos[0], FALSE, + &max_file_size))) { e->cart_info_count++; } CHECK_MSG(e->cart_info_count != 0, "Invalid ROM.\n"); - set_cart_info(e, 0); + i = 0; +done: + if (max_file_size > file_size) { + file_data_resize(&e->file_data, max_file_size); + // Fix cart_info data pointers. + for (u32 j = 0; j < e->cart_info_count; ++j) { + e->cart_infos[j].data = e->file_data.data + e->cart_infos[j].offset; + } + } + set_cart_info(e, i); return OK; ON_ERROR_RETURN; } @@ -4970,6 +4979,7 @@ Result emulator_write_ext_ram(Emulator* e, FileData* file_data) { ON_ERROR_RETURN; } +#ifndef __wasm__ Result emulator_read_ext_ram_from_file(Emulator* e, const char* filename) { if (EXT_RAM.battery_type != BATTERY_TYPE_WITH_BATTERY) return OK; @@ -5023,6 +5033,7 @@ Result emulator_write_state_to_file(Emulator* e, const char* filename) { file_data_delete(&file_data); return result; } +#endif Emulator* emulator_new(const EmulatorInit* init) { Emulator* e = xcalloc(1, sizeof(Emulator)); @@ -5039,6 +5050,7 @@ Emulator* emulator_new(const EmulatorInit* init) { void emulator_delete(Emulator* e) { if (e) { xfree(e->audio_buffer.data); + file_data_delete(&e->file_data); xfree(e); } } diff --git a/src/emulator.h b/src/emulator.h index e624499..6d40ed4 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -231,10 +231,12 @@ Result emulator_write_state(Emulator*, FileData*); Result emulator_read_ext_ram(Emulator*, const FileData*); Result emulator_write_ext_ram(Emulator*, FileData*); +#ifndef __wasm__ Result emulator_read_state_from_file(Emulator*, const char* filename); Result emulator_write_state_to_file(Emulator*, const char* filename); Result emulator_read_ext_ram_from_file(Emulator*, const char* filename); Result emulator_write_ext_ram_to_file(Emulator*, const char* filename); +#endif EmulatorEvent emulator_step(Emulator*); EmulatorEvent emulator_run_until(Emulator*, Ticks until_ticks); diff --git a/src/memory.c b/src/memory.c index c19f865..ef3d6d4 100644 --- a/src/memory.c +++ b/src/memory.c @@ -20,6 +20,13 @@ void* xmalloc_(const char* file, int line, size_t size) { return p; } +void* xrealloc_(const char* file, int line, void* p, size_t size) { + void* newp = realloc(size); + printf("%s:%d: %s(%p, %" PRIu64 ") => %p\n", file, line, __func__, p, + (uint64_t)size, newp); + return newp; +} + void xfree_(const char* file, int line, void* p) { printf("%s:%d: %s(%p)\n", file, line, __func__, p); free(p); diff --git a/src/memory.h b/src/memory.h index a62c5ed..7a0357b 100644 --- a/src/memory.h +++ b/src/memory.h @@ -19,12 +19,14 @@ extern "C" { #if TRACE_MEMORY #define xmalloc(size) xmalloc_(__FILE__, __LINE__, size) +#define xrealloc(size) xrealloc_(__FILE__, __LINE__, p, size) #define xfree(p) xfree_(__FILE__, __LINE__, p) #define xcalloc(count, size) xcalloc_(__FILE__, __LINE__, count, size) #define xstrdup(s) xstrdup_(__FILE__, __LINE__, s) /* Use these instead to make it easier to track memory usage. */ void* xmalloc_(const char* file, int line, size_t); +void* xrealloc_(const char* file, int line, void*, size_t); void xfree_(const char* file, int line, void*); void* xcalloc_(const char* file, int line, size_t, size_t); char* xstrdup_(const char* file, int line, const char*); @@ -32,6 +34,7 @@ char* xstrdup_(const char* file, int line, const char*); #else #define xmalloc malloc +#define xrealloc realloc #define xfree free #define xcalloc calloc #define xstrdup strdup