Implement state saving and loading for CPU and Bus, add tests for various functionalities

- Added `state.c` to handle saving and loading the state of the CPU and Bus.
- Implemented CRC32 checksum for data integrity verification during state operations.
- Enhanced `README.md` in tests/roms to document new test commands for decimal, interrupt, Apple I, and nestest.
- Created new test files: `run_apple1.c`, `run_decimal.c`, `run_interrupt.c`, `run_nestest.c`, and `run_vectors.c` to validate the new features.
- Updated `run_tests.c` to include tests for state saving/loading and other functionalities.
- Introduced `test_vectors.py` to facilitate downloading and running JSON test vectors for opcode verification.
This commit is contained in:
2026-07-20 13:55:48 +03:00
parent c6e1c5b3b5
commit 0dcd2ed687
29 changed files with 827 additions and 58 deletions
+14
View File
@@ -0,0 +1,14 @@
#ifndef APPLE1_H
#define APPLE1_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "bus.h"
typedef struct {
uint8_t key;bool key_ready;bool stdout_enabled;
char output[8192];size_t output_length;
} Apple1IO;
void apple1_init(Apple1IO *io,Bus6502 *bus);
void apple1_key(Apple1IO *io,uint8_t ascii);
void apple1_enable_stdout(Apple1IO *io,bool enabled);
#endif
+11 -2
View File
@@ -5,13 +5,20 @@
#include <stdint.h>
#include "memory.h"
typedef struct Bus6502 {
typedef struct Bus6502 Bus6502;
typedef bool (*bus_read_hook_t)(void *userdata,uint16_t addr,uint8_t *value);
typedef bool (*bus_write_hook_t)(void *userdata,uint16_t addr,uint8_t value);
struct Bus6502 {
Memory memory;
uint8_t keyboard;
uint32_t rng_state;
bool easy6502_io;
bool framebuffer_dirty;
} Bus6502;
bus_read_hook_t read_hook;
bus_write_hook_t write_hook;
void *hook_userdata;
};
void bus_init(Bus6502 *bus);
uint8_t bus_read(Bus6502 *bus, uint16_t addr);
@@ -20,5 +27,7 @@ uint16_t bus_read16(Bus6502 *bus, uint16_t addr);
void bus_write16(Bus6502 *bus, uint16_t addr, uint16_t value);
void bus_set_keyboard(Bus6502 *bus, uint8_t key);
void bus_seed_rng(Bus6502 *bus, uint32_t seed);
void bus_set_hooks(Bus6502 *bus,bus_read_hook_t read_hook,
bus_write_hook_t write_hook,void *userdata);
#endif
+1
View File
@@ -13,6 +13,7 @@ typedef struct CPU6502 {
uint8_t P;
bool nmi_pending;
bool irq_asserted;
bool decimal_enabled;
} CPU6502;
enum {
+28
View File
@@ -0,0 +1,28 @@
#ifndef NES_H
#define NES_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "bus.h"
#include "cpu.h"
typedef struct {
uint8_t prg[512*1024],chr[256*1024],ram[2048],prg_ram[8192];
uint8_t nametable[4096],palette[32],oam[256];
size_t prg_size,chr_size;uint8_t mapper,prg_bank,chr_bank,mirroring;bool chr_ram;
uint8_t ppu_ctrl,ppu_mask,ppu_status,oam_addr,ppu_latch,read_buffer;
uint8_t scroll_x,scroll_y;
uint16_t ppu_addr;unsigned ppu_dot,ppu_scanline;bool frame_ready;
uint8_t controller,controller_shift;bool controller_strobe;
uint8_t apu_reg[0x18],apu_status;uint64_t apu_cycles;
double pulse_phase[2],triangle_phase,noise_phase;uint16_t noise_lfsr;
Bus6502 bus;CPU6502 cpu;
} NES;
int nes_load(NES *nes,const char *path);
void nes_reset(NES *nes);
cpu_step_result_t nes_step(NES *nes);
void nes_set_controller(NES *nes,uint8_t buttons);
void nes_render_frame(NES *nes,uint32_t pixels[256*240]);
float nes_audio_sample(NES *nes,double sample_rate);
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifndef STATE_H
#define STATE_H
#include "bus.h"
#include "cpu.h"
int state_save(const char *path,const CPU6502 *cpu,const Bus6502 *bus);
int state_load(const char *path,CPU6502 *cpu,Bus6502 *bus);
#endif