| @@ -30,7 +30,7 @@ PFLAGS += -g | |||||
| #PFLAGS += -DDEBUG_APU | #PFLAGS += -DDEBUG_APU | ||||
| #PFLAGS += -DDEBUG_INPUT | #PFLAGS += -DDEBUG_INPUT | ||||
| #PFLAGS += -DE6502_DEBUG | #PFLAGS += -DE6502_DEBUG | ||||
| #PFLAGS += -DE6502_ILLEGAL | |||||
| PFLAGS += -DE6502_ILLEGAL | |||||
| CFLAGS += $(PFLAGS) -Wall -Werror -Wshadow -Wunused -I../ -Isrc/ | CFLAGS += $(PFLAGS) -Wall -Werror -Wshadow -Wunused -I../ -Isrc/ | ||||
| CFLAGS += -Iinc/$(PLATFORM)/SDL2 | CFLAGS += -Iinc/$(PLATFORM)/SDL2 | ||||
| LDFLAGS += $(PFLAGS) | LDFLAGS += $(PFLAGS) | ||||
| @@ -96,7 +96,7 @@ static int cnrom_state_size(const void* _map) { | |||||
| return (sizeof(map->bank) + sizeof(map->vram)); | 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; | cnrom_mapper* map = (cnrom_mapper*)_map; | ||||
| const void* ptr = data; | const void* ptr = data; | ||||
| @@ -111,7 +111,7 @@ static int cnrom_state_read(void* _map, const void* data) { | |||||
| return (ptr - 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; | cnrom_mapper* map = (cnrom_mapper*)_map; | ||||
| void* ptr = data; | void* ptr = data; | ||||
| @@ -15,9 +15,11 @@ typedef struct { | |||||
| uint8_t* chr_bank[2]; | uint8_t* chr_bank[2]; | ||||
| uint8_t* vram_bank[4]; | uint8_t* vram_bank[4]; | ||||
| uint8_t* prg_bank[2]; | uint8_t* prg_bank[2]; | ||||
| uint8_t* chr_ram; | |||||
| uint8_t* chr; | uint8_t* chr; | ||||
| int chr_bank_offset[2]; | |||||
| int chr_ram_lim; | |||||
| uint8_t reg_shift; | uint8_t reg_shift; | ||||
| uint8_t reg_n_shift; | uint8_t reg_n_shift; | ||||
| uint8_t reg_control; | uint8_t reg_control; | ||||
| @@ -27,6 +29,8 @@ typedef struct { | |||||
| uint8_t vram[2][nes_vram_page_size]; | uint8_t vram[2][nes_vram_page_size]; | ||||
| uint8_t wram[nes_mem_wram_size]; | uint8_t wram[nes_mem_wram_size]; | ||||
| uint8_t chr_ram[]; | |||||
| } mmc1_mapper; | } mmc1_mapper; | ||||
| @@ -55,21 +59,22 @@ static void mmc1_update_vram(mmc1_mapper* map) { | |||||
| } | } | ||||
| static void mmc1_update_chr(mmc1_mapper* map) { | static void mmc1_update_chr(mmc1_mapper* map) { | ||||
| // CHR RAM selection | |||||
| int banks[2] = {0}; | |||||
| if (!(map->reg_control & 0b10000)) { | 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 { | } 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) { | 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) { | 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) { | if (NULL != map) { | ||||
| map->prg_rom = cart->prg_rom; | map->prg_rom = cart->prg_rom; | ||||
| map->prg_rom_banks = cart->prg_rom_banks; | map->prg_rom_banks = cart->prg_rom_banks; | ||||
| map->chr_rom_banks = cart->chr_rom_banks / 2; | map->chr_rom_banks = cart->chr_rom_banks / 2; | ||||
| if (map->chr_rom_banks > 0) { | if (map->chr_rom_banks > 0) { | ||||
| map->chr_rom = cart->chr_rom; | map->chr_rom = cart->chr_rom; | ||||
| map->chr_ram = NULL; | |||||
| map->chr = map->chr_rom; | map->chr = map->chr_rom; | ||||
| } else { | } else { | ||||
| map->chr_rom = NULL; | map->chr_rom = NULL; | ||||
| map->chr_ram = calloc(32, nes_chr_page_size); | |||||
| map->chr = map->chr_ram; | map->chr = map->chr_ram; | ||||
| } | } | ||||
| map->chr_ram_lim = 0; | |||||
| map->battery = !!(cart->flags & Cart_Flag_Battery); | 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) { | 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, | 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, | static void mmc1_chr_write(void* data, | ||||
| uint16_t addr, uint8_t val) { | 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; | *(mmc1_chr_addr(data, addr)) = val; | ||||
| } | } | ||||
| } | } | ||||
| @@ -233,17 +241,27 @@ static int mmc1_sram_size(void* data) { | |||||
| /* Save State */ | /* 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) { | static int mmc1_state_size(const void* _map) { | ||||
| mmc1_mapper* map = (mmc1_mapper*)_map; | mmc1_mapper* map = (mmc1_mapper*)_map; | ||||
| return ( (void*)map + | |||||
| return ( map->chr_ram_lim + | |||||
| (void*)map + | |||||
| sizeof(*map) - | sizeof(*map) - | ||||
| (void*)&(map->reg_shift)); | (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; | 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); | memcpy(&(map->reg_shift), data, size); | ||||
| mmc1_update_prg(map); | mmc1_update_prg(map); | ||||
| @@ -253,9 +271,11 @@ static int mmc1_state_read(void* _map, const void* data) { | |||||
| return size; | 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; | mmc1_mapper* map = (mmc1_mapper*)_map; | ||||
| int size = mmc1_state_size(_map); | int size = mmc1_state_size(_map); | ||||
| if (size > data_len) size = data_len; | |||||
| memcpy(data, &(map->reg_shift), size); | memcpy(data, &(map->reg_shift), size); | ||||
| return size; | return size; | ||||
| } | } | ||||
| @@ -32,6 +32,9 @@ typedef struct { | |||||
| uint8_t* chr_bank[8]; // 1 KB | uint8_t* chr_bank[8]; // 1 KB | ||||
| uint8_t* vram_bank[4]; | uint8_t* vram_bank[4]; | ||||
| int chr_bank_offset[8]; | |||||
| int chr_ram_lim; | |||||
| uint8_t r[8]; | uint8_t r[8]; | ||||
| uint8_t flags; | uint8_t flags; | ||||
| uint8_t bank_select; | uint8_t bank_select; | ||||
| @@ -40,6 +43,7 @@ typedef struct { | |||||
| uint8_t wram[nes_mem_wram_size]; | uint8_t wram[nes_mem_wram_size]; | ||||
| uint8_t vram[2][nes_vram_page_size]; | uint8_t vram[2][nes_vram_page_size]; | ||||
| uint8_t chr_ram[]; | |||||
| } mmc3_mapper; | } mmc3_mapper; | ||||
| static inline uint8_t* mmc3_prg_bank(mmc3_mapper* map, int bank) { | 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_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 + 0] = mmc3_chr_bank(map, bank); | ||||
| map->chr_bank[reg + 1] = mmc3_chr_bank(map, bank | 1); | 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, | 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_LOG("CHR ROM: 1k $%04x <- bank %d", reg << 10, bank); | ||||
| map->chr_bank[reg] = mmc3_chr_bank(map, 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, | 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) { | 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) { | if (NULL != map) { | ||||
| map->mapper = nes_map; | map->mapper = nes_map; | ||||
| map->flags = (cart->flags & Cart_Flag_Horizontal) ? | 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 = cart->prg_rom; | ||||
| map->prg_rom_banks = cart->prg_rom_banks * 2; | map->prg_rom_banks = cart->prg_rom_banks * 2; | ||||
| if (cart->chr_rom_banks <= 0) { | if (cart->chr_rom_banks <= 0) { | ||||
| map->chr_rom = calloc(1024, 256); | |||||
| map->chr_rom = map->chr_ram; | |||||
| map->chr_rom_banks = 256; | map->chr_rom_banks = 256; | ||||
| map->flags |= mmc3_Flag_CHR_RAM; | map->flags |= mmc3_Flag_CHR_RAM; | ||||
| } else { | } else { | ||||
| @@ -188,13 +198,7 @@ static void* mmc3_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| } | } | ||||
| static void mmc3_done(void* data) { | 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, | 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) { | uint16_t addr, uint8_t val) { | ||||
| mmc3_mapper* map = (mmc3_mapper*)data; | mmc3_mapper* map = (mmc3_mapper*)data; | ||||
| if (map->flags & mmc3_Flag_CHR_RAM) { | 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); | // MAP_LOG("CHR ROM Write: $%04x < %02x\n", addr, val); | ||||
| } | } | ||||
| @@ -349,17 +356,27 @@ static int mmc3_sram_size(void* data) { | |||||
| /* Save State */ | /* 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) { | static int mmc3_state_size(const void* data) { | ||||
| const mmc3_mapper* map = (mmc3_mapper*)data; | const mmc3_mapper* map = (mmc3_mapper*)data; | ||||
| return ( (map->wram - map->r) + | return ( (map->wram - map->r) + | ||||
| sizeof(map->wram) + | 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; | 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); | memcpy(map->r, data, size); | ||||
| uint8_t new_bank_select = map->bank_select; | uint8_t new_bank_select = map->bank_select; | ||||
| @@ -371,9 +388,11 @@ static int mmc3_state_read(void* _map, const void* data) { | |||||
| return size; | 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; | mmc3_mapper* map = (mmc3_mapper*)_map; | ||||
| int size = mmc3_state_size(_map); | int size = mmc3_state_size(_map); | ||||
| if (size > data_len) size = data_len; | |||||
| memcpy(data, map->r, size); | memcpy(data, map->r, size); | ||||
| return size; | return size; | ||||
| } | } | ||||
| @@ -10,20 +10,24 @@ typedef struct { | |||||
| uint8_t* chr_rom; | uint8_t* chr_rom; | ||||
| int chr_rom_banks; | int chr_rom_banks; | ||||
| uint8_t mirror; | uint8_t mirror; | ||||
| uint8_t vram[nes_vram_page_size * 2]; | uint8_t vram[nes_vram_page_size * 2]; | ||||
| uint8_t wram[nes_mem_wram_size]; | uint8_t wram[nes_mem_wram_size]; | ||||
| uint8_t chr_ram[]; | |||||
| } nrom_mapper; | } nrom_mapper; | ||||
| static void nrom_reset(void* data) {} | static void nrom_reset(void* data) {} | ||||
| static void* nrom_init(nes_mapper* nes_map, nes_cart* cart) { | 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) { | if (NULL != map) { | ||||
| map->prg_rom = cart->prg_rom; | map->prg_rom = cart->prg_rom; | ||||
| map->prg_rom_banks = cart->prg_rom_banks; | map->prg_rom_banks = cart->prg_rom_banks; | ||||
| if (cart->chr_rom_banks <= 0) { | if (cart->chr_rom_banks <= 0) { | ||||
| map->chr_rom = calloc(8, 1024); | |||||
| map->chr_rom = map->chr_ram; | |||||
| } else { | } else { | ||||
| map->chr_rom = cart->chr_rom; | map->chr_rom = cart->chr_rom; | ||||
| } | } | ||||
| @@ -97,23 +101,29 @@ static void nrom_chr_write(void* data, | |||||
| /* Save State */ | /* 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) { | static int nrom_state_size(const void* _map) { | ||||
| nrom_mapper* map = (nrom_mapper*)_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; | 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; | 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; | |||||
| } | } | ||||
| @@ -97,7 +97,7 @@ int uxrom_state_size(const void* _map) { | |||||
| sizeof(map->chr_ram)); | 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; | uxrom_mapper* map = (uxrom_mapper*)_map; | ||||
| const void* ptr = data; | const void* ptr = data; | ||||
| @@ -113,7 +113,7 @@ int uxrom_state_read(void* _map, const void* data) { | |||||
| return (ptr - 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; | uxrom_mapper* map = (uxrom_mapper*)_map; | ||||
| void* ptr = data; | void* ptr = data; | ||||
| @@ -33,8 +33,8 @@ typedef struct nes_mapper_t { | |||||
| int (*sram_size)(void*); | int (*sram_size)(void*); | ||||
| int (*state_size)(const void* map); | 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; | } nes_mapper; | ||||
| static inline void* nes_map_init(nes_mapper* map, | static inline void* nes_map_init(nes_mapper* map, | ||||
| @@ -76,7 +76,13 @@ int load_state(nes* sys, const char* cart_filename) { | |||||
| FILE* file = fopen(state_filename, "rb"); | FILE* file = fopen(state_filename, "rb"); | ||||
| if (NULL != file) { | 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); | void* mem = map_file(file, file_size, Filemap_Mode_Read); | ||||
| if (NULL != mem) { | 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 nes_mapper* mapper = sys->cart.mapper; | ||||
| const void* map_data = sys->cart.map_data; | 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); | return (ptr - mem); | ||||
| } | } | ||||
| @@ -342,7 +348,7 @@ int state_read(nes* sys, const void* mem, int mem_size) { | |||||
| } else if (tag_mapper == tag) { | } else if (tag_mapper == tag) { | ||||
| n_read = sys->cart.mapper->state_read( | n_read = sys->cart.mapper->state_read( | ||||
| sys->cart.map_data, ptr | |||||
| sys->cart.map_data, ptr, size | |||||
| ); | ); | ||||
| loaded |= Component_Mapper; | loaded |= Component_Mapper; | ||||
| @@ -395,3 +401,29 @@ int state_read(nes* sys, const void* mem, int mem_size) { | |||||
| return result; | 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); | |||||
| } | |||||
| */ | |||||
| @@ -14,5 +14,19 @@ int state_write(const nes*, void* mem, int size); | |||||
| int load_state(nes*, const char* filename); | int load_state(nes*, const char* filename); | ||||
| int save_state(const 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_ | #endif // NESE_SAVE_H_ | ||||