summaryrefslogtreecommitdiff
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
parent2084552c536a8299a3578c8b9b687cff98e6d9a3 (diff)
add basic implementation of ppu write registers
-rw-r--r--ppu.c88
-rw-r--r--ppu.h12
2 files changed, 83 insertions, 17 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}
diff --git a/ppu.h b/ppu.h
index c5483e1..d7cd93c 100644
--- a/ppu.h
+++ b/ppu.h
@@ -17,11 +17,11 @@ struct ppu {
17 uint8_t last_read; 17 uint8_t last_read;
18 18
19 struct ppu_regs { 19 struct ppu_regs {
20 uint16_t v : 15; /* current vram address */ 20 uint16_t v : 15; /* current vram address */
21 uint16_t t : 15; /* temporary vram address */ 21 uint16_t t : 15; /* temporary vram address */
22 uint8_t x : 3; /* fine x scroll */ 22 uint16_t scroll_x : 9; /* x scroll position */
23 uint8_t w : 1; /* first/second write toggle */ 23 uint16_t scroll_y : 9; /* y scroll position */
24 uint8_t padding : 6; 24 uint8_t write_toggle : 1; /* first/second write toggle */
25 } regs; 25 } regs;
26 26
27 struct ppu_ctrl { /* $2000 */ 27 struct ppu_ctrl { /* $2000 */
@@ -31,7 +31,7 @@ struct ppu {
31 uint8_t bg_tile_sel : 1; 31 uint8_t bg_tile_sel : 1;
32 uint8_t sprite_tile_sel : 1; 32 uint8_t sprite_tile_sel : 1;
33 uint8_t inc_mode : 1; 33 uint8_t inc_mode : 1;
34 uint8_t nametable_sel : 2; 34 uint8_t nametable_base : 2;
35 } ctrl; 35 } ctrl;
36 struct ppu_mask { /* $2001 */ 36 struct ppu_mask { /* $2001 */
37 uint8_t colour_emphasis : 3; 37 uint8_t colour_emphasis : 3;