Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Save state #6

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions lib/cpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,28 @@ CPU::CPU(Memory* memory)
this->memory = memory;
}

void CPU::dump_state(cpu_state* state) const
{
memcpy(state->registers, this->registers, 6*sizeof(uint16_t));
state->halted = this->halted;
state->divider_cycle_count = this->divider_cycle_count;
state->timer_cycle_count = this->timer_cycle_count;

state->ime = this->ime;
state->ime_scheduled = this->ime_scheduled;
}

void CPU::load_state(const cpu_state* const state)
{
memcpy(this->registers, state->registers, 6 * sizeof(uint16_t));
this->halted = state->halted ;
this->divider_cycle_count = state->divider_cycle_count ;
this->timer_cycle_count = state->timer_cycle_count ;

this->ime = state->ime ;
this->ime_scheduled = state->ime_scheduled;
}

void CPU::reset()
{
memset(registers, 0, 12);
Expand Down
14 changes: 14 additions & 0 deletions lib/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,20 @@ class CPU
void init();
uint8_t step();

struct cpu_state {
uint16_t registers[6];
uint8_t divider_cycle_count;
uint16_t timer_cycle_count;

bool ime;
bool ime_scheduled;

bool halted;
};

void dump_state(cpu_state* state) const;
void load_state(const cpu_state* const state);

bool is_double_speed();
};

Expand Down
14 changes: 14 additions & 0 deletions lib/emulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,20 @@ void Emulator::set_rom_file(std::string filename)
//reset();
}

void Emulator::save_state()
{
memory.dump_state(&quick_savestate.mem_state);
cpu.dump_state(&quick_savestate.cpu_state);
gpu.dump_state(&quick_savestate.gpu_state);

}

void Emulator::load_state(){
memory.load_state(&quick_savestate.mem_state);
cpu.load_state(&quick_savestate.cpu_state);
gpu.load_state(&quick_savestate.gpu_state);
}

bool Emulator::is_running() const
{
return state == emu_state::RUNNING;
Expand Down
13 changes: 13 additions & 0 deletions lib/emulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ class EMULATOR_API Emulator

friend class Debug_Display;

public:
struct save_state
{
Memory::memory_state mem_state;
CPU::cpu_state cpu_state;
GPU::gpu_state gpu_state;
};

private:

enum class emu_state : uint8_t {
Expand All @@ -47,6 +55,8 @@ class EMULATOR_API Emulator
GPU gpu;
Sound apu;

save_state quick_savestate;

uint8_t frame_count;

uint8_t serial_byte;
Expand Down Expand Up @@ -87,6 +97,9 @@ class EMULATOR_API Emulator

void set_rom_file(std::string filename);

void save_state();
void load_state();

//state functions
bool is_running() const;
bool is_exiting() const;
Expand Down
16 changes: 16 additions & 0 deletions lib/gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ PaletteData* const GPU::get_palette_data()
return cgb_palettes;
}

void GPU::dump_state(gpu_state *state) const
{
memcpy(state->cgb_palettes, this->cgb_palettes, 2* sizeof(PaletteData));
memcpy(state->pixels, this->pixels, sizeof(this->pixels));
memcpy(state->bg_color_prio_line, this->bg_color_prio_line, sizeof(this->bg_color_prio_line));
state->clock_counter = this->clock_counter;
}

void GPU::load_state(const gpu_state *const state)
{
memcpy(this->cgb_palettes, state->cgb_palettes, 2 * sizeof(PaletteData));
memcpy(this->pixels, state->pixels, sizeof(this->pixels));
memcpy(this->bg_color_prio_line, state->bg_color_prio_line, sizeof(this->bg_color_prio_line));
this->clock_counter = state->clock_counter;
}

void GPU::step(uint8_t cycles)
{
uint8_t stat_val = memory->read_8bits(STAT) | 0x80;
Expand Down
10 changes: 10 additions & 0 deletions lib/gpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ class GPU
GPU(Memory* memory);
~GPU();

struct gpu_state{
PaletteData cgb_palettes[2];
uint32_t pixels[LCD_HEIGHT][LCD_WIDTH];
uint16_t clock_counter;
uint8_t bg_color_prio_line[LCD_WIDTH];
};

void dump_state(gpu_state* state) const;
void load_state(const gpu_state* const state);

void step(uint8_t cycles);

const uint32_t* get_pixel_data() const;
Expand Down
23 changes: 23 additions & 0 deletions lib/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,29 @@ void Memory::load_content(std::istream &file)
}
}

void Memory::dump_state(memory_state *state) const
{
memcpy(state->mmap, this->mmap, MEMSIZE);
state->is_cgb = this->is_cgb;

if(this->is_cgb){
memcpy(state->vram_banks, this->vram_banks, 2* VRAM_BANK_SIZE);
memcpy(state->wram_banks, this->wram_banks, 7* WRAM_BANK_SIZE);
}
}

void Memory::load_state(const memory_state *const state)
{
memcpy(this->mmap, state->mmap, MEMSIZE);
this->is_cgb = state->is_cgb;

if (this->is_cgb)
{
memcpy(this->vram_banks, state->vram_banks, 2 * VRAM_BANK_SIZE);
memcpy(this->wram_banks, state->wram_banks, 7 * WRAM_BANK_SIZE);
}
}

void Memory::load_content(const uint8_t* data, uint32_t size)
{
memcpy(mmap, data, size);
Expand Down
10 changes: 10 additions & 0 deletions lib/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,16 @@ class Memory

void reset();

struct memory_state{
uint8_t mmap[MEMSIZE];
bool is_cgb;
uint8_t vram_banks[2 * VRAM_BANK_SIZE];
uint8_t wram_banks[7 * VRAM_BANK_SIZE];
};

void dump_state(memory_state* state) const;
void load_state(const memory_state* const state);

void load_content(std::istream &file);
void load_content(const uint8_t* data, uint32_t size);

Expand Down
21 changes: 21 additions & 0 deletions src/debug_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ static uint16_t sample_offset = 0;
static GLuint bg_full;
static GLuint bg_tiles[2];
static GLuint screen;
static GLuint quicksave_preview;

static MemoryEditor mem_edit;
static MemoryEditor mem_edit2;
Expand Down Expand Up @@ -118,6 +119,7 @@ Debug_Display::Debug_Display(Emulator &emu)
bg_tiles[0] = 0;
bg_tiles[1]= 0;
screen = 0;
quicksave_preview = 0;

hqxInit();
}
Expand Down Expand Up @@ -598,6 +600,25 @@ void Debug_Display::update(const uint32_t *pixels)
ImGui::TreePop();
}

if(ImGui::TreeNode("Quick Save")){
if(ImGui::Button("Save"))
{
emu.save_state();
}
ImGui::SameLine();
if(ImGui::Button("Restore"))
{
emu.load_state();
}

LoadTextureFromPixels((const uint32_t*)&emu.quick_savestate.gpu_state.pixels[0], &quicksave_preview, LCD_WIDTH, LCD_HEIGHT);
float ratio = (ImGui::GetWindowWidth() * 0.8f)/LCD_WIDTH;
ImGui::Image((void *)(intptr_t)quicksave_preview, ImVec2(LCD_WIDTH * ratio, LCD_HEIGHT * ratio));

ImGui::TreePop();
}


ImGui::End();
}

Expand Down
6 changes: 6 additions & 0 deletions src/sdl_display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,12 @@ bool SDL_Display::handle_events(Emulator &emu)
options.debug_ui = !options.debug_ui;
options.display_changed = true;
break;
case SDL_SCANCODE_F2:
emu.save_state();
break;
case SDL_SCANCODE_F3:
emu.load_state();
break;
case SDL_SCANCODE_R:
emu.reset();
break;
Expand Down