diff options
Diffstat (limited to 'ppu.c')
| -rw-r--r-- | ppu.c | 88 |
1 files changed, 77 insertions, 11 deletions
| @@ -38,6 +38,10 @@ void | |||
| 38 | ppu_tick(void) | 38 | ppu_tick(void) |
| 39 | { | 39 | { |
| 40 | ppu.cycles++; | 40 | ppu.cycles++; |
| 41 | |||
| 42 | if (ppu.cycles > 256 && ppu.cycles <= 320) | ||
| 43 | ppu.oam_addr = 0; | ||
| 44 | |||
| 41 | if (ppu.cycles >= 341) { | 45 | if (ppu.cycles >= 341) { |
| 42 | ppu.cycles -= 341; | 46 | ppu.cycles -= 341; |
| 43 | ppu.scanlines++; | 47 | ppu.scanlines++; |
| @@ -58,23 +62,22 @@ ppu_read(uint16_t addr) | |||
| 58 | | (ppu.status.sprite_overflow << 5); | 62 | | (ppu.status.sprite_overflow << 5); |
| 59 | 63 | ||
| 60 | ppu.status.vblank = 0; | 64 | ppu.status.vblank = 0; |
| 61 | ppu.regs.w = 0; | 65 | ppu.regs.write_toggle = 0; |
| 62 | 66 | ||
| 63 | return tmp; | 67 | return tmp; |
| 64 | case 0x2004: | 68 | case 0x2004: |
| 65 | return ppu.oam[ppu.oam_addr]; | 69 | return ppu.oam[ppu.oam_addr]; |
| 66 | case 0x2007: | 70 | case 0x2007: |
| 67 | vram_addr_inc(); | 71 | tmp = ppu.last_read; |
| 68 | 72 | ||
| 69 | if (addr <= 0x1fff) { | 73 | if (addr <= 0x1fff) |
| 70 | tmp = ppu.last_read; | ||
| 71 | ppu.last_read = ppu.rom->chr_rom[ppu.regs.v]; | 74 | ppu.last_read = ppu.rom->chr_rom[ppu.regs.v]; |
| 72 | return tmp; | 75 | else if (addr <= 0x2fff) |
| 73 | } else if (addr <= 0x2fff) { | ||
| 74 | tmp = ppu.last_read; | ||
| 75 | ppu.last_read = ppu.vram[vram_addr_mirror(addr)]; | 76 | ppu.last_read = ppu.vram[vram_addr_mirror(addr)]; |
| 76 | return tmp; | 77 | |
| 77 | } | 78 | vram_addr_inc(); |
| 79 | |||
| 80 | return tmp; | ||
| 78 | default: | 81 | default: |
| 79 | fprintf(stderr, "Invalid PPU read at address $%04\n", addr); | 82 | fprintf(stderr, "Invalid PPU read at address $%04\n", addr); |
| 80 | return 0; | 83 | return 0; |
| @@ -84,7 +87,70 @@ ppu_read(uint16_t addr) | |||
| 84 | void | 87 | void |
| 85 | ppu_write(uint16_t addr, uint8_t byte) | 88 | ppu_write(uint16_t addr, uint8_t byte) |
| 86 | { | 89 | { |
| 87 | static uint8_t prev; | 90 | switch (addr) { |
| 91 | case 0x2000: | ||
| 92 | ppu.ctrl.nametable_base = byte & 3; | ||
| 93 | ppu.ctrl.inc_mode = byte & (1 << 2); | ||
| 94 | ppu.ctrl.sprite_tile_sel = byte & (1 << 3); | ||
| 95 | ppu.ctrl.bg_tile_sel = byte & (1 << 4); | ||
| 96 | ppu.ctrl.sprite_height = byte & (1 << 5); | ||
| 97 | ppu.ctrl.master_slave = byte & (1 << 6); | ||
| 98 | ppu.ctrl.nmi_enable = byte & (1 << 7); | ||
| 99 | |||
| 100 | if (ppu.ctrl.nametable_base & 1) | ||
| 101 | ppu.regs.scroll_x += 256; | ||
| 102 | if (ppu.ctrl.nametable_base & 2) | ||
| 103 | ppu.regs.scroll_y += 240; | ||
| 104 | |||
| 105 | /* | ||
| 106 | * TODO: send NMI if vblank flag still set and nmi_enable | ||
| 107 | * changes from 0 to 1 | ||
| 108 | */ | ||
| 109 | break; | ||
| 110 | case 0x2001: | ||
| 111 | ppu.mask.grayscale = byte & 1; | ||
| 112 | ppu.mask.bg_left_enable = byte & (1 << 1); | ||
| 113 | ppu.mask.sprite_left_enable = byte & (1 << 2); | ||
| 114 | ppu.mask.bg_enable = byte & (1 << 3); | ||
| 115 | ppu.mask.sprite_enable = byte & (1 << 4); | ||
| 116 | ppu.mask.colour_emphasis = byte & (1 << 5); | ||
| 117 | |||
| 118 | break; | ||
| 119 | case 0x2003: | ||
| 120 | ppu.oam_addr = byte; | ||
| 121 | |||
| 122 | break; | ||
| 123 | case 0x2004: | ||
| 124 | ppu.oam[ppu.oam_addr++] = byte; | ||
| 125 | |||
| 126 | break; | ||
| 127 | case 0x2005: | ||
| 128 | if (ppu.regs.write_toggle == 0) | ||
| 129 | ppu.regs.scroll_x = byte; | ||
| 130 | else | ||
| 131 | ppu.regs.scroll_y = byte; | ||
| 132 | ppu.regs.write_toggle = !ppu.regs.write_toggle; | ||
| 88 | 133 | ||
| 89 | prev = byte; | 134 | break; |
| 135 | case 0x2006: | ||
| 136 | if (ppu.regs.write_toggle == 0) | ||
| 137 | ppu.regs.v = (byte << 8); | ||
| 138 | else { | ||
| 139 | ppu.regs.v |= byte; | ||
| 140 | ppu.regs.v &= 0x3fff; | ||
| 141 | } | ||
| 142 | ppu.regs.write_toggle = !ppu.regs.write_toggle; | ||
| 143 | |||
| 144 | break; | ||
| 145 | case 0x2007: | ||
| 146 | ppu.vram[ppu.regs.v] = byte; | ||
| 147 | vram_addr_inc(); | ||
| 148 | |||
| 149 | break; | ||
| 150 | case 0x4014: | ||
| 151 | break; | ||
| 152 | default: | ||
| 153 | fprintf(stderr, "Invalid PPU write at address $%04X\n", addr); | ||
| 154 | return; | ||
| 155 | } | ||
| 90 | } | 156 | } |
