diff --git a/Makefile b/Makefile index 6ea40ff..42bb8d0 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ PFLAGS += -g #PFLAGS += -DDEBUG_APU #PFLAGS += -DDEBUG_INPUT #PFLAGS += -DE6502_DEBUG -#PFLAGS += -DE6502_ILLEGAL +PFLAGS += -DE6502_ILLEGAL CFLAGS += $(PFLAGS) -Wall -Werror -Wshadow -Wunused -I../ -Isrc/ CFLAGS += -Iinc/$(PLATFORM)/SDL2 LDFLAGS += $(PFLAGS) diff --git a/src/map/cnrom.c b/src/map/cnrom.c index 9d63c3a..aa3764b 100644 --- a/src/map/cnrom.c +++ b/src/map/cnrom.c @@ -96,7 +96,7 @@ static int cnrom_state_size(const void* _map) { return (sizeof(map->bank) + sizeof(map->vram)); } -static int cnrom_state_read(void* _map, const void* data) { +static int cnrom_state_read(void* _map, const void* data, int len) { cnrom_mapper* map = (cnrom_mapper*)_map; const void* ptr = data; @@ -111,7 +111,7 @@ static int cnrom_state_read(void* _map, const void* data) { return (ptr - data); } -static int cnrom_state_write(const void* _map, void* data) { +static int cnrom_state_write(const void* _map, void* data, int len) { cnrom_mapper* map = (cnrom_mapper*)_map; void* ptr = data; diff --git a/src/map/mmc1.c b/src/map/mmc1.c index 29b9e25..abc5e8b 100644 --- a/src/map/mmc1.c +++ b/src/map/mmc1.c @@ -15,9 +15,11 @@ typedef struct { uint8_t* chr_bank[2]; uint8_t* vram_bank[4]; uint8_t* prg_bank[2]; - uint8_t* chr_ram; uint8_t* chr; + int chr_bank_offset[2]; + int chr_ram_lim; + uint8_t reg_shift; uint8_t reg_n_shift; uint8_t reg_control; @@ -27,6 +29,8 @@ typedef struct { uint8_t vram[2][nes_vram_page_size]; uint8_t wram[nes_mem_wram_size]; + + uint8_t chr_ram[]; } mmc1_mapper; @@ -55,21 +59,22 @@ static void mmc1_update_vram(mmc1_mapper* map) { } static void mmc1_update_chr(mmc1_mapper* map) { - // CHR RAM selection + int banks[2] = {0}; if (!(map->reg_control & 0b10000)) { - int bank = (map->reg_chr_0 & 0b11110); - MAP_LOG("CHR: 8 KB: %d + %d", bank, bank + 1); - map->chr_bank[0] = &map->chr[ bank * - nes_chr_page_size]; - map->chr_bank[1] = &map->chr[ (bank + 1) * - nes_chr_page_size]; + banks[0] = (map->reg_chr_0 & 0b11110); + banks[1] = banks[0] + 1; } else { - MAP_LOG("CHR: %d + %d", map->reg_chr_0, map->reg_chr_1); - map->chr_bank[0] = &map->chr[ map->reg_chr_0 * - nes_chr_page_size]; - map->chr_bank[1] = &map->chr[ map->reg_chr_1 * - nes_chr_page_size]; + banks[0] = map->reg_chr_0; + banks[1] = map->reg_chr_1; } + + MAP_LOG("CHR: %d + %d", banks[0], banks[1]); + + map->chr_bank_offset[0] = banks[0] * nes_chr_page_size; + map->chr_bank_offset[1] = banks[1] * nes_chr_page_size; + + map->chr_bank[0] = &map->chr[map->chr_bank_offset[0]]; + map->chr_bank[1] = &map->chr[map->chr_bank_offset[1]]; } static void mmc1_update_prg(mmc1_mapper* map) { @@ -103,20 +108,22 @@ static void mmc1_reset(void* data) { } static void* mmc1_init(nes_mapper* nes_map, nes_cart* cart) { - mmc1_mapper* map = calloc(1, sizeof(mmc1_mapper)); + int chr_ram_size = ( cart->chr_rom_banks > 0 ? + 0 : 128 * 1024); + mmc1_mapper* map = calloc(1, sizeof(mmc1_mapper) + + chr_ram_size); if (NULL != map) { map->prg_rom = cart->prg_rom; map->prg_rom_banks = cart->prg_rom_banks; map->chr_rom_banks = cart->chr_rom_banks / 2; if (map->chr_rom_banks > 0) { map->chr_rom = cart->chr_rom; - map->chr_ram = NULL; map->chr = map->chr_rom; } else { map->chr_rom = NULL; - map->chr_ram = calloc(32, nes_chr_page_size); map->chr = map->chr_ram; } + map->chr_ram_lim = 0; map->battery = !!(cart->flags & Cart_Flag_Battery); @@ -126,10 +133,7 @@ static void* mmc1_init(nes_mapper* nes_map, nes_cart* cart) { } static void mmc1_done(void* data) { - if (NULL != data) { - free(((mmc1_mapper*)data)->chr_ram); - free(data); - } + free(data); } static inline uint8_t* mmc1_prg_addr(mmc1_mapper* map, @@ -207,7 +211,11 @@ static uint8_t* mmc1_chr_addr(void* data, uint16_t addr) { static void mmc1_chr_write(void* data, uint16_t addr, uint8_t val) { - if (NULL != ((mmc1_mapper*)data)->chr_ram) { + mmc1_mapper* map = (mmc1_mapper*)data; + if (NULL == map->chr_rom) { + int pos = map->chr_bank_offset[(addr >> 12) & 1] + + (addr & 0xFFFU); + if (pos >= map->chr_ram_lim) map->chr_ram_lim = pos + 1; *(mmc1_chr_addr(data, addr)) = val; } } @@ -233,17 +241,27 @@ static int mmc1_sram_size(void* data) { /* Save State */ +static inline int mmc1_chr_ram_size(const mmc1_mapper* map) { + return (map->chr_rom_banks <= 0 ? (128 * 1024) : 0); +} + static int mmc1_state_size(const void* _map) { mmc1_mapper* map = (mmc1_mapper*)_map; - return ( (void*)map + + + return ( map->chr_ram_lim + + (void*)map + sizeof(*map) - (void*)&(map->reg_shift)); } -static int mmc1_state_read(void* _map, const void* data) { +static int mmc1_state_read(void* _map, const void* data, + int data_len) { mmc1_mapper* map = (mmc1_mapper*)_map; - int size = mmc1_state_size(_map); + int base_size = mmc1_state_size(map) - map->chr_ram_lim; + int size = base_size + mmc1_chr_ram_size(map); + if (size > data_len) size = data_len; + map->chr_ram_lim = data_len - base_size; memcpy(&(map->reg_shift), data, size); mmc1_update_prg(map); @@ -253,9 +271,11 @@ static int mmc1_state_read(void* _map, const void* data) { return size; } -static int mmc1_state_write(const void* _map, void* data) { +static int mmc1_state_write(const void* _map, void* data, + int data_len) { mmc1_mapper* map = (mmc1_mapper*)_map; int size = mmc1_state_size(_map); + if (size > data_len) size = data_len; memcpy(data, &(map->reg_shift), size); return size; } diff --git a/src/map/mmc3.c b/src/map/mmc3.c index 6b7e97d..41d1268 100644 --- a/src/map/mmc3.c +++ b/src/map/mmc3.c @@ -32,6 +32,9 @@ typedef struct { uint8_t* chr_bank[8]; // 1 KB uint8_t* vram_bank[4]; + int chr_bank_offset[8]; + int chr_ram_lim; + uint8_t r[8]; uint8_t flags; uint8_t bank_select; @@ -40,6 +43,7 @@ typedef struct { uint8_t wram[nes_mem_wram_size]; uint8_t vram[2][nes_vram_page_size]; + uint8_t chr_ram[]; } mmc3_mapper; static inline uint8_t* mmc3_prg_bank(mmc3_mapper* map, int bank) { @@ -79,6 +83,8 @@ static inline void mmc3_map_2k_chr(mmc3_mapper* map, MAP_LOG("CHR ROM: 2k $%04x <- bank %d + %d", reg << 10, bank, bank | 1); map->chr_bank[reg + 0] = mmc3_chr_bank(map, bank); map->chr_bank[reg + 1] = mmc3_chr_bank(map, bank | 1); + map->chr_bank_offset[reg + 0] = map->chr_bank[reg + 0] - map->chr_rom; + map->chr_bank_offset[reg + 1] = map->chr_bank[reg + 1] - map->chr_rom; } static inline void mmc3_map_1k_chr(mmc3_mapper* map, @@ -89,6 +95,7 @@ static inline void mmc3_map_1k_chr(mmc3_mapper* map, } MAP_LOG("CHR ROM: 1k $%04x <- bank %d", reg << 10, bank); map->chr_bank[reg] = mmc3_chr_bank(map, bank); + map->chr_bank_offset[reg] = map->chr_bank[reg] - map->chr_rom; } static inline void mmc3_update_chr(mmc3_mapper* map, @@ -159,7 +166,10 @@ static void mmc3_reset(void* data) { } static void* mmc3_init(nes_mapper* nes_map, nes_cart* cart) { - mmc3_mapper* map = calloc(1, sizeof(mmc3_mapper)); + int chr_ram_size = ( cart->chr_rom_banks <= 0 ? + (256 * 1024) : 0); + mmc3_mapper* map = calloc(1, sizeof(mmc3_mapper) + + chr_ram_size); if (NULL != map) { map->mapper = nes_map; map->flags = (cart->flags & Cart_Flag_Horizontal) ? @@ -167,7 +177,7 @@ static void* mmc3_init(nes_mapper* nes_map, nes_cart* cart) { map->prg_rom = cart->prg_rom; map->prg_rom_banks = cart->prg_rom_banks * 2; if (cart->chr_rom_banks <= 0) { - map->chr_rom = calloc(1024, 256); + map->chr_rom = map->chr_ram; map->chr_rom_banks = 256; map->flags |= mmc3_Flag_CHR_RAM; } else { @@ -188,13 +198,7 @@ static void* mmc3_init(nes_mapper* nes_map, nes_cart* cart) { } static void mmc3_done(void* data) { - mmc3_mapper* map = (mmc3_mapper*)data; - if (NULL != map) { - if (map->flags & mmc3_Flag_CHR_RAM) { - free(map->chr_rom); - } - free(map); - } + free(data); } static inline uint8_t* mmc3_prg_addr(mmc3_mapper* map, @@ -328,7 +332,10 @@ static void mmc3_chr_write(void* data, uint16_t addr, uint8_t val) { mmc3_mapper* map = (mmc3_mapper*)data; if (map->flags & mmc3_Flag_CHR_RAM) { - *(mmc3_chr_addr(data, addr)) = val; + uint8_t* ptr = mmc3_chr_addr(data, addr); + int pos = (ptr - map->chr_ram); + if (pos >= map->chr_ram_lim) map->chr_ram_lim = pos + 1; + *ptr = val; } // MAP_LOG("CHR ROM Write: $%04x < %02x\n", addr, val); } @@ -349,17 +356,27 @@ static int mmc3_sram_size(void* data) { /* Save State */ +static inline int mmc3_chr_ram_size(const mmc3_mapper* map) { + return ( (map->flags & mmc3_Flag_CHR_RAM) ? + (256 * 1024) : 0); +} + static int mmc3_state_size(const void* data) { const mmc3_mapper* map = (mmc3_mapper*)data; return ( (map->wram - map->r) + sizeof(map->wram) + - sizeof(map->vram)); + sizeof(map->vram) + + map->chr_ram_lim); } -static int mmc3_state_read(void* _map, const void* data) { +static int mmc3_state_read(void* _map, const void* data, + int data_len) { mmc3_mapper* map = (mmc3_mapper*)_map; - int size = mmc3_state_size(_map); + int base_size = mmc3_state_size(map) - map->chr_ram_lim; + int size = base_size + mmc3_chr_ram_size(map); + if (size > data_len) size = data_len; + map->chr_ram_lim = data_len - base_size; memcpy(map->r, data, size); uint8_t new_bank_select = map->bank_select; @@ -371,9 +388,11 @@ static int mmc3_state_read(void* _map, const void* data) { return size; } -static int mmc3_state_write(const void* _map, void* data) { +static int mmc3_state_write(const void* _map, void* data, + int data_len) { mmc3_mapper* map = (mmc3_mapper*)_map; int size = mmc3_state_size(_map); + if (size > data_len) size = data_len; memcpy(data, map->r, size); return size; } diff --git a/src/map/nrom.c b/src/map/nrom.c index 49e37de..e53a854 100644 --- a/src/map/nrom.c +++ b/src/map/nrom.c @@ -10,20 +10,24 @@ typedef struct { uint8_t* chr_rom; int chr_rom_banks; uint8_t mirror; + uint8_t vram[nes_vram_page_size * 2]; uint8_t wram[nes_mem_wram_size]; + uint8_t chr_ram[]; } nrom_mapper; static void nrom_reset(void* data) {} static void* nrom_init(nes_mapper* nes_map, nes_cart* cart) { - nrom_mapper* map = calloc(1, sizeof(nrom_mapper)); + int chr_ram_size = (cart->chr_rom_banks <= 0 ? 8192U : 0); + nrom_mapper* map = calloc(1, sizeof(nrom_mapper) + + chr_ram_size); if (NULL != map) { map->prg_rom = cart->prg_rom; map->prg_rom_banks = cart->prg_rom_banks; if (cart->chr_rom_banks <= 0) { - map->chr_rom = calloc(8, 1024); + map->chr_rom = map->chr_ram; } else { map->chr_rom = cart->chr_rom; } @@ -97,23 +101,29 @@ static void nrom_chr_write(void* data, /* Save State */ +static inline int nrom_chr_ram_size(const nrom_mapper* map) { + return (map->chr_rom_banks <= 0 ? (8 * 1024) : 0); +} + static int nrom_state_size(const void* _map) { nrom_mapper* map = (nrom_mapper*)_map; - return (sizeof(map->vram) + sizeof(map->wram)); + return ( sizeof(map->vram) + sizeof(map->wram) + + nrom_chr_ram_size(map)); } -static int nrom_state_read(void* _map, const void* data) { +static int nrom_state_read(void* _map, const void* data, int len) { nrom_mapper* map = (nrom_mapper*)_map; - memcpy(map->vram, data, sizeof(map->vram)); - memcpy(map->wram, data + sizeof(map->vram), sizeof(map->wram)); - return (sizeof(map->vram) + sizeof(map->wram)); + int max_size = nrom_state_size(_map); + if (max_size > len) max_size = len; + memcpy(map->vram, data, max_size); + return max_size; } -static int nrom_state_write(const void* _map, void* data) { +static int nrom_state_write(const void* _map, void* data, int len) { nrom_mapper* map = (nrom_mapper*)_map; - memcpy(data, map->vram, sizeof(map->vram)); - memcpy(data + sizeof(map->vram), map->wram, sizeof(map->wram)); - return (sizeof(map->vram) + sizeof(map->wram)); + int size = nrom_state_size(_map); + memcpy(data, map->vram, size); + return size; } diff --git a/src/map/uxrom.c b/src/map/uxrom.c index 4dbad8e..b915c9d 100644 --- a/src/map/uxrom.c +++ b/src/map/uxrom.c @@ -97,7 +97,7 @@ int uxrom_state_size(const void* _map) { sizeof(map->chr_ram)); } -int uxrom_state_read(void* _map, const void* data) { +int uxrom_state_read(void* _map, const void* data, int len) { uxrom_mapper* map = (uxrom_mapper*)_map; const void* ptr = data; @@ -113,7 +113,7 @@ int uxrom_state_read(void* _map, const void* data) { return (ptr - data); } -int uxrom_state_write(const void* _map, void* data) { +int uxrom_state_write(const void* _map, void* data, int len) { uxrom_mapper* map = (uxrom_mapper*)_map; void* ptr = data; diff --git a/src/mapper.h b/src/mapper.h index 8a13eec..3df3c49 100644 --- a/src/mapper.h +++ b/src/mapper.h @@ -33,8 +33,8 @@ typedef struct nes_mapper_t { int (*sram_size)(void*); int (*state_size)(const void* map); - int (*state_read)(void* map, const void* data); - int (*state_write)(const void* map, void* data); + int (*state_read)(void* map, const void* data, int len); + int (*state_write)(const void* map, void* data, int len); } nes_mapper; static inline void* nes_map_init(nes_mapper* map, diff --git a/src/save.c b/src/save.c index adfb76f..826be96 100644 --- a/src/save.c +++ b/src/save.c @@ -76,7 +76,13 @@ int load_state(nes* sys, const char* cart_filename) { FILE* file = fopen(state_filename, "rb"); if (NULL != file) { - int file_size = state_size(sys); +// int expected_size = state_size(sys); + + fseek(file, 0L, SEEK_END); + int file_size = ftell(file); +// rewind(file); +// if (max_size < size) size = max_size; + void* mem = map_file(file, file_size, Filemap_Mode_Read); if (NULL != mem) { @@ -278,9 +284,9 @@ int state_write(const nes* sys, void* mem, int size) { const nes_mapper* mapper = sys->cart.mapper; const void* map_data = sys->cart.map_data; - ptr = write_header(ptr, tag_mapper, - mapper->state_size(map_data)); - ptr += mapper->state_write(map_data, ptr); + int state_size = mapper->state_size(map_data); + ptr = write_header(ptr, tag_mapper, state_size); + ptr += mapper->state_write(map_data, ptr, state_size); return (ptr - mem); } @@ -342,7 +348,7 @@ int state_read(nes* sys, const void* mem, int mem_size) { } else if (tag_mapper == tag) { n_read = sys->cart.mapper->state_read( - sys->cart.map_data, ptr + sys->cart.map_data, ptr, size ); loaded |= Component_Mapper; @@ -395,3 +401,29 @@ int state_read(nes* sys, const void* mem, int mem_size) { return result; } + +/* +// Chunking + +int write_chunks(void* dst, int dst_len, const void* src, + const nese_io_chunk* chunks, int n_chunks) { + void* ptr = dst; + for ( void* end = dst + dst_len; + n_chunks > 0 && ptr < end; + ptr += chunks->size, --n_chunks, ++chunks) { + memcpy(ptr, src + chunks->offset, chunks->size); + } + return (ptr - dst); +} + +int read_chunks(const void* src, int src_len, void* dst, + const nese_io_chunk* chunks, int n_chunks) { + const void* ptr = src; + for ( const void* end = src + src_len; + n_chunks > 0 && ptr < end; + ptr += chunks->size, --n_chunks, ++chunks) { + memcpy(dst + chunks->offset, ptr, chunks->size); + } + return (ptr - dst); +} +*/ diff --git a/src/save.h b/src/save.h index ffff4b0..270ebd3 100644 --- a/src/save.h +++ b/src/save.h @@ -14,5 +14,19 @@ int state_write(const nes*, void* mem, int size); int load_state(nes*, const char* filename); int save_state(const nes*, const char* filename); +/* +// Chunking + +typedef struct { + int offset; + int size; +} nese_io_chunk; + +int write_chunks(void* dst, int dst_len, const void* src, + const nese_io_chunk* chunks, int n_chunks); + +int read_chunks(const void* src, int src_len, void* dst, + const nese_io_chunk* chunks, int n_chunks); +*/ #endif // NESE_SAVE_H_