Skip to content

Commit

Permalink
Allow for ROM files smaller than header indicates
Browse files Browse the repository at this point in the history
See #43 and #49. This will resize the ROM and pad with 0.
  • Loading branch information
binji committed Sep 15, 2023
1 parent 178e214 commit 7275f65
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 16 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 0 additions & 5 deletions src/emscripten/wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
34 changes: 23 additions & 11 deletions src/emulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand All @@ -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);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 7 additions & 0 deletions src/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions src/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,22 @@ 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*);

#else

#define xmalloc malloc
#define xrealloc realloc
#define xfree free
#define xcalloc calloc
#define xstrdup strdup
Expand Down

0 comments on commit 7275f65

Please sign in to comment.