From 821c20eba83ca3ba4a128bf313f089095467732e Mon Sep 17 00:00:00 2001 From: Samuel Walker Date: Fri, 23 May 2025 16:37:55 -0600 Subject: [PATCH] file based save states, and improved file structure --- include/cart.h | 2 ++ include/state.h | 5 ++++- lib/cart.c | 19 +++++++++++++++++-- lib/emu.c | 9 +++++++++ lib/state.c | 41 +++++++++++++++++++++++++++++++++++++++++ lib/ui.c | 6 ++---- 6 files changed, 75 insertions(+), 7 deletions(-) diff --git a/include/cart.h b/include/cart.h index bc5342c..245c30f 100644 --- a/include/cart.h +++ b/include/cart.h @@ -63,6 +63,8 @@ bool cart_load(char *cart); rom_header *get_rom_header(); +cart_context *cart_get_context(); + u8 cart_read(u16 address); void cart_write(u16 address, u8 value); diff --git a/include/state.h b/include/state.h index b5e1401..8563877 100644 --- a/include/state.h +++ b/include/state.h @@ -22,4 +22,7 @@ typedef struct { } save_state; void state_save(save_state*); -void state_load(const save_state*); \ No newline at end of file +void state_load(const save_state*); + +void state_save_file(u8 slot); +void state_load_file(u8 slot); \ No newline at end of file diff --git a/lib/cart.c b/lib/cart.c index c20dcbe..12c46d2 100644 --- a/lib/cart.c +++ b/lib/cart.c @@ -1,6 +1,7 @@ #include #include #include +#include static cart_context ctx; @@ -372,8 +373,11 @@ void cart_write(u16 address, u8 value){ } bool cart_battery_load(){ + char *filename = strrchr(ctx.filename, '\\'); + filename++; char fn[1048]; - sprintf(fn, "%s.battery", ctx.filename); + char *profile = getenv("USERPROFILE"); + sprintf(fn, "%s/Documents/gbemu/saves/%s.battery", profile, filename); FILE *fp = fopen(fn, "rb"); if(!fp) { @@ -386,8 +390,11 @@ bool cart_battery_load(){ } bool cart_battery_save(){ + char *filename = strrchr(ctx.filename, '\\'); + filename++; char fn[1048]; - sprintf(fn, "%s.battery", ctx.filename); + char *profile = getenv("USERPROFILE"); + sprintf(fn, "%s/Documents/gbemu/saves/%s.battery", profile, filename); FILE *fp = fopen(fn, "wb"); if(!fp) { @@ -432,6 +439,10 @@ void cart_load_state(const cart_state* state){ ctx.ram_bank = ctx.ram_banks[0]; } + if(ctx.battery) { + cart_battery_load(); + } + } void cart_save_state(cart_state* state){ @@ -448,4 +459,8 @@ void cart_save_state(cart_state* state){ memcpy((&state->ram_banks[i]), ctx.ram_banks[i], 0x2000); } } +} + +cart_context *cart_get_context(){ + return &ctx; } \ No newline at end of file diff --git a/lib/emu.c b/lib/emu.c index bf4d592..2176c14 100644 --- a/lib/emu.c +++ b/lib/emu.c @@ -87,6 +87,15 @@ int emu_run(int argc, char **argv) { printf("Failed to load ROM file: %s\n", argv[1]); return -2; } + + char fn[1048]; + char *profile = getenv("USERPROFILE"); + sprintf(fn, "%s\\Documents\\gbemu", profile); + CreateDirectory(fn, NULL); + sprintf(fn, "%s\\Documents\\gbemu\\saves", profile); + CreateDirectory(fn, NULL); + sprintf(fn, "%s\\Documents\\gbemu\\states", profile); + CreateDirectory(fn, NULL); printf("Cart loaded..\n"); ctx.app_path = argv[0]; diff --git a/lib/state.c b/lib/state.c index 7adeed6..c396f5d 100644 --- a/lib/state.c +++ b/lib/state.c @@ -1,4 +1,5 @@ #include +#include void state_save(save_state* state) { printf("Saving state\n"); @@ -24,4 +25,44 @@ void state_load(const save_state* state) { audio_load_state(&state->audio); gamepad_load_state(&state->ctlr); cart_load_state(&state->cart); +} + +void state_save_file(u8 slot) { + save_state* state = malloc(sizeof(*state)); + state_save(state); + char *filename = strrchr(cart_get_context()->filename, '\\'); + filename++; + char fn[1048]; + char *profile = getenv("USERPROFILE"); + sprintf(fn, "%s/Documents/gbemu/states/%s", profile, filename); + CreateDirectory(fn, NULL); + sprintf(fn, "%s/Documents/gbemu/states/%s/%d.state", profile, filename, slot); + FILE *fp = fopen(fn, "wb"); + + if(!fp) { + fprintf(stderr, "unable to save state %d\n", slot); + return; + } + + fwrite(state, sizeof(*state), 1, fp); + fclose(fp); +} + +void state_load_file(u8 slot) { + save_state* state = malloc(sizeof(*state)); + char *filename = strrchr(cart_get_context()->filename, '\\'); + filename++; + char fn[1048]; + char *profile = getenv("USERPROFILE"); + sprintf(fn, "%s/Documents/gbemu/states/%s/%d.state", profile, filename, slot); + FILE *fp = fopen(fn, "rb"); + + if(!fp) { + printf("Save slot %d doesnt exist.\n", slot); + return; + } + + fread(state, sizeof(*state), 1, fp); + fclose(fp); + state_load(state); } \ No newline at end of file diff --git a/lib/ui.c b/lib/ui.c index 5254870..ad477ae 100644 --- a/lib/ui.c +++ b/lib/ui.c @@ -25,12 +25,10 @@ SDL_Renderer *sdlDebugRenderer; SDL_Texture *sdlDebugTexture; SDL_Surface *debugScreen; TTF_Font *sans; -save_state *state; static int scale = 4; void ui_init(){ - state = malloc(sizeof(*state)); SDL_Init(SDL_INIT_VIDEO); printf("SDL INIT\n"); TTF_Init(); @@ -344,13 +342,13 @@ void ui_on_key(bool down, u32 key_code) { } if(key_code == SDLK_s && down == true) { emu_stop(); - state_save(state); + state_save_file(0); emu_start(); } if(key_code == SDLK_l && down == true) { emu_stop(); emu_reset(); - state_load(state); + state_load_file(0); emu_start(); } switch(key_code){