summaryrefslogtreecommitdiff
path: root/ppu.c
diff options
context:
space:
mode:
authorvin <git@vineetk.net>2024-09-01 19:44:40 -0400
committervin <git@vineetk.net>2024-09-01 19:44:40 -0400
commite14776a4739f525ac2c5531fca94142454683563 (patch)
tree8481e175e6308170006c79068dea7ad604fd3d42 /ppu.c
parent2084552c536a8299a3578c8b9b687cff98e6d9a3 (diff)
add basic implementation of ppu write registers
Diffstat (limited to 'ppu.c')
-rw-r--r--ppu.c88
1 files changed, 77 insertions, 11 deletions
diff --git a/ppu.c b/ppu.c
index 52837ad..866e382 100644
--- a/ppu.c
+++ b/ppu.c
@@ -38,6 +38,10 @@ void
38ppu_tick(void) 38ppu_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)
84void 87void
85ppu_write(uint16_t addr, uint8_t byte) 88ppu_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}