| @@ -19,7 +19,7 @@ int nes_cart_init_mem(nes_cart* cart, void* mem, int len) { | |||||
| if (0 == status) { | if (0 == status) { | ||||
| int prg_size = ines_prg_rom_chunk * hdr->prg_size_lsb; | int prg_size = ines_prg_rom_chunk * hdr->prg_size_lsb; | ||||
| if (prg_size > nes_mem_rom_size || prg_size <= 0) { | |||||
| if (prg_size <= 0) { | |||||
| INES_ERR("Bad program ROM size: %d / %d", | INES_ERR("Bad program ROM size: %d / %d", | ||||
| prg_size, nes_mem_rom_size); | prg_size, nes_mem_rom_size); | ||||
| status = -1; | status = -1; | ||||
| @@ -32,19 +32,10 @@ int nes_cart_init_mem(nes_cart* cart, void* mem, int len) { | |||||
| if (0 == status) { | if (0 == status) { | ||||
| int chr_size = ines_chr_rom_chunk * hdr->chr_size_lsb; | int chr_size = ines_chr_rom_chunk * hdr->chr_size_lsb; | ||||
| if (chr_size > nes_ppu_mem_size || chr_size <= 0) { | |||||
| INES_ERR("Bad sprite ROM size: %d / %d", | |||||
| chr_size, nes_ppu_mem_size); | |||||
| status = -1; | |||||
| } else { | |||||
| cart->chr_rom = ptr; | |||||
| cart->chr_rom_size = chr_size; | |||||
| } | |||||
| cart->chr_rom = ptr; | |||||
| cart->chr_rom_size = chr_size; | |||||
| ptr += chr_size; | ptr += chr_size; | ||||
| } | |||||
| if (0 == status) { | |||||
| int index = (hdr->flags_6 & ines_Mapper_Nibble_Lo) >> 4 | | int index = (hdr->flags_6 & ines_Mapper_Nibble_Lo) >> 4 | | ||||
| (hdr->flags_7 & ines_Mapper_Nibble_Hi); | (hdr->flags_7 & ines_Mapper_Nibble_Hi); | ||||
| cart->mapper = nes_mappers[index]; | cart->mapper = nes_mappers[index]; | ||||
| @@ -5,9 +5,6 @@ | |||||
| #include <stdio.h> | #include <stdio.h> | ||||
| #define nes_mem_wram_size (0x2000U) | |||||
| typedef enum { | typedef enum { | ||||
| Cart_Flag_Vertical = 0b0, | Cart_Flag_Vertical = 0b0, | ||||
| Cart_Flag_Horizontal = 0b1, | Cart_Flag_Horizontal = 0b1, | ||||
| @@ -18,7 +15,6 @@ typedef struct nes_cart_t { | |||||
| int prg_rom_size; | int prg_rom_size; | ||||
| uint8_t* chr_rom; | uint8_t* chr_rom; | ||||
| int chr_rom_size; | int chr_rom_size; | ||||
| uint8_t wram[nes_mem_wram_size]; | |||||
| nes_Cart_Flags flags; | nes_Cart_Flags flags; | ||||
| struct nes_mapper_t* mapper; | struct nes_mapper_t* mapper; | ||||
| @@ -1,2 +1,2 @@ | |||||
| #include "../nes.h" | |||||
| #include "../mapper.h" | #include "../mapper.h" | ||||
| #include "../cart.h" | |||||
| @@ -1,72 +1,214 @@ | |||||
| #include <stdlib.h> | |||||
| #include "map.h" | #include "map.h" | ||||
| #define MAP_LOG(fmt, ...) //printf("MAP: " fmt "\n" __VA_OPT__(,) __VA_ARGS__) | |||||
| typedef struct { | typedef struct { | ||||
| // TODO: Does this even support CHR ROM? | |||||
| uint8_t* prg_rom; | uint8_t* prg_rom; | ||||
| int prg_rom_size; | int prg_rom_size; | ||||
| uint8_t* prg_ram; | |||||
| int prg_ram_size; | |||||
| uint8_t* chr_rom; | |||||
| int chr_rom_size; | |||||
| uint8_t reg_shift; | uint8_t reg_shift; | ||||
| uint8_t reg_n_shift; | |||||
| uint8_t reg_control; | uint8_t reg_control; | ||||
| uint8_t reg_chr_0; | uint8_t reg_chr_0; | ||||
| uint8_t reg_chr_1; | uint8_t reg_chr_1; | ||||
| uint8_t reg_prg; | uint8_t reg_prg; | ||||
| uint8_t* chr_bank[2]; | |||||
| uint8_t* vram_bank[4]; | |||||
| uint8_t* prg_bank[2]; | |||||
| uint8_t vram[2][nes_vram_page_size]; | |||||
| uint8_t chr[32][nes_chr_page_size]; | |||||
| uint8_t wram[nes_mem_wram_size]; | |||||
| } mmc1_mapper; | } mmc1_mapper; | ||||
| /* | |||||
| int mmc1_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| nrom_mapper* map = malloc(sizeof(nrom_mapper)); | |||||
| static void mmc1_update_vram(mmc1_mapper* map) { | |||||
| // VRAM selection | |||||
| int nametable = (map->reg_control & 0b11); | |||||
| if (nametable == 0) { | |||||
| MAP_LOG("VRAM: 1-screen, lower bank"); | |||||
| map->vram_bank[0] = map->vram_bank[1] = | |||||
| map->vram_bank[2] = map->vram_bank[3] = | |||||
| map->vram[0]; | |||||
| } else if (nametable == 1) { | |||||
| MAP_LOG("VRAM: 1-screen, upper bank"); | |||||
| map->vram_bank[0] = map->vram_bank[1] = | |||||
| map->vram_bank[2] = map->vram_bank[3] = | |||||
| map->vram[1]; | |||||
| } else if (nametable == 2) { | |||||
| MAP_LOG("VRAM: Vertical mirroring"); | |||||
| map->vram_bank[0] = map->vram_bank[2] = map->vram[0]; | |||||
| map->vram_bank[1] = map->vram_bank[3] = map->vram[1]; | |||||
| } else if (nametable == 3) { | |||||
| MAP_LOG("VRAM: Horizontal mirroring"); | |||||
| map->vram_bank[0] = map->vram_bank[1] = map->vram[0]; | |||||
| map->vram_bank[2] = map->vram_bank[3] = map->vram[1]; | |||||
| } | |||||
| } | |||||
| static void mmc1_update_chr(mmc1_mapper* map) { | |||||
| // CHR RAM selection | |||||
| 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]; | |||||
| map->chr_bank[1] = map->chr[bank + 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]; | |||||
| map->chr_bank[1] = map->chr[map->reg_chr_1]; | |||||
| } | |||||
| } | |||||
| static void mmc1_update_prg(mmc1_mapper* map) { | |||||
| // PRG ROM selection | |||||
| int mode = (map->reg_control >> 2) & 3; | |||||
| int bank = (map->reg_prg & 0b01111); | |||||
| if (!(mode & 0b10)) { | |||||
| bank = (bank & 0b01110); | |||||
| MAP_LOG("PRG: 32 KB %d + %d", bank, bank + 1); | |||||
| bank *= nes_prg_rom_page_size; | |||||
| map->prg_bank[0] = &map->prg_rom[bank]; | |||||
| map->prg_bank[1] = &map->prg_rom[bank + | |||||
| nes_prg_rom_page_size]; | |||||
| } else if (mode == 2) { | |||||
| MAP_LOG("PRG: %d + %d", 0, bank); | |||||
| bank *= nes_prg_rom_page_size; | |||||
| map->prg_bank[0] = &map->prg_rom[0]; | |||||
| map->prg_bank[1] = &map->prg_rom[bank]; | |||||
| } else if (mode == 3) { | |||||
| MAP_LOG("PRG: %d + %d", bank, (map->prg_rom_size / | |||||
| nes_prg_rom_page_size) - 1); | |||||
| bank *= nes_prg_rom_page_size; | |||||
| map->prg_bank[0] = &map->prg_rom[bank]; | |||||
| map->prg_bank[1] = &map->prg_rom[map->prg_rom_size - | |||||
| nes_prg_rom_page_size]; | |||||
| } | |||||
| } | |||||
| static void mmc1_reset(nes_mapper* nes_map) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| map->reg_shift = 0b10000; | |||||
| map->reg_control = 0; | |||||
| map->reg_chr_0 = 0; | |||||
| map->reg_chr_1 = 0; | |||||
| map->reg_prg = 0; | |||||
| mmc1_update_prg(map); | |||||
| mmc1_update_chr(map); | |||||
| mmc1_update_vram(map); | |||||
| } | |||||
| static int mmc1_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| mmc1_mapper* map = calloc(1, sizeof(mmc1_mapper)); | |||||
| nes_map->data = map; | 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_size = cart->prg_rom_size; | map->prg_rom_size = cart->prg_rom_size; | ||||
| map->chr_rom = cart->chr_rom; | |||||
| map->chr_rom_size = cart->chr_rom_size; | |||||
| map->prg_ram = cart->wram; | |||||
| map->prg_ram_size = nes_mem_wram_size; | |||||
| map->shift_reg = 0; | |||||
| mmc1_reset(nes_map); | |||||
| } | } | ||||
| return (NULL == map ? -1 : 0); | return (NULL == map ? -1 : 0); | ||||
| } | } | ||||
| void nrom_done(nes_mapper* nes_map) { | |||||
| static void mmc1_done(nes_mapper* nes_map) { | |||||
| free(nes_map->data); | free(nes_map->data); | ||||
| } | } | ||||
| static inline uint8_t* nrom_prg_addr(nrom_mapper* map, | |||||
| static inline uint8_t* mmc1_prg_addr(mmc1_mapper* map, | |||||
| uint16_t addr) { | uint16_t addr) { | ||||
| if (addr > map->prg_rom_size) { | |||||
| addr &= 0x3FFF; | |||||
| int bank = (addr >> 14) & 1; | |||||
| addr &= 0x3FFFU; | |||||
| return &map->prg_bank[bank][addr]; | |||||
| } | |||||
| static inline uint8_t* mmc1_wram_addr(mmc1_mapper* map, | |||||
| uint16_t addr) { | |||||
| return &(map->wram[addr & 0x1FFFU]); | |||||
| } | |||||
| static uint8_t mmc1_read(nes_mapper* map, uint16_t addr) { | |||||
| uint8_t val = 0; | |||||
| if (addr >= nes_mem_rom_start) { | |||||
| val = *(mmc1_prg_addr((mmc1_mapper*)map->data, addr)); | |||||
| } else if (addr >= nes_mem_wram_start) { | |||||
| val = *(mmc1_wram_addr((mmc1_mapper*)map->data, addr)); | |||||
| } | } | ||||
| return &(map->prg_rom[addr]); | |||||
| return val; | |||||
| } | } | ||||
| uint8_t nrom_prg_read(nes_mapper* map, uint16_t addr) { | |||||
| return *(nrom_prg_addr((nrom_mapper*)map->data, addr)); | |||||
| static void mmc1_write(nes_mapper* nes_map, | |||||
| uint16_t addr, uint8_t val) { | |||||
| mmc1_mapper* map = (mmc1_mapper*)nes_map->data; | |||||
| if (addr >= nes_mem_rom_start) { | |||||
| MAP_LOG("Write $%04x < %02x", addr, val); | |||||
| if (val & 0x80U) { | |||||
| MAP_LOG("Resetting"); | |||||
| map->reg_shift = 0b10000; | |||||
| map->reg_control |= 0b01100; | |||||
| mmc1_update_prg(map); | |||||
| } else { | |||||
| // TODO: Handle consective-cycle writes? | |||||
| int done = (map->reg_shift & 1); | |||||
| map->reg_shift = (map->reg_shift >> 1) | | |||||
| ((val & 1) << 4); | |||||
| if (done) { | |||||
| int reg = (addr >> 13) & 0b11; | |||||
| if (reg == 0) { | |||||
| MAP_LOG("Control %02x", map->reg_shift); | |||||
| map->reg_control = map->reg_shift; | |||||
| mmc1_update_chr(map); | |||||
| mmc1_update_vram(map); | |||||
| mmc1_update_prg(map); | |||||
| } else if (reg == 1) { | |||||
| MAP_LOG("CHR_0 %02x", map->reg_shift); | |||||
| map->reg_chr_0 = map->reg_shift; | |||||
| mmc1_update_chr(map); | |||||
| } else if (reg == 2) { | |||||
| MAP_LOG("CHR_1 %02x", map->reg_shift); | |||||
| map->reg_chr_1 = map->reg_shift; | |||||
| mmc1_update_chr(map); | |||||
| } else { | |||||
| MAP_LOG("PRG %02x", map->reg_shift); | |||||
| map->reg_prg = map->reg_shift; | |||||
| mmc1_update_prg(map); | |||||
| } | |||||
| map->reg_shift = 0b10000; | |||||
| } | |||||
| } | |||||
| } else if ( addr < nes_mem_rom_start && | |||||
| addr >= nes_mem_wram_start) { | |||||
| *(mmc1_wram_addr(map, addr)) = val; | |||||
| } | |||||
| } | } | ||||
| void nrom_prg_write(nes_mapper* map, uint16_t addr, uint8_t val) { | |||||
| // No ROM writes. | |||||
| static uint8_t* mmc1_chr_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| int page = (addr >> 12) & 1; | |||||
| addr &= 0xFFFU; | |||||
| return &((mmc1_mapper*)nes_map->data)->chr_bank[page][addr]; | |||||
| } | } | ||||
| uint8_t* nrom_chr_addr(nes_mapper* nes_map, uint16_t addr) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | |||||
| return &map->chr_rom[addr % map->chr_rom_size]; | |||||
| static uint8_t* mmc1_vram_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| int page = (addr >> 10) & 3; | |||||
| int loc = addr & 0x3FFU; | |||||
| // MAP_LOG("VRAM $%04x -> %p", addr, ((mmc1_mapper*)nes_map->data)->vram_bank[page]); | |||||
| return &((mmc1_mapper*)nes_map->data)->vram_bank[page][loc]; | |||||
| } | } | ||||
| */ | |||||
| nes_mapper mapper_mmc1 = { | nes_mapper mapper_mmc1 = { | ||||
| /* | |||||
| .init = mmc1_init, | .init = mmc1_init, | ||||
| .reset = mmc1_reset, | |||||
| .done = mmc1_done, | .done = mmc1_done, | ||||
| .prg_read = mmc1_prg_read, | |||||
| .prg_write = mmc1_prg_write, | |||||
| .read = mmc1_read, | |||||
| .write = mmc1_write, | |||||
| .chr_addr = mmc1_chr_addr, | .chr_addr = mmc1_chr_addr, | ||||
| .vram_addr = mmc1_chr_addr, | |||||
| */ | |||||
| .vram_addr = mmc1_vram_addr, | |||||
| }; | }; | ||||
| @@ -6,16 +6,17 @@ | |||||
| typedef struct { | typedef struct { | ||||
| uint8_t* prg_rom; | uint8_t* prg_rom; | ||||
| int prg_rom_size; | int prg_rom_size; | ||||
| uint8_t* prg_ram; | |||||
| int prg_ram_size; | |||||
| uint8_t* chr_rom; | uint8_t* chr_rom; | ||||
| int chr_rom_size; | int chr_rom_size; | ||||
| 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]; | |||||
| } nrom_mapper; | } nrom_mapper; | ||||
| int nrom_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| static void nrom_reset(nes_mapper* nes_map) {} | |||||
| static int 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; | nes_map->data = map; | ||||
| if (NULL != map) { | if (NULL != map) { | ||||
| @@ -23,39 +24,54 @@ int nrom_init(nes_mapper* nes_map, nes_cart* cart) { | |||||
| map->prg_rom_size = cart->prg_rom_size; | map->prg_rom_size = cart->prg_rom_size; | ||||
| map->chr_rom = cart->chr_rom; | map->chr_rom = cart->chr_rom; | ||||
| map->chr_rom_size = cart->chr_rom_size; | map->chr_rom_size = cart->chr_rom_size; | ||||
| map->prg_ram = cart->wram; | |||||
| map->prg_ram_size = nes_mem_wram_size; | |||||
| map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | map->mirror = (cart->flags & Cart_Flag_Horizontal) ? 0 : 1; | ||||
| } | } | ||||
| return (NULL == map ? -1 : 0); | return (NULL == map ? -1 : 0); | ||||
| } | } | ||||
| void nrom_done(nes_mapper* nes_map) { | |||||
| static void nrom_done(nes_mapper* nes_map) { | |||||
| free(nes_map->data); | free(nes_map->data); | ||||
| } | } | ||||
| static inline uint8_t* nrom_prg_addr(nrom_mapper* map, | static inline uint8_t* nrom_prg_addr(nrom_mapper* map, | ||||
| uint16_t addr) { | uint16_t addr) { | ||||
| addr &= 0x7FFFU; | |||||
| if (addr > map->prg_rom_size) { | if (addr > map->prg_rom_size) { | ||||
| addr &= 0x3FFF; | addr &= 0x3FFF; | ||||
| } | } | ||||
| return &(map->prg_rom[addr]); | return &(map->prg_rom[addr]); | ||||
| } | } | ||||
| uint8_t nrom_prg_read(nes_mapper* map, uint16_t addr) { | |||||
| return *(nrom_prg_addr((nrom_mapper*)map->data, addr)); | |||||
| static inline uint8_t* nrom_wram_addr(nrom_mapper* map, | |||||
| uint16_t addr) { | |||||
| return &(map->wram[addr & 0x1FFFU]); | |||||
| } | |||||
| static uint8_t nrom_read(nes_mapper* map, uint16_t addr) { | |||||
| uint8_t val = 0; | |||||
| if (addr >= nes_mem_rom_start) { | |||||
| val = *(nrom_prg_addr((nrom_mapper*)map->data, addr)); | |||||
| } else if (addr >= nes_mem_wram_start) { | |||||
| val = *(nrom_wram_addr((nrom_mapper*)map->data, addr)); | |||||
| } | |||||
| return val; | |||||
| } | } | ||||
| void nrom_prg_write(nes_mapper* map, uint16_t addr, uint8_t val) { | |||||
| // No ROM writes. | |||||
| static void nrom_write(nes_mapper* map, | |||||
| uint16_t addr, uint8_t val) { | |||||
| if (addr < nes_mem_rom_start && addr >= nes_mem_wram_start) { | |||||
| *(nrom_wram_addr((nrom_mapper*)map->data, addr)) = val; | |||||
| } | |||||
| } | } | ||||
| uint8_t* nrom_chr_addr(nes_mapper* nes_map, uint16_t addr) { | |||||
| static uint8_t* nrom_chr_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | nrom_mapper* map = (nrom_mapper*)nes_map->data; | ||||
| return &map->chr_rom[addr % map->chr_rom_size]; | return &map->chr_rom[addr % map->chr_rom_size]; | ||||
| } | } | ||||
| uint8_t* nrom_vram_addr(nes_mapper* nes_map, uint16_t addr) { | |||||
| static uint8_t* nrom_vram_addr(nes_mapper* nes_map, | |||||
| uint16_t addr) { | |||||
| nrom_mapper* map = (nrom_mapper*)nes_map->data; | nrom_mapper* map = (nrom_mapper*)nes_map->data; | ||||
| int page = addr >> 10U; | int page = addr >> 10U; | ||||
| page >>= map->mirror; | page >>= map->mirror; | ||||
| @@ -65,9 +81,10 @@ uint8_t* nrom_vram_addr(nes_mapper* nes_map, uint16_t addr) { | |||||
| nes_mapper mapper_nrom = { | nes_mapper mapper_nrom = { | ||||
| .init = nrom_init, | .init = nrom_init, | ||||
| .reset = nrom_reset, | |||||
| .done = nrom_done, | .done = nrom_done, | ||||
| .prg_read = nrom_prg_read, | |||||
| .prg_write = nrom_prg_write, | |||||
| .read = nrom_read, | |||||
| .write = nrom_write, | |||||
| .chr_addr = nrom_chr_addr, | .chr_addr = nrom_chr_addr, | ||||
| .vram_addr = nrom_vram_addr, | .vram_addr = nrom_vram_addr, | ||||
| }; | }; | ||||
| @@ -4,17 +4,19 @@ | |||||
| #include <stdint.h> | #include <stdint.h> | ||||
| #define nes_chr_page_size (0x1000U) | |||||
| #define nes_vram_page_size (0x0400U) | |||||
| #define nes_chr_page_size (0x1000U) | |||||
| #define nes_vram_page_size (0x0400U) | |||||
| #define nes_prg_rom_page_size (0x4000U) | |||||
| struct nes_cart_t; | struct nes_cart_t; | ||||
| typedef struct nes_mapper_t { | typedef struct nes_mapper_t { | ||||
| int (*init)(struct nes_mapper_t*, struct nes_cart_t* cart); | int (*init)(struct nes_mapper_t*, struct nes_cart_t* cart); | ||||
| void (*reset)(struct nes_mapper_t*); | |||||
| void (*done)(struct nes_mapper_t*); | void (*done)(struct nes_mapper_t*); | ||||
| uint8_t (*prg_read)(struct nes_mapper_t*, uint16_t addr); | |||||
| void (*prg_write)(struct nes_mapper_t*, uint16_t addr, uint8_t val); | |||||
| uint8_t (*read)(struct nes_mapper_t*, uint16_t addr); | |||||
| void (*write)(struct nes_mapper_t*, uint16_t addr, uint8_t val); | |||||
| uint8_t* (*chr_addr)(struct nes_mapper_t*, uint16_t addr); | uint8_t* (*chr_addr)(struct nes_mapper_t*, uint16_t addr); | ||||
| uint8_t* (*vram_addr)(struct nes_mapper_t*, uint16_t addr); | uint8_t* (*vram_addr)(struct nes_mapper_t*, uint16_t addr); | ||||
| void* data; | void* data; | ||||
| @@ -25,19 +27,23 @@ static inline int nes_map_init(nes_mapper* map, | |||||
| 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_done(nes_mapper* map) { | static inline void nes_map_done(nes_mapper* map) { | ||||
| map->done(map); | map->done(map); | ||||
| } | } | ||||
| static inline uint8_t nes_map_prg_read(nes_mapper* map, | |||||
| static inline uint8_t nes_map_read(nes_mapper* map, | |||||
| uint16_t addr) { | uint16_t addr) { | ||||
| return map->prg_read(map, addr); | |||||
| return map->read(map, addr); | |||||
| } | } | ||||
| static inline void nes_map_prg_write(nes_mapper* map, | |||||
| static inline void nes_map_write(nes_mapper* map, | |||||
| uint16_t addr, | uint16_t addr, | ||||
| uint8_t val) { | uint8_t val) { | ||||
| map->prg_write(map, addr, val); | |||||
| map->write(map, addr, val); | |||||
| } | } | ||||
| static inline uint8_t* nes_map_chr_addr(nes_mapper* map, | static inline uint8_t* nes_map_chr_addr(nes_mapper* map, | ||||
| @@ -22,16 +22,8 @@ uint8_t nes_mem_read(nes* sys, uint16_t addr) { | |||||
| } else if (addr < nes_mem_exp_start) { | } else if (addr < nes_mem_exp_start) { | ||||
| val = nes_apu_read(&sys->apu, addr); | val = nes_apu_read(&sys->apu, addr); | ||||
| } else if (addr < nes_mem_wram_start) { | |||||
| // TODO: Expansion ROM support | |||||
| } else if (addr < nes_mem_rom_start) { | |||||
| // TODO: Send to mapper? | |||||
| val = sys->cart.wram[addr - nes_mem_wram_start]; | |||||
| } else { | } else { | ||||
| val = nes_map_prg_read(sys->cart.mapper, | |||||
| addr - nes_mem_rom_start); | |||||
| val = nes_map_read(sys->cart.mapper, addr); | |||||
| } | } | ||||
| return val; | return val; | ||||
| @@ -61,15 +53,8 @@ void nes_mem_write(nes* sys, uint16_t addr, uint8_t val) { | |||||
| } else if (addr < nes_mem_exp_start) { | } else if (addr < nes_mem_exp_start) { | ||||
| nes_apu_write(&sys->apu, addr, val); | nes_apu_write(&sys->apu, addr, val); | ||||
| } else if (addr < nes_mem_wram_start) { | |||||
| // No ROM writes | |||||
| } else if (addr < nes_mem_rom_start) { | |||||
| sys->cart.wram[addr - nes_mem_wram_start] = val; | |||||
| } else { | } else { | ||||
| nes_map_prg_write(sys->cart.mapper, | |||||
| addr - nes_mem_rom_start, val); | |||||
| nes_map_write(sys->cart.mapper, addr, val); | |||||
| } | } | ||||
| } | } | ||||
| @@ -23,7 +23,7 @@ | |||||
| #define nes_mem_exp_start (0x4020U) | #define nes_mem_exp_start (0x4020U) | ||||
| #define nes_mem_exp_size (0x1FE0U) | #define nes_mem_exp_size (0x1FE0U) | ||||
| #define nes_mem_wram_start (0x6000U) | #define nes_mem_wram_start (0x6000U) | ||||
| //#define nes_mem_wram_size (0x2000U) | |||||
| #define nes_mem_wram_size (0x2000U) | |||||
| #define nes_mem_rom_start (0x8000U) | #define nes_mem_rom_start (0x8000U) | ||||
| #define nes_mem_rom_size (0x8000U) | #define nes_mem_rom_size (0x8000U) | ||||
| @@ -159,6 +159,10 @@ 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, vram_addr, val); | ||||
| } else { | |||||
| // printf("PPU: CHR MEM WRITE %04x > %02x\n", ppu->addr, val); | |||||
| *(nes_map_chr_addr(ppu->mapper, ppu->addr)) = val; | |||||
| } | } | ||||
| ppu->addr += (ppu->control & ppu_Control_VRAM_Inc) ? | ppu->addr += (ppu->control & ppu_Control_VRAM_Inc) ? | ||||