This required a significant refactor to move the mapper data out of the static struct, but in the end is a saner architecture.master
| @@ -63,7 +63,8 @@ int nes_cart_init_mem(nes_cart* cart, void* mem, int len) { | |||||
| } | } | ||||
| // Don't initialize the mapper until all flags are set! | // Don't initialize the mapper until all flags are set! | ||||
| status = nes_map_init(cart->mapper, cart); | |||||
| cart->map_data = nes_map_init(cart->mapper, cart); | |||||
| status = (NULL == cart->map_data ? -1 : 0); | |||||
| } | } | ||||
| return status; | return status; | ||||
| @@ -71,8 +72,9 @@ int nes_cart_init_mem(nes_cart* cart, void* mem, int len) { | |||||
| void nes_cart_done(nes_cart* cart) { | void nes_cart_done(nes_cart* cart) { | ||||
| if (NULL != cart->mapper) { | if (NULL != cart->mapper) { | ||||
| nes_map_done(cart->mapper); | |||||
| nes_map_done(cart->mapper, cart->map_data); | |||||
| cart->mapper = NULL; | cart->mapper = NULL; | ||||
| cart->map_data = NULL; | |||||
| } | } | ||||
| if (NULL != cart->ines_mem) { | if (NULL != cart->ines_mem) { | ||||
| unmap_file(cart->ines_mem, cart->ines_size); | unmap_file(cart->ines_mem, cart->ines_size); | ||||
| @@ -17,7 +17,9 @@ typedef struct nes_cart_t { | |||||
| uint8_t* chr_rom; | uint8_t* chr_rom; | ||||
| int chr_rom_banks; | int chr_rom_banks; | ||||
| nes_Cart_Flags flags; | nes_Cart_Flags flags; | ||||
| struct nes_mapper_t* mapper; | struct nes_mapper_t* mapper; | ||||
| void* map_data; | |||||
| void* ines_mem; | void* ines_mem; | ||||
| int ines_size; | int ines_size; | ||||
| @@ -24,27 +24,26 @@ static void cnrom_set_bank(cnrom_mapper* map, uint8_t bank) { | |||||
| ]; | ]; | ||||
| } | } | ||||
| static void cnrom_reset(nes_mapper* nes_map) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)nes_map->data; | |||||
| static void cnrom_reset(void* _map) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)_map; | |||||
| cnrom_set_bank(map, 0); | cnrom_set_bank(map, 0); | ||||
| } | } | ||||
| static int cnrom_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| static void* cnrom_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| cnrom_mapper* map = calloc(1, sizeof(cnrom_mapper)); | cnrom_mapper* map = calloc(1, sizeof(cnrom_mapper)); | ||||
| nes_map->data = map; | |||||
| 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 = cart->chr_rom; | map->chr_rom = cart->chr_rom; | ||||
| map->chr_rom_banks = cart->chr_rom_banks; | map->chr_rom_banks = cart->chr_rom_banks; | ||||
| map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | ||||
| cnrom_reset(nes_map); | |||||
| cnrom_reset(map); | |||||
| } | } | ||||
| return (NULL == map ? -1 : 0); | |||||
| return map; | |||||
| } | } | ||||
| static void cnrom_done(nes_mapper* nes_map) { | |||||
| free(nes_map->data); | |||||
| static void cnrom_done(void* _map) { | |||||
| free(_map); | |||||
| } | } | ||||
| static inline uint8_t* cnrom_prg_addr(cnrom_mapper* map, | static inline uint8_t* cnrom_prg_addr(cnrom_mapper* map, | ||||
| @@ -57,37 +56,34 @@ static inline uint8_t* cnrom_prg_addr(cnrom_mapper* map, | |||||
| } | } | ||||
| static uint8_t cnrom_read(nes_mapper* map, uint16_t addr) { | |||||
| static uint8_t cnrom_read(void* _map, uint16_t addr) { | |||||
| uint8_t val = 0; | uint8_t val = 0; | ||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| val = *(cnrom_prg_addr((cnrom_mapper*)map->data, addr)); | |||||
| val = *(cnrom_prg_addr((cnrom_mapper*)_map, addr)); | |||||
| } | } | ||||
| return val; | return val; | ||||
| } | } | ||||
| static void cnrom_write(nes_mapper* nes_map, | |||||
| uint16_t addr, uint8_t val) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)nes_map->data; | |||||
| static void cnrom_write(void* _map, uint16_t addr, uint8_t val) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)_map; | |||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| cnrom_set_bank(map, val); | cnrom_set_bank(map, val); | ||||
| } | } | ||||
| } | } | ||||
| static uint8_t* cnrom_chr_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| return &((cnrom_mapper*)nes_map->data)->chr_bank[addr]; | |||||
| static uint8_t* cnrom_chr_addr(void* _map, uint16_t addr) { | |||||
| return &((cnrom_mapper*)_map)->chr_bank[addr]; | |||||
| } | } | ||||
| static uint8_t* cnrom_vram_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)nes_map->data; | |||||
| static uint8_t* cnrom_vram_addr(void* _map, uint16_t addr) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)_map; | |||||
| int page = addr >> 10U; | int page = addr >> 10U; | ||||
| page >>= map->mirror; | page >>= map->mirror; | ||||
| addr = ((page & 1) << 10U) | (addr & 0x3FFU); | addr = ((page & 1) << 10U) | (addr & 0x3FFU); | ||||
| return &map->vram[addr]; | return &map->vram[addr]; | ||||
| } | } | ||||
| static void cnrom_chr_write(nes_mapper* nes_map, | |||||
| static void cnrom_chr_write(void* _map, | |||||
| uint16_t addr, uint8_t val) { | uint16_t addr, uint8_t val) { | ||||
| // ROM only. | // ROM only. | ||||
| } | } | ||||
| @@ -95,13 +91,13 @@ static void cnrom_chr_write(nes_mapper* nes_map, | |||||
| /* Save State */ | /* Save State */ | ||||
| int cnrom_state_size(const nes_mapper* nes_map) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)nes_map->data; | |||||
| static int cnrom_state_size(const void* _map) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)_map; | |||||
| return (sizeof(map->bank) + sizeof(map->vram)); | return (sizeof(map->bank) + sizeof(map->vram)); | ||||
| } | } | ||||
| int cnrom_state_read(nes_mapper* nes_map, const void* data) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)nes_map->data; | |||||
| static int cnrom_state_read(void* _map, const void* data) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)_map; | |||||
| const void* ptr = data; | const void* ptr = data; | ||||
| memcpy(&map->bank, ptr, sizeof(map->bank)); | memcpy(&map->bank, ptr, sizeof(map->bank)); | ||||
| @@ -115,8 +111,8 @@ int cnrom_state_read(nes_mapper* nes_map, const void* data) { | |||||
| return (ptr - data); | return (ptr - data); | ||||
| } | } | ||||
| int cnrom_state_write(const nes_mapper* nes_map, void* data) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)nes_map->data; | |||||
| static int cnrom_state_write(const void* _map, void* data) { | |||||
| cnrom_mapper* map = (cnrom_mapper*)_map; | |||||
| void* ptr = data; | void* ptr = data; | ||||
| memcpy(ptr, &map->bank, sizeof(map->bank)); | memcpy(ptr, &map->bank, sizeof(map->bank)); | ||||
| @@ -90,8 +90,8 @@ static void mmc1_update_prg(mmc1_mapper* map) { | |||||
| map->prg_bank[1] = &map->prg_rom[bank_1 * nes_prg_rom_page_size]; | map->prg_bank[1] = &map->prg_rom[bank_1 * nes_prg_rom_page_size]; | ||||
| } | } | ||||
| static void mmc1_reset(nes_mapper* nes_map) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| static void mmc1_reset(void* data) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)data; | |||||
| map->reg_shift = 0b10000; | map->reg_shift = 0b10000; | ||||
| map->reg_control = 0b01100; | map->reg_control = 0b01100; | ||||
| map->reg_chr_0 = 0; | map->reg_chr_0 = 0; | ||||
| @@ -102,9 +102,8 @@ static void mmc1_reset(nes_mapper* nes_map) { | |||||
| mmc1_update_vram(map); | mmc1_update_vram(map); | ||||
| } | } | ||||
| static int 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)); | mmc1_mapper* map = calloc(1, sizeof(mmc1_mapper)); | ||||
| nes_map->data = map; | |||||
| 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; | ||||
| @@ -121,15 +120,15 @@ static int mmc1_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| map->battery = !!(cart->flags & Cart_Flag_Battery); | map->battery = !!(cart->flags & Cart_Flag_Battery); | ||||
| mmc1_reset(nes_map); | |||||
| mmc1_reset(map); | |||||
| } | } | ||||
| return (NULL == map ? -1 : 0); | |||||
| return map; | |||||
| } | } | ||||
| static void mmc1_done(nes_mapper* nes_map) { | |||||
| if (NULL != nes_map->data) { | |||||
| free(((mmc1_mapper*)nes_map->data)->chr_ram); | |||||
| free(nes_map->data); | |||||
| static void mmc1_done(void* data) { | |||||
| if (NULL != data) { | |||||
| free(((mmc1_mapper*)data)->chr_ram); | |||||
| free(data); | |||||
| } | } | ||||
| } | } | ||||
| @@ -145,19 +144,18 @@ static inline uint8_t* mmc1_wram_addr(mmc1_mapper* map, | |||||
| return &(map->wram[addr & 0x1FFFU]); | return &(map->wram[addr & 0x1FFFU]); | ||||
| } | } | ||||
| static uint8_t mmc1_read(nes_mapper* map, uint16_t addr) { | |||||
| static uint8_t mmc1_read(void* data, uint16_t addr) { | |||||
| uint8_t val = 0; | uint8_t val = 0; | ||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| val = *(mmc1_prg_addr((mmc1_mapper*)map->data, addr)); | |||||
| val = *(mmc1_prg_addr((mmc1_mapper*)data, addr)); | |||||
| } else if (addr >= nes_mem_wram_start) { | } else if (addr >= nes_mem_wram_start) { | ||||
| val = *(mmc1_wram_addr((mmc1_mapper*)map->data, addr)); | |||||
| val = *(mmc1_wram_addr((mmc1_mapper*)data, addr)); | |||||
| } | } | ||||
| return val; | return val; | ||||
| } | } | ||||
| static void mmc1_write(nes_mapper* nes_map, | |||||
| uint16_t addr, uint8_t val) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| static void mmc1_write(void* data, uint16_t addr, uint8_t val) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)data; | |||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| MAP_LOG("Write $%04x < %02x", addr, val); | MAP_LOG("Write $%04x < %02x", addr, val); | ||||
| if (val & 0x80U) { | if (val & 0x80U) { | ||||
| @@ -201,53 +199,51 @@ static void mmc1_write(nes_mapper* nes_map, | |||||
| } | } | ||||
| } | } | ||||
| static uint8_t* mmc1_chr_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| static uint8_t* mmc1_chr_addr(void* data, uint16_t addr) { | |||||
| int page = (addr >> 12) & 1; | int page = (addr >> 12) & 1; | ||||
| addr &= 0xFFFU; | addr &= 0xFFFU; | ||||
| return &((mmc1_mapper*)nes_map->data)->chr_bank[page][addr]; | |||||
| return &((mmc1_mapper*)data)->chr_bank[page][addr]; | |||||
| } | } | ||||
| static void mmc1_chr_write(nes_mapper* nes_map, | |||||
| static void mmc1_chr_write(void* data, | |||||
| uint16_t addr, uint8_t val) { | uint16_t addr, uint8_t val) { | ||||
| if (NULL != ((mmc1_mapper*)nes_map->data)->chr_ram) { | |||||
| *(mmc1_chr_addr(nes_map, addr)) = val; | |||||
| if (NULL != ((mmc1_mapper*)data)->chr_ram) { | |||||
| *(mmc1_chr_addr(data, addr)) = val; | |||||
| } | } | ||||
| } | } | ||||
| static uint8_t* mmc1_vram_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| static uint8_t* mmc1_vram_addr(void* data, uint16_t addr) { | |||||
| int page = (addr >> 10) & 3; | int page = (addr >> 10) & 3; | ||||
| int loc = addr & 0x3FFU; | int loc = addr & 0x3FFU; | ||||
| // MAP_LOG("VRAM $%04x -> %p", addr, ((mmc1_mapper*)nes_map->data)->vram_bank[page]); | // MAP_LOG("VRAM $%04x -> %p", addr, ((mmc1_mapper*)nes_map->data)->vram_bank[page]); | ||||
| return &((mmc1_mapper*)nes_map->data)->vram_bank[page][loc]; | |||||
| return &((mmc1_mapper*)data)->vram_bank[page][loc]; | |||||
| } | } | ||||
| static void* mmc1_sram(nes_mapper* nes_map) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| static void* mmc1_sram(void* data) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)data; | |||||
| return (map->battery ? map->wram : NULL); | return (map->battery ? map->wram : NULL); | ||||
| } | } | ||||
| static int mmc1_sram_size(nes_mapper* nes_map) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| static int mmc1_sram_size(void* data) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)data; | |||||
| return (map->battery ? sizeof(map->wram) : 0); | return (map->battery ? sizeof(map->wram) : 0); | ||||
| } | } | ||||
| /* Save State */ | /* Save State */ | ||||
| int mmc1_state_size(const nes_mapper* nes_map) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| static int mmc1_state_size(const void* _map) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)_map; | |||||
| return ( (void*)map + | return ( (void*)map + | ||||
| sizeof(*map) - | sizeof(*map) - | ||||
| (void*)&(map->reg_shift)); | (void*)&(map->reg_shift)); | ||||
| } | } | ||||
| int mmc1_state_read(nes_mapper* nes_map, const void* data) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| static int mmc1_state_read(void* _map, const void* data) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)_map; | |||||
| int size = mmc1_state_size(nes_map); | |||||
| int size = mmc1_state_size(_map); | |||||
| memcpy(&(map->reg_shift), data, size); | memcpy(&(map->reg_shift), data, size); | ||||
| mmc1_update_prg(map); | mmc1_update_prg(map); | ||||
| @@ -257,9 +253,9 @@ int mmc1_state_read(nes_mapper* nes_map, const void* data) { | |||||
| return size; | return size; | ||||
| } | } | ||||
| int mmc1_state_write(const nes_mapper* nes_map, void* data) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| int size = mmc1_state_size(nes_map); | |||||
| static int mmc1_state_write(const void* _map, void* data) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)_map; | |||||
| int size = mmc1_state_size(_map); | |||||
| memcpy(data, &(map->reg_shift), size); | memcpy(data, &(map->reg_shift), size); | ||||
| return size; | return size; | ||||
| } | } | ||||
| @@ -267,6 +263,7 @@ int mmc1_state_write(const nes_mapper* nes_map, void* data) { | |||||
| nes_mapper mapper_mmc1 = { | nes_mapper mapper_mmc1 = { | ||||
| .name = "MMC1", | .name = "MMC1", | ||||
| .init = mmc1_init, | .init = mmc1_init, | ||||
| .reset = mmc1_reset, | .reset = mmc1_reset, | ||||
| .done = mmc1_done, | .done = mmc1_done, | ||||
| @@ -3,6 +3,7 @@ | |||||
| #include "map.h" | #include "map.h" | ||||
| typedef enum { | typedef enum { | ||||
| mmc3_Flag_Horizontal = 0b00000001, | mmc3_Flag_Horizontal = 0b00000001, | ||||
| mmc3_Flag_IRQ_Enabled = 0b00000010, | mmc3_Flag_IRQ_Enabled = 0b00000010, | ||||
| @@ -25,6 +26,8 @@ typedef struct { | |||||
| uint8_t* chr_rom; | uint8_t* chr_rom; | ||||
| int chr_rom_banks; // 4 KB / 1 KB = 4 | int chr_rom_banks; // 4 KB / 1 KB = 4 | ||||
| nes_mapper* mapper; | |||||
| uint8_t* prg_bank[4]; // 8 KB | uint8_t* prg_bank[4]; // 8 KB | ||||
| uint8_t* chr_bank[8]; // 1 KB | uint8_t* chr_bank[8]; // 1 KB | ||||
| uint8_t* vram_bank[4]; | uint8_t* vram_bank[4]; | ||||
| @@ -146,8 +149,8 @@ static inline void mmc3_update_vram(mmc3_mapper* map) { | |||||
| } | } | ||||
| } | } | ||||
| static void mmc3_reset(nes_mapper* nes_map) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| static void mmc3_reset(void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| map->irq_count = 0; | map->irq_count = 0; | ||||
| map->irq_latch = 0; | map->irq_latch = 0; | ||||
| mmc3_update_rom_mode(map, 0); | mmc3_update_rom_mode(map, 0); | ||||
| @@ -155,10 +158,10 @@ static void mmc3_reset(nes_mapper* nes_map) { | |||||
| mmc3_update_vram(map); | mmc3_update_vram(map); | ||||
| } | } | ||||
| static int 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)); | mmc3_mapper* map = calloc(1, sizeof(mmc3_mapper)); | ||||
| nes_map->data = map; | |||||
| if (NULL != map) { | if (NULL != map) { | ||||
| map->mapper = nes_map; | |||||
| map->flags = (cart->flags & Cart_Flag_Horizontal) ? | map->flags = (cart->flags & Cart_Flag_Horizontal) ? | ||||
| mmc3_Flag_Horizontal : 0; | mmc3_Flag_Horizontal : 0; | ||||
| map->prg_rom = cart->prg_rom; | map->prg_rom = cart->prg_rom; | ||||
| @@ -179,18 +182,18 @@ static int mmc3_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| map->bank_select = mmc3_Bank_Select_PRG | | map->bank_select = mmc3_Bank_Select_PRG | | ||||
| mmc3_Bank_Select_CHR; | mmc3_Bank_Select_CHR; | ||||
| mmc3_reset(nes_map); | |||||
| mmc3_reset(map); | |||||
| } | } | ||||
| return (NULL == map ? -1 : 0); | |||||
| return map; | |||||
| } | } | ||||
| static void mmc3_done(nes_mapper* nes_map) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| static void mmc3_done(void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| if (NULL != map) { | if (NULL != map) { | ||||
| if (map->flags & mmc3_Flag_CHR_RAM) { | if (map->flags & mmc3_Flag_CHR_RAM) { | ||||
| free(map->chr_rom); | free(map->chr_rom); | ||||
| } | } | ||||
| free(nes_map->data); | |||||
| free(map); | |||||
| } | } | ||||
| } | } | ||||
| @@ -204,9 +207,9 @@ static inline uint8_t* mmc3_wram_addr(mmc3_mapper* map, | |||||
| return &(map->wram[addr & 0x1FFFU]); | return &(map->wram[addr & 0x1FFFU]); | ||||
| } | } | ||||
| static uint8_t mmc3_read(nes_mapper* nes_map, uint16_t addr) { | |||||
| static uint8_t mmc3_read(void* data, uint16_t addr) { | |||||
| uint8_t* ptr = NULL; | uint8_t* ptr = NULL; | ||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| ptr = mmc3_prg_addr(map, addr); | ptr = mmc3_prg_addr(map, addr); | ||||
| } else if ( addr >= nes_mem_wram_start && | } else if ( addr >= nes_mem_wram_start && | ||||
| @@ -222,9 +225,9 @@ static uint8_t mmc3_read(nes_mapper* nes_map, uint16_t addr) { | |||||
| return val; | return val; | ||||
| } | } | ||||
| static void mmc3_write(nes_mapper* nes_map, | |||||
| static void mmc3_write(void* data, | |||||
| uint16_t addr, uint8_t val) { | uint16_t addr, uint8_t val) { | ||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| if (addr >= nes_mem_rom_start) MAP_LOG("$%04x < %02x", addr, val); | if (addr >= nes_mem_rom_start) MAP_LOG("$%04x < %02x", addr, val); | ||||
| @@ -284,13 +287,13 @@ static void mmc3_write(nes_mapper* nes_map, | |||||
| map->flags |= mmc3_Flag_IRQ_Enabled; | map->flags |= mmc3_Flag_IRQ_Enabled; | ||||
| } else { | } else { | ||||
| map->flags &= ~mmc3_Flag_IRQ_Enabled; | map->flags &= ~mmc3_Flag_IRQ_Enabled; | ||||
| nes_map_trigger_irq(nes_map, 0); | |||||
| nes_map_trigger_irq(map->mapper, 0); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void mmc3_scanline(nes_mapper* nes_map) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| static void mmc3_scanline(void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| if ( map->irq_count <= 0 || | if ( map->irq_count <= 0 || | ||||
| (map->flags & mmc3_Flag_IRQ_Reload)) { | (map->flags & mmc3_Flag_IRQ_Reload)) { | ||||
| @@ -303,42 +306,42 @@ static void mmc3_scanline(nes_mapper* nes_map) { | |||||
| if ( map->irq_count <= 0 && | if ( map->irq_count <= 0 && | ||||
| (map->flags & mmc3_Flag_IRQ_Enabled)) { | (map->flags & mmc3_Flag_IRQ_Enabled)) { | ||||
| MAP_LOG("IRQ Trigger"); | MAP_LOG("IRQ Trigger"); | ||||
| nes_map_trigger_irq(nes_map, 1); | |||||
| nes_map_trigger_irq(map->mapper, 1); | |||||
| map->irq_count = 0; | map->irq_count = 0; | ||||
| } | } | ||||
| } | } | ||||
| static uint8_t* mmc3_chr_addr(nes_mapper* nes_map, | |||||
| static uint8_t* mmc3_chr_addr(void* data, | |||||
| uint16_t addr) { | uint16_t addr) { | ||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| return &map->chr_bank[(addr >> 10) & 7][addr & 0x3FFU]; | return &map->chr_bank[(addr >> 10) & 7][addr & 0x3FFU]; | ||||
| } | } | ||||
| static uint8_t* mmc3_vram_addr(nes_mapper* nes_map, | |||||
| static uint8_t* mmc3_vram_addr(void* data, | |||||
| uint16_t addr) { | uint16_t addr) { | ||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| return &map->vram_bank[(addr >> 10) & 3][addr & 0x3FFU]; | return &map->vram_bank[(addr >> 10) & 3][addr & 0x3FFU]; | ||||
| } | } | ||||
| static void mmc3_chr_write(nes_mapper* nes_map, | |||||
| static void mmc3_chr_write(void* data, | |||||
| uint16_t addr, uint8_t val) { | uint16_t addr, uint8_t val) { | ||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| if (map->flags & mmc3_Flag_CHR_RAM) { | if (map->flags & mmc3_Flag_CHR_RAM) { | ||||
| *(mmc3_chr_addr(nes_map, addr)) = val; | |||||
| *(mmc3_chr_addr(data, addr)) = val; | |||||
| } | } | ||||
| // MAP_LOG("CHR ROM Write: $%04x < %02x\n", addr, val); | // MAP_LOG("CHR ROM Write: $%04x < %02x\n", addr, val); | ||||
| } | } | ||||
| static void* mmc3_sram(nes_mapper* nes_map) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| static void* mmc3_sram(void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| return ( (map->flags & mmc3_Flag_Battery) ? | return ( (map->flags & mmc3_Flag_Battery) ? | ||||
| map->wram : NULL); | map->wram : NULL); | ||||
| } | } | ||||
| static int mmc3_sram_size(nes_mapper* nes_map) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| static int mmc3_sram_size(void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)data; | |||||
| return ( (map->flags & mmc3_Flag_Battery) ? | return ( (map->flags & mmc3_Flag_Battery) ? | ||||
| sizeof(map->wram) : 0); | sizeof(map->wram) : 0); | ||||
| } | } | ||||
| @@ -346,19 +349,19 @@ static int mmc3_sram_size(nes_mapper* nes_map) { | |||||
| /* Save State */ | /* Save State */ | ||||
| int mmc3_state_size(const nes_mapper* nes_map) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| static int mmc3_state_size(const void* 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)); | ||||
| } | } | ||||
| int mmc3_state_read(nes_mapper* nes_map, const void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| static int mmc3_state_read(void* _map, const void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)_map; | |||||
| uint8_t old_bank_select = map->bank_select; | uint8_t old_bank_select = map->bank_select; | ||||
| int size = mmc3_state_size(nes_map); | |||||
| int size = mmc3_state_size(_map); | |||||
| 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; | ||||
| @@ -370,9 +373,9 @@ int mmc3_state_read(nes_mapper* nes_map, const void* data) { | |||||
| return size; | return size; | ||||
| } | } | ||||
| int mmc3_state_write(const nes_mapper* nes_map, void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)nes_map->data; | |||||
| int size = mmc3_state_size(nes_map); | |||||
| static int mmc3_state_write(const void* _map, void* data) { | |||||
| mmc3_mapper* map = (mmc3_mapper*)_map; | |||||
| int size = mmc3_state_size(_map); | |||||
| memcpy(data, map->r, size); | memcpy(data, map->r, size); | ||||
| return size; | return size; | ||||
| } | } | ||||
| @@ -380,6 +383,7 @@ int mmc3_state_write(const nes_mapper* nes_map, void* data) { | |||||
| nes_mapper mapper_mmc3 = { | nes_mapper mapper_mmc3 = { | ||||
| .name = "MMC3", | .name = "MMC3", | ||||
| .init = mmc3_init, | .init = mmc3_init, | ||||
| .reset = mmc3_reset, | .reset = mmc3_reset, | ||||
| .done = mmc3_done, | .done = mmc3_done, | ||||
| @@ -15,11 +15,10 @@ typedef struct { | |||||
| } nrom_mapper; | } nrom_mapper; | ||||
| static void nrom_reset(nes_mapper* nes_map) {} | |||||
| static void nrom_reset(void* data) {} | |||||
| static int 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)); | nrom_mapper* map = calloc(1, sizeof(nrom_mapper)); | ||||
| nes_map->data = map; | |||||
| 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; | ||||
| @@ -31,16 +30,16 @@ static int nrom_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| map->chr_rom_banks = cart->chr_rom_banks; | map->chr_rom_banks = cart->chr_rom_banks; | ||||
| map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | ||||
| } | } | ||||
| return (NULL == map ? -1 : 0); | |||||
| return map; | |||||
| } | } | ||||
| static void nrom_done(nes_mapper* nes_map) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | |||||
| static void nrom_done(void* data) { | |||||
| nrom_mapper* map = (nrom_mapper*)data; | |||||
| if (NULL != map) { | if (NULL != map) { | ||||
| if (map->chr_rom_banks <= 0) { | if (map->chr_rom_banks <= 0) { | ||||
| free(map->chr_rom); | free(map->chr_rom); | ||||
| } | } | ||||
| free(nes_map->data); | |||||
| free(data); | |||||
| } | } | ||||
| } | } | ||||
| @@ -58,42 +57,39 @@ static inline uint8_t* nrom_wram_addr(nrom_mapper* map, | |||||
| return &(map->wram[addr & 0x1FFFU]); | return &(map->wram[addr & 0x1FFFU]); | ||||
| } | } | ||||
| static uint8_t nrom_read(nes_mapper* map, uint16_t addr) { | |||||
| static uint8_t nrom_read(void* data, uint16_t addr) { | |||||
| uint8_t val = 0; | uint8_t val = 0; | ||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| val = *(nrom_prg_addr((nrom_mapper*)map->data, addr)); | |||||
| val = *(nrom_prg_addr((nrom_mapper*)data, addr)); | |||||
| } else if (addr >= nes_mem_wram_start) { | } else if (addr >= nes_mem_wram_start) { | ||||
| val = *(nrom_wram_addr((nrom_mapper*)map->data, addr)); | |||||
| val = *(nrom_wram_addr((nrom_mapper*)data, addr)); | |||||
| } | } | ||||
| return val; | return val; | ||||
| } | } | ||||
| static void nrom_write(nes_mapper* map, | |||||
| uint16_t addr, uint8_t val) { | |||||
| static void nrom_write(void* data, uint16_t addr, uint8_t val) { | |||||
| if (addr < nes_mem_rom_start && addr >= nes_mem_wram_start) { | if (addr < nes_mem_rom_start && addr >= nes_mem_wram_start) { | ||||
| *(nrom_wram_addr((nrom_mapper*)map->data, addr)) = val; | |||||
| *(nrom_wram_addr((nrom_mapper*)data, addr)) = val; | |||||
| } | } | ||||
| } | } | ||||
| static uint8_t* nrom_chr_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| return &(((nrom_mapper*)nes_map->data)->chr_rom[addr]); | |||||
| static uint8_t* nrom_chr_addr(void* data, uint16_t addr) { | |||||
| return &(((nrom_mapper*)data)->chr_rom[addr]); | |||||
| } | } | ||||
| static uint8_t* nrom_vram_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | |||||
| static uint8_t* nrom_vram_addr(void* data, uint16_t addr) { | |||||
| nrom_mapper* map = (nrom_mapper*)data; | |||||
| int page = addr >> 10U; | int page = addr >> 10U; | ||||
| page >>= map->mirror; | page >>= map->mirror; | ||||
| addr = ((page & 1) << 10U) | (addr & 0x3FFU); | addr = ((page & 1) << 10U) | (addr & 0x3FFU); | ||||
| return &map->vram[addr]; | return &map->vram[addr]; | ||||
| } | } | ||||
| static void nrom_chr_write(nes_mapper* nes_map, | |||||
| static void nrom_chr_write(void* data, | |||||
| uint16_t addr, uint8_t val) { | uint16_t addr, uint8_t val) { | ||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | |||||
| nrom_mapper* map = (nrom_mapper*)data; | |||||
| if (map->chr_rom_banks <= 0) { | if (map->chr_rom_banks <= 0) { | ||||
| *(nrom_chr_addr(nes_map, addr)) = val; | |||||
| *(nrom_chr_addr(data, addr)) = val; | |||||
| } | } | ||||
| // printf("CHR ROM Write: $%04x < %02x\n", addr, val); | // printf("CHR ROM Write: $%04x < %02x\n", addr, val); | ||||
| } | } | ||||
| @@ -101,20 +97,20 @@ static void nrom_chr_write(nes_mapper* nes_map, | |||||
| /* Save State */ | /* Save State */ | ||||
| int nrom_state_size(const nes_mapper* nes_map) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | |||||
| 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)); | ||||
| } | } | ||||
| int nrom_state_read(nes_mapper* nes_map, const void* data) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | |||||
| static int nrom_state_read(void* _map, const void* data) { | |||||
| nrom_mapper* map = (nrom_mapper*)_map; | |||||
| memcpy(map->vram, data, sizeof(map->vram)); | memcpy(map->vram, data, sizeof(map->vram)); | ||||
| memcpy(map->wram, data + sizeof(map->vram), sizeof(map->wram)); | memcpy(map->wram, data + sizeof(map->vram), sizeof(map->wram)); | ||||
| return (sizeof(map->vram) + sizeof(map->wram)); | return (sizeof(map->vram) + sizeof(map->wram)); | ||||
| } | } | ||||
| int nrom_state_write(const nes_mapper* nes_map, void* data) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | |||||
| static int nrom_state_write(const void* _map, void* data) { | |||||
| nrom_mapper* map = (nrom_mapper*)_map; | |||||
| memcpy(data, map->vram, sizeof(map->vram)); | memcpy(data, map->vram, sizeof(map->vram)); | ||||
| memcpy(data + sizeof(map->vram), map->wram, sizeof(map->wram)); | memcpy(data + sizeof(map->vram), map->wram, sizeof(map->wram)); | ||||
| return (sizeof(map->vram) + sizeof(map->wram)); | return (sizeof(map->vram) + sizeof(map->wram)); | ||||
| @@ -24,28 +24,27 @@ static void uxrom_set_bank(uxrom_mapper* map, uint8_t bank) { | |||||
| ]; | ]; | ||||
| } | } | ||||
| static void uxrom_reset(nes_mapper* nes_map) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)nes_map->data; | |||||
| static void uxrom_reset(void* data) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)data; | |||||
| uxrom_set_bank(map, 0); | uxrom_set_bank(map, 0); | ||||
| map->prg_bank_lo = map->prg_rom; | map->prg_bank_lo = map->prg_rom; | ||||
| } | } | ||||
| static int uxrom_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| static void* uxrom_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| uxrom_mapper* map = calloc(1, sizeof(uxrom_mapper)); | uxrom_mapper* map = calloc(1, sizeof(uxrom_mapper)); | ||||
| nes_map->data = map; | |||||
| 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->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | ||||
| map->prg_bank_hi = &map->prg_rom[(map->prg_rom_banks - 1) * | map->prg_bank_hi = &map->prg_rom[(map->prg_rom_banks - 1) * | ||||
| nes_prg_rom_page_size]; | nes_prg_rom_page_size]; | ||||
| uxrom_reset(nes_map); | |||||
| uxrom_reset(map); | |||||
| } | } | ||||
| return (NULL == map ? -1 : 0); | |||||
| return map; | |||||
| } | } | ||||
| static void uxrom_done(nes_mapper* nes_map) { | |||||
| free(nes_map->data); | |||||
| static void uxrom_done(void* data) { | |||||
| free(data); | |||||
| } | } | ||||
| static inline uint8_t* uxrom_prg_addr(uxrom_mapper* map, | static inline uint8_t* uxrom_prg_addr(uxrom_mapper* map, | ||||
| @@ -56,53 +55,50 @@ static inline uint8_t* uxrom_prg_addr(uxrom_mapper* map, | |||||
| } | } | ||||
| static uint8_t uxrom_read(nes_mapper* map, uint16_t addr) { | |||||
| static uint8_t uxrom_read(void* _map, uint16_t addr) { | |||||
| uint8_t val = 0; | uint8_t val = 0; | ||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| val = *(uxrom_prg_addr((uxrom_mapper*)map->data, addr)); | |||||
| val = *(uxrom_prg_addr((uxrom_mapper*)_map, addr)); | |||||
| } | } | ||||
| return val; | return val; | ||||
| } | } | ||||
| static void uxrom_write(nes_mapper* nes_map, | |||||
| uint16_t addr, uint8_t val) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)nes_map->data; | |||||
| static void uxrom_write(void* _map, uint16_t addr, uint8_t val) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)_map; | |||||
| if (addr >= nes_mem_rom_start) { | if (addr >= nes_mem_rom_start) { | ||||
| uxrom_set_bank(map, val); | uxrom_set_bank(map, val); | ||||
| } | } | ||||
| } | } | ||||
| static uint8_t* uxrom_chr_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| return &((uxrom_mapper*)nes_map->data)->chr_ram[addr]; | |||||
| static uint8_t* uxrom_chr_addr(void* data, uint16_t addr) { | |||||
| return &((uxrom_mapper*)data)->chr_ram[addr]; | |||||
| } | } | ||||
| static uint8_t* uxrom_vram_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)nes_map->data; | |||||
| static uint8_t* uxrom_vram_addr(void* data, uint16_t addr) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)data; | |||||
| int page = addr >> 10U; | int page = addr >> 10U; | ||||
| page >>= map->mirror; | page >>= map->mirror; | ||||
| addr = ((page & 1) << 10U) | (addr & 0x3FFU); | addr = ((page & 1) << 10U) | (addr & 0x3FFU); | ||||
| return &map->vram[addr]; | return &map->vram[addr]; | ||||
| } | } | ||||
| static void uxrom_chr_write(nes_mapper* nes_map, | |||||
| static void uxrom_chr_write(void* data, | |||||
| uint16_t addr, uint8_t val) { | uint16_t addr, uint8_t val) { | ||||
| ((uxrom_mapper*)nes_map->data)->chr_ram[addr] = val; | |||||
| ((uxrom_mapper*)data)->chr_ram[addr] = val; | |||||
| } | } | ||||
| /* Save State */ | /* Save State */ | ||||
| int uxrom_state_size(const nes_mapper* nes_map) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)nes_map->data; | |||||
| int uxrom_state_size(const void* _map) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)_map; | |||||
| return ( sizeof(uint32_t) + | return ( sizeof(uint32_t) + | ||||
| sizeof(map->vram) + | sizeof(map->vram) + | ||||
| sizeof(map->chr_ram)); | sizeof(map->chr_ram)); | ||||
| } | } | ||||
| int uxrom_state_read(nes_mapper* nes_map, const void* data) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)nes_map->data; | |||||
| int uxrom_state_read(void* _map, const void* data) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)_map; | |||||
| const void* ptr = data; | const void* ptr = data; | ||||
| map->bank = *(uint32_t*)ptr; | map->bank = *(uint32_t*)ptr; | ||||
| @@ -117,8 +113,8 @@ int uxrom_state_read(nes_mapper* nes_map, const void* data) { | |||||
| return (ptr - data); | return (ptr - data); | ||||
| } | } | ||||
| int uxrom_state_write(const nes_mapper* nes_map, void* data) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)nes_map->data; | |||||
| int uxrom_state_write(const void* _map, void* data) { | |||||
| uxrom_mapper* map = (uxrom_mapper*)_map; | |||||
| void* ptr = data; | void* ptr = data; | ||||
| uint32_t bank = map->bank; | uint32_t bank = map->bank; | ||||
| @@ -12,45 +12,42 @@ | |||||
| struct nes_cart_t; | struct nes_cart_t; | ||||
| typedef struct nes_mapper_t { | typedef struct nes_mapper_t { | ||||
| void* data; | |||||
| const char* name; | const char* name; | ||||
| int (*init)(struct nes_mapper_t*, struct nes_cart_t* cart); | |||||
| void (*reset)(struct nes_mapper_t*); | |||||
| void (*done)(struct nes_mapper_t*); | |||||
| void* (*init)(struct nes_mapper_t*, struct nes_cart_t* cart); | |||||
| void (*reset)(void*); | |||||
| void (*done)(void*); | |||||
| uint8_t (*read)(struct nes_mapper_t*, uint16_t addr); | |||||
| void (*write)(struct nes_mapper_t*, uint16_t addr, uint8_t val); | |||||
| uint8_t (*read)(void*, uint16_t addr); | |||||
| void (*write)(void*, uint16_t addr, uint8_t val); | |||||
| uint8_t* (*chr_addr)(struct nes_mapper_t*, uint16_t addr); | |||||
| uint8_t* (*vram_addr)(struct nes_mapper_t*, uint16_t addr); | |||||
| void (*chr_write)(struct nes_mapper_t*, uint16_t addr, uint8_t val); | |||||
| uint8_t* (*chr_addr)(void*, uint16_t addr); | |||||
| uint8_t* (*vram_addr)(void*, uint16_t addr); | |||||
| void (*chr_write)(void*, uint16_t addr, uint8_t val); | |||||
| void (*scanline)(struct nes_mapper_t*); | |||||
| void (*irq_callback)(void*, int); | |||||
| void (*scanline)(void*); | |||||
| void (*irq_callback)(void* irq_arg, int); | |||||
| void* irq_arg; | void* irq_arg; | ||||
| void* (*sram)(struct nes_mapper_t*); | |||||
| int (*sram_size)(struct nes_mapper_t*); | |||||
| int (*state_size)(const struct nes_mapper_t*); | |||||
| int (*state_read)(struct nes_mapper_t*, const void*); | |||||
| int (*state_write)(const struct nes_mapper_t*, void*); | |||||
| void* (*sram)(void*); | |||||
| 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); | |||||
| } nes_mapper; | } nes_mapper; | ||||
| static inline int nes_map_init(nes_mapper* map, | |||||
| struct nes_cart_t* cart) { | |||||
| static inline void* nes_map_init(nes_mapper* map, | |||||
| struct nes_cart_t* cart) { | |||||
| return map->init(map, cart); | return map->init(map, cart); | ||||
| } | } | ||||
| static inline void nes_map_reset(nes_mapper* map) { | |||||
| map->reset(map); | |||||
| static inline void nes_map_reset(nes_mapper* map, void* data) { | |||||
| map->reset(data); | |||||
| } | } | ||||
| static inline void nes_map_done(nes_mapper* map) { | |||||
| map->done(map); | |||||
| static inline void nes_map_done(nes_mapper* map, void* data) { | |||||
| map->done(data); | |||||
| } | } | ||||
| static inline void nes_map_set_irq(nes_mapper* map, | static inline void nes_map_set_irq(nes_mapper* map, | ||||
| @@ -66,44 +63,51 @@ static inline void nes_map_trigger_irq(nes_mapper* map, | |||||
| } | } | ||||
| static inline uint8_t nes_map_read(nes_mapper* map, | static inline uint8_t nes_map_read(nes_mapper* map, | ||||
| uint16_t addr) { | |||||
| return map->read(map, addr); | |||||
| void* data, | |||||
| uint16_t addr) { | |||||
| return map->read(data, addr); | |||||
| } | } | ||||
| static inline void nes_map_write(nes_mapper* map, | static inline void nes_map_write(nes_mapper* map, | ||||
| uint16_t addr, | |||||
| uint8_t val) { | |||||
| map->write(map, addr, val); | |||||
| void* data, | |||||
| uint16_t addr, | |||||
| uint8_t val) { | |||||
| map->write(data, addr, val); | |||||
| } | } | ||||
| static inline uint8_t* nes_map_chr_addr(nes_mapper* map, | static inline uint8_t* nes_map_chr_addr(nes_mapper* map, | ||||
| uint16_t addr) { | |||||
| return map->chr_addr(map, addr); | |||||
| void* data, | |||||
| uint16_t addr) { | |||||
| return map->chr_addr(data, addr); | |||||
| } | } | ||||
| static inline uint8_t nes_chr_read(nes_mapper* map, | static inline uint8_t nes_chr_read(nes_mapper* map, | ||||
| uint16_t addr) { | |||||
| return *(nes_map_chr_addr(map, addr)); | |||||
| void* data, | |||||
| uint16_t addr) { | |||||
| return *(nes_map_chr_addr(map, data, addr)); | |||||
| } | } | ||||
| static inline void nes_chr_write(nes_mapper* map, | |||||
| uint16_t addr, uint8_t val) { | |||||
| return map->chr_write(map, addr, val); | |||||
| static inline void nes_chr_write(nes_mapper* map, void* data, | |||||
| uint16_t addr, uint8_t val) { | |||||
| return map->chr_write(data, addr, val); | |||||
| } | } | ||||
| static inline uint8_t* nes_map_vram_addr(nes_mapper* map, | static inline uint8_t* nes_map_vram_addr(nes_mapper* map, | ||||
| void* data, | |||||
| uint16_t addr) { | uint16_t addr) { | ||||
| return map->vram_addr(map, addr & 0x1FFFU); | |||||
| return map->vram_addr(data, addr & 0x1FFFU); | |||||
| } | } | ||||
| static inline uint8_t nes_vram_read(nes_mapper* map, | static inline uint8_t nes_vram_read(nes_mapper* map, | ||||
| void* data, | |||||
| uint16_t addr) { | uint16_t addr) { | ||||
| return *(nes_map_vram_addr(map, addr)); | |||||
| return *(nes_map_vram_addr(map, data, addr)); | |||||
| } | } | ||||
| static inline void nes_vram_write(nes_mapper* map, | static inline void nes_vram_write(nes_mapper* map, | ||||
| void* data, | |||||
| uint16_t addr, uint8_t val) { | uint16_t addr, uint8_t val) { | ||||
| *(nes_map_vram_addr(map, addr)) = val; | |||||
| *(nes_map_vram_addr(map, data, addr)) = val; | |||||
| } | } | ||||
| @@ -23,7 +23,8 @@ uint8_t nes_mem_read(nes* sys, uint16_t addr) { | |||||
| val = nes_apu_read(&sys->apu, addr); | val = nes_apu_read(&sys->apu, addr); | ||||
| } else { | } else { | ||||
| val = nes_map_read(sys->cart.mapper, addr); | |||||
| val = nes_map_read(sys->cart.mapper, | |||||
| sys->cart.map_data, addr); | |||||
| } | } | ||||
| return val; | return val; | ||||
| @@ -55,7 +56,8 @@ void nes_mem_write(nes* sys, uint16_t addr, uint8_t val) { | |||||
| nes_apu_write(&sys->apu, addr, val); | nes_apu_write(&sys->apu, addr, val); | ||||
| } else { | } else { | ||||
| nes_map_write(sys->cart.mapper, addr, val); | |||||
| nes_map_write(sys->cart.mapper, sys->cart.map_data, | |||||
| addr, val); | |||||
| } | } | ||||
| } | } | ||||
| @@ -84,6 +86,7 @@ void nes_done(nes* sys) { | |||||
| int nes_setup_cart(nes* sys) { | int nes_setup_cart(nes* sys) { | ||||
| nes_map_set_irq(sys->cart.mapper, nes_irq, sys); | nes_map_set_irq(sys->cart.mapper, nes_irq, sys); | ||||
| sys->ppu.mapper = sys->cart.mapper; | sys->ppu.mapper = sys->cart.mapper; | ||||
| sys->ppu.map_data = sys->cart.map_data; | |||||
| nes_reset(sys); | nes_reset(sys); | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -43,12 +43,14 @@ uint8_t nes_ppu_read(nes_ppu* ppu, uint16_t addr) { | |||||
| if (ppu->addr < nes_ppu_mem_vram_start) { | if (ppu->addr < nes_ppu_mem_vram_start) { | ||||
| PPU_LOG("PPU: CHR MEM READ %04x > %02x\n", ppu->addr, val); | PPU_LOG("PPU: CHR MEM READ %04x > %02x\n", ppu->addr, val); | ||||
| ppu->data = nes_chr_read(ppu->mapper, ppu->addr); | |||||
| ppu->data = nes_chr_read(ppu->mapper, | |||||
| ppu->map_data, | |||||
| ppu->addr); | |||||
| } else if (ppu->addr < nes_ppu_mem_vram_start + | } else if (ppu->addr < nes_ppu_mem_vram_start + | ||||
| nes_ppu_mem_vram_size) { | nes_ppu_mem_vram_size) { | ||||
| VRAM_LOG("PPU: VRAM READ %04x > %02x\n", ppu->addr, val); | VRAM_LOG("PPU: VRAM READ %04x > %02x\n", ppu->addr, val); | ||||
| ppu->data = nes_vram_read( | ppu->data = nes_vram_read( | ||||
| ppu->mapper, | |||||
| ppu->mapper, ppu->map_data, | |||||
| ppu->addr - nes_ppu_mem_vram_start | ppu->addr - nes_ppu_mem_vram_start | ||||
| ); | ); | ||||
| } else if (ppu->addr < nes_ppu_mem_pal_start) { | } else if (ppu->addr < nes_ppu_mem_pal_start) { | ||||
| @@ -186,11 +188,13 @@ void nes_ppu_write(nes_ppu* ppu, uint16_t addr, uint8_t val) { | |||||
| } | } | ||||
| #endif // DEBUG_VRAM | #endif // DEBUG_VRAM | ||||
| // printf("PPU: VRAM %04x < %02x\n", vram_addr, val); | // printf("PPU: VRAM %04x < %02x\n", vram_addr, val); | ||||
| nes_vram_write(ppu->mapper, vram_addr, val); | |||||
| nes_vram_write(ppu->mapper, ppu->map_data, | |||||
| vram_addr, val); | |||||
| } else { | } else { | ||||
| // PPU_LOG("PPU: CHR MEM WRITE %04x > %02x\n", ppu->addr, val); | // PPU_LOG("PPU: CHR MEM WRITE %04x > %02x\n", ppu->addr, val); | ||||
| nes_chr_write(ppu->mapper, ppu->addr, val); | |||||
| nes_chr_write(ppu->mapper, ppu->map_data, | |||||
| ppu->addr, val); | |||||
| } | } | ||||
| ppu->addr += (ppu->control & ppu_Control_VRAM_Inc) ? | ppu->addr += (ppu->control & ppu_Control_VRAM_Inc) ? | ||||
| @@ -212,6 +216,7 @@ void nes_ppu_reset(nes_ppu* ppu) { | |||||
| int nes_ppu_init(nes_ppu* ppu, const nes_cart* cart) { | int nes_ppu_init(nes_ppu* ppu, const nes_cart* cart) { | ||||
| ppu->mapper = cart->mapper; | ppu->mapper = cart->mapper; | ||||
| ppu->map_data = cart->map_data; | |||||
| ppu->status = 0; | ppu->status = 0; | ||||
| ppu->oam_addr = 0; | ppu->oam_addr = 0; | ||||
| ppu->addr = 0; | ppu->addr = 0; | ||||
| @@ -237,7 +242,7 @@ nes_ppu_Result nes_ppu_run(nes_ppu* ppu, int cycles) { | |||||
| ppu->scanline < nes_ppu_render && | ppu->scanline < nes_ppu_render && | ||||
| (ppu->mask & (ppu_Mask_Back | ppu_Mask_Sprite)) && | (ppu->mask & (ppu_Mask_Back | ppu_Mask_Sprite)) && | ||||
| ppu->cycle < 260 && next_cycle >= 260) { | ppu->cycle < 260 && next_cycle >= 260) { | ||||
| ppu->mapper->scanline(ppu->mapper); | |||||
| ppu->mapper->scanline(ppu->map_data); | |||||
| } | } | ||||
| ppu->cycle = next_cycle; | ppu->cycle = next_cycle; | ||||
| @@ -151,6 +151,7 @@ typedef struct { | |||||
| // System Interface | // System Interface | ||||
| struct nes_mapper_t* mapper; | struct nes_mapper_t* mapper; | ||||
| void* map_data; | |||||
| } nes_ppu; | } nes_ppu; | ||||
| uint8_t nes_ppu_read(nes_ppu* ppu, uint16_t addr); | uint8_t nes_ppu_read(nes_ppu* ppu, uint16_t addr); | ||||
| @@ -20,9 +20,9 @@ int load_sram(nes_cart* cart, const char* cart_filename) { | |||||
| int status = -1; | int status = -1; | ||||
| int sram_size = cart->mapper->sram_size ? | int sram_size = cart->mapper->sram_size ? | ||||
| cart->mapper->sram_size(cart->mapper) : 0; | |||||
| cart->mapper->sram_size(cart->map_data) : 0; | |||||
| void* sram = cart->mapper->sram ? | void* sram = cart->mapper->sram ? | ||||
| cart->mapper->sram(cart->mapper) : NULL; | |||||
| cart->mapper->sram(cart->map_data) : NULL; | |||||
| if (sram_size > 0 && NULL != sram) { | if (sram_size > 0 && NULL != sram) { | ||||
| char sram_filename[FILENAME_MAX] = {0}; | char sram_filename[FILENAME_MAX] = {0}; | ||||
| @@ -39,9 +39,9 @@ int save_sram(const nes_cart* cart, const char* cart_filename) { | |||||
| if (NULL != cart->mapper) { | if (NULL != cart->mapper) { | ||||
| int sram_size = cart->mapper->sram_size ? | int sram_size = cart->mapper->sram_size ? | ||||
| cart->mapper->sram_size(cart->mapper) : 0; | |||||
| cart->mapper->sram_size(cart->map_data) : 0; | |||||
| const void* sram = cart->mapper->sram ? | const void* sram = cart->mapper->sram ? | ||||
| cart->mapper->sram(cart->mapper) : NULL; | |||||
| cart->mapper->sram(cart->map_data) : NULL; | |||||
| if (sram_size > 0 && NULL != sram) { | if (sram_size > 0 && NULL != sram) { | ||||
| char sram_filename[FILENAME_MAX] = {0}; | char sram_filename[FILENAME_MAX] = {0}; | ||||
| @@ -230,7 +230,7 @@ int state_size(const nes* sys) { | |||||
| size += szChunkHeader + ram_state_size(sys); | size += szChunkHeader + ram_state_size(sys); | ||||
| // Cart should already be loaded | // Cart should already be loaded | ||||
| size += szChunkHeader + | size += szChunkHeader + | ||||
| sys->cart.mapper->state_size(sys->cart.mapper); | |||||
| sys->cart.mapper->state_size(sys->cart.map_data); | |||||
| return size; | return size; | ||||
| } | } | ||||
| @@ -273,8 +273,10 @@ int state_write(const nes* sys, void* mem, int size) { | |||||
| ptr += ram_state_write(sys, ptr); | ptr += ram_state_write(sys, ptr); | ||||
| const nes_mapper* mapper = sys->cart.mapper; | const nes_mapper* mapper = sys->cart.mapper; | ||||
| ptr = write_header(ptr, tag_mapper, mapper->state_size(mapper)); | |||||
| ptr += mapper->state_write(mapper, ptr); | |||||
| 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); | |||||
| return (ptr - mem); | return (ptr - mem); | ||||
| } | } | ||||
| @@ -336,7 +338,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.mapper, ptr | |||||
| sys->cart.map_data, ptr | |||||
| ); | ); | ||||
| loaded |= Component_Mapper; | loaded |= Component_Mapper; | ||||
| @@ -33,7 +33,7 @@ static SDL_Color nes_palette[64] = { | |||||
| static inline uint8_t* chr_mem(const nes_ppu* ppu, | static inline uint8_t* chr_mem(const nes_ppu* ppu, | ||||
| uint16_t addr) { | uint16_t addr) { | ||||
| return ppu->mapper->chr_addr(ppu->mapper, addr); | |||||
| return ppu->mapper->chr_addr(ppu->map_data, addr); | |||||
| } | } | ||||
| @@ -243,6 +243,7 @@ static inline void render_bg_scanline_area( | |||||
| y = y % 8; | y = y % 8; | ||||
| int bank = (ppu->control & ppu_Control_Back_Bank) ? 0x100 : 0; | int bank = (ppu->control & ppu_Control_Back_Bank) ? 0x100 : 0; | ||||
| const uint8_t* indexes = nes_map_vram_addr(ppu->mapper, | const uint8_t* indexes = nes_map_vram_addr(ppu->mapper, | ||||
| ppu->map_data, | |||||
| page << 10); | page << 10); | ||||
| const uint8_t* attrs = indexes + 960U; | const uint8_t* attrs = indexes + 960U; | ||||
| const uint8_t* index = indexes + | const uint8_t* index = indexes + | ||||