diff options
Diffstat (limited to 'memory.c')
| -rw-r--r-- | memory.c | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/memory.c b/memory.c new file mode 100644 index 0000000..cb29344 --- /dev/null +++ b/memory.c @@ -0,0 +1,95 @@ + + + +static uint8_t memory_read(struct nes_state *restrict state, uint32_t offset) { + state->cycle++; + for(uint32_t i = 0; i < 3; ++i) { + ppu_tick(state); + } + + if(offset < 0x2000) { + return state->ram[offset & 0x07ff]; + } else if(offset < 0x4000) { + switch(offset & 7) { + case 2: return ppu_read_2002(state); + case 4: return ppu_read_2004(state); + case 7: return ppu_read_2007(state); + default: return 0; + } + } else if(offset < 0x4020) { + // TODO: APU and I/O reads + return 0; + } else if(offset >= 0x6000) { + return state->mapper.read(state, offset); + } else { + return 0; + } +} + +static void memory_write(struct nes_state *restrict state, uint32_t offset, uint8_t value) { + state->cycle++; + for(uint32_t i = 0; i < 3; ++i) { + ppu_tick(state); + } + + if(offset < 0x2000) { + state->ram[offset & 0x07ff] = value; + } else if(offset < 0x4000) { + switch(offset & 7) { + case 0: state->ppu.ctrl = value; break; + case 1: state->ppu.mask = value; break; + case 3: ppu_write_2003(state, value); break; + case 4: ppu_write_2004(state, value); break; + case 5: ppu_write_2005(state, value); break; + case 6: ppu_write_2006(state, value); break; + case 7: ppu_write_2007(state, value); break; + default: break; + } + } else if(offset == 0x4014) { + ppu_dma_4014(state, value); + } else if(offset < 0x4020) { + // TODO: APU and I/O writes + } else if(offset >= 0x6000) { + state->mapper.write(state, offset, value); + } +} + +static uint8_t memory_read_dma(struct nes_state *restrict state, uint32_t offset) { + // Do not tick CPU/PPU/APU — caller handles timing + if(offset < 0x2000) { + return state->ram[offset & 0x07ff]; + } else if(offset < 0x4000) { + // PPU register reads are ignored during DMA + return 0; + } else if(offset < 0x4020) { + // APU and I/O — usually ignored or blocked during DMA + return 0; + } else if(offset >= 0x6000) { + return state->mapper.read(state, offset); + } else { + return 0; + } +} + +static uint8_t memory_read_dummy(struct nes_state *restrict state, uint32_t offset) { + state->cycle++; + for(uint32_t i = 0; i < 3; ++i) { + ppu_tick(state); + } + + if(offset < 0x2000) { + return 0; + } else if(offset < 0x4000) { + switch(offset & 7) { + case 2: return ppu_read_2002(state); + case 7: return ppu_read_2007(state); + default: return 0; + } + } else if(offset < 0x4020) { + return 0; + } else if(offset >= 0x6000) { + return state->mapper.read(state, offset); + } else { + return 0; + } +} |
