aboutsummaryrefslogtreecommitdiffstats
path: root/src/devices.c
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2023-08-30 20:31:08 +0200
committerBad Diode <bd@badd10de.dev>2023-08-30 20:31:08 +0200
commit874ae39b6074da2778b72bcbaf6c7c7ef19aa233 (patch)
tree5ed5989ac78df0fea75c88c0b63f9a1a5ead6f53 /src/devices.c
parentbe57c62f4633623005b5ac463ce7f65e8761d9bd (diff)
downloaduxngba-874ae39b6074da2778b72bcbaf6c7c7ef19aa233.tar.gz
uxngba-874ae39b6074da2778b72bcbaf6c7c7ef19aa233.zip
Remove previous uxn core
Diffstat (limited to 'src/devices.c')
-rw-r--r--src/devices.c515
1 files changed, 265 insertions, 250 deletions
diff --git a/src/devices.c b/src/devices.c
index e031a85..c65d79b 100644
--- a/src/devices.c
+++ b/src/devices.c
@@ -1,290 +1,305 @@
1static time_t seconds = 0; 1static time_t seconds = 0;
2 2
3int 3#define RAM_PAGES 0x10
4uxn_halt(Uxn *u, u8 instr, u8 err, u16 addr) { 4
5 (void)u; 5void
6 txt_printf("HALTED\n"); 6deo_console(u8 *dev, u8 port) {
7 txt_printf("I: %lu\n", instr); 7 switch(port) {
8 txt_printf("E: %lu\n", err); 8 case 0x8:
9 txt_printf("A: %lu\n", addr); 9 txt_putc(dev[port]);
10 while (true); 10 return;
11 case 0x9:
12 txt_printf("ERROR: %c");
13 txt_putc(dev[port]);
14 return;
15 }
11} 16}
12 17
13IWRAM_CODE 18u16
14u8 19dei_screen(u8 *dev, u8 port) {
15screen_dei(u8 *d, u8 port) { 20 switch(port) {
16 // switch(port) { 21 case 0x0:
17 // case 0x2: return (SCREEN_WIDTH >> 8); 22 case 0x8:
18 // case 0x3: return (SCREEN_WIDTH); 23 case 0xa:
19 // case 0x4: return (SCREEN_HEIGHT >> 8); 24 case 0xc: return PEEK2(dev + port);
20 // case 0x5: return (SCREEN_HEIGHT); 25 case 0x2: return SCREEN_WIDTH;
21 // default: return d[port]; 26 case 0x4: return SCREEN_HEIGHT;
22 // } 27 default: return dev[port];
28 }
23} 29}
24 30
25IWRAM_CODE 31u16
26void 32dei_mouse(u8 *dev, u8 port) {
27screen_deo(u8 *ram, u8 *d, u8 port) { 33 switch(port) {
28 // switch(port) { 34 case 0x0:
29 // case 0xe: { 35 case 0x2:
30 // u8 ctrl = d[0xe]; 36 case 0x4:
31 // u8 color = ctrl & 0x3; 37 case 0xa:
32 // u16 x0 = PEEK2(d + 0x8); 38 case 0xc: return PEEK2(dev + port);
33 // u16 y0 = PEEK2(d + 0xa); 39 default: return dev[port];
34 // u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK; 40 }
35 // if(ctrl & 0x80) {
36 // u16 x1 = SCREEN_WIDTH - 1;
37 // u16 y1 = SCREEN_HEIGHT - 1;
38 // if(ctrl & 0x10) x1 = x0, x0 = 0;
39 // if(ctrl & 0x20) y1 = y0, y0 = 0;
40 // PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
41 // } else {
42 // PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
43 // if(d[0x6] & 0x1) POKE2(d + 0x8, x0 + 1); /* auto x+1 */
44 // if(d[0x6] & 0x2) POKE2(d + 0xa, y0 + 1); /* auto y+1 */
45 // }
46 // break;
47 // }
48 // case 0xf: {
49 // u16 x, y, dx, dy, addr;
50 // u8 n, twobpp = !!(d[0xf] & 0x80);
51 // x = PEEK2(d + 0x8);
52 // y = PEEK2(d + 0xa);
53 // addr = PEEK2(d + 0xc);
54 // n = d[0x6] >> 4;
55 // dx = (d[0x6] & 0x01) << 3;
56 // dy = (d[0x6] & 0x02) << 2;
57 // if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
58 // return;
59 // }
60 // u8 *layer = (d[0xf] & 0x40) ? FG_BACK : BG_BACK;
61 // u8 color = d[0xf] & 0xf;
62 // u8 flipx = d[0xf] & 0x10;
63 // u8 flipy = d[0xf] & 0x20;
64 // for(size_t i = 0; i <= n; i++) {
65 // u8 *sprite = &ram[addr];
66 // if (twobpp) {
67 // PROF(ppu_2bpp(layer,
68 // x + dy * i,
69 // y + dx * i,
70 // sprite,
71 // color,
72 // flipx, flipy), ppu_chr_cycles);
73 // } else {
74 // PROF(ppu_1bpp(layer,
75 // x + dy * i,
76 // y + dx * i,
77 // sprite,
78 // color,
79 // flipx, flipy), ppu_icn_cycles);
80 // }
81 // addr += (d[0x6] & 0x04) << (1 + twobpp);
82 // }
83 // POKE2(d + 0xc, addr); /* auto addr+length */
84 // POKE2(d + 0x8, x + dx); /* auto x+8 */
85 // POKE2(d + 0xa, y + dy); /* auto y+8 */
86 // break;
87 // }
88 // }
89} 41}
90 42
91u8 43void
92audio_dei(int instance, u8 *d, u8 port) { 44deo_screen(u8 *dev, u8 port) {
93 // AudioChannel *c = &channels[instance]; 45 switch(port) {
94 // switch(port) { 46 case 0xe: {
95 // // case 0x4: return apu_get_vu(instance); 47 u8 ctrl = dev[0xe];
96 // case 0x2: { 48 u8 color = ctrl & 0x3;
97 // POKE2(d + 0x2, c->pos); 49 u16 x0 = PEEK2(dev + 0x8);
98 // c->pos <<= 12; // fixed point. 50 u16 y0 = PEEK2(dev + 0xa);
99 // break; 51 u8 *layer = (ctrl & 0x40) ? FG_BACK : BG_BACK;
100 // } 52 if(ctrl & 0x80) {
101 // } 53 u16 x1 = SCREEN_WIDTH - 1;
102 return d[port]; 54 u16 y1 = SCREEN_HEIGHT - 1;
55 if(ctrl & 0x10) x1 = x0, x0 = 0;
56 if(ctrl & 0x20) y1 = y0, y0 = 0;
57 PROF(screen_fill(layer, x0, y0, x1, y1, color), ppu_fill_cycles);
58 } else {
59 PROF(ppu_pixel(layer, x0, y0, color), ppu_pixel_cycles);
60 if(dev[0x6] & 0x1) POKE2(dev + 0x8, x0 + 1); /* auto x+1 */
61 if(dev[0x6] & 0x2) POKE2(dev + 0xa, y0 + 1); /* auto y+1 */
62 }
63 break;
64 }
65 case 0xf: {
66 u16 x, y, dx, dy, addr;
67 u8 n, twobpp = !!(dev[0xf] & 0x80);
68 x = PEEK2(dev + 0x8);
69 y = PEEK2(dev + 0xa);
70 addr = PEEK2(dev + 0xc);
71 n = dev[0x6] >> 4;
72 dx = (dev[0x6] & 0x01) << 3;
73 dy = (dev[0x6] & 0x02) << 2;
74 if(addr > 0x10000 - ((n + 1) << (3 + twobpp))) {
75 return;
76 }
77 u8 *layer = (dev[0xf] & 0x40) ? FG_BACK : BG_BACK;
78 u8 color = dev[0xf] & 0xf;
79 u8 flipx = dev[0xf] & 0x10;
80 u8 flipy = dev[0xf] & 0x20;
81 for(size_t i = 0; i <= n; i++) {
82 u8 *sprite = &uxn_ram[addr];
83 if (twobpp) {
84 PROF(ppu_2bpp(layer,
85 x + dy * i,
86 y + dx * i,
87 sprite,
88 color,
89 flipx, flipy), ppu_chr_cycles);
90 } else {
91 PROF(ppu_1bpp(layer,
92 x + dy * i,
93 y + dx * i,
94 sprite,
95 color,
96 flipx, flipy), ppu_icn_cycles);
97 }
98 addr += (dev[0x6] & 0x04) << (1 + twobpp);
99 }
100 POKE2(dev + 0xc, addr); /* auto addr+length */
101 POKE2(dev + 0x8, x + dx); /* auto x+8 */
102 POKE2(dev + 0xa, y + dy); /* auto y+8 */
103 break;
104 }
105 }
103} 106}
104 107
105void 108void
106audio_deo(int instance, u8 *d, u8 port, Uxn *u) { 109deo_system(u8 *dev, u8 port) {
107 // AudioChannel *c = &channels[instance]; 110 switch(port) {
108 // if (port == 0xf) { 111 case 0x3: {
109 // u16 length = 0; 112 // TODO: Rom bank switching (Needs testing).
110 // u16 adsr = 0; 113 u16 addr = PEEK2(dev + 0x2);
111 // u16 addr = 0; 114 if(uxn_ram[addr] == 0x01) {
112 // u8 pitch = d[0xf] & 0x7f; 115 u16 i, length = PEEK2(uxn_ram + addr + 1);
113 // adsr = PEEK2(d + 0x8); 116 u16 a_page = PEEK2(uxn_ram + addr + 1 + 2);
114 // length = PEEK2(d + 0xa); 117 u16 a_addr = PEEK2(uxn_ram + addr + 1 + 4);
115 // addr = PEEK2(d + 0xc); 118 u16 b_addr = PEEK2(uxn_ram + addr + 1 + 8);
116 // u8 *data = &u->ram[addr]; 119 u8 *rom = uxn_rom + (a_page % RAM_PAGES) * 0x10000;
117 // u32 vol = MAX(d[0xe] >> 4, d[0xe] & 0xf) * 4 / 3; 120 for(i = 0; i < length; i++) {
118 // bool loop = !(d[0xf] & 0x80); 121 uxn_ram[(u16)(b_addr + i)] = rom[(u16)(a_addr + i)];
119 // update_channel(c, data, length, pitch, adsr, vol, loop); 122 }
120 // } 123 }
124 } break;
125 case 0x4: {
126 // TODO: Set wst_ptr, but is it the offset instead?
127 } break;
128 case 0x5: {
129 // TODO: Set rst_ptr, but is it the offset instead?
130 } break;
131 case 0x8:
132 case 0x9:
133 case 0xa:
134 case 0xb:
135 case 0xc:
136 case 0xd: {
137 // Setup RGB palette.
138 putcolors(&dev[0x8]);
139 } break;
140 case 0xe: {
141 // TODO: System inspect.
142 } break;
143 }
121} 144}
122 145
123u8 146u16
124datetime_dei(u8 *d, u8 port) { 147dei_system(u8 *dev, u8 port) {
148 switch (port) {
149 case 0x0:
150 case 0x2:
151 case 0x6:
152 case 0x8:
153 case 0xa:
154 case 0xc: return PEEK2(dev + port);
155 case 0x4: {
156 // TODO: Return wst_ptr, but is it the offset instead?
157 } break;
158 case 0x5: {
159 // TODO: Return rst_ptr, but is it the offset instead?
160 } break;
161 }
162 return dev[port];
163}
164
165u16
166dei_datetime(u8 *dev, u8 port) {
125 struct tm *t = gmtime(&seconds); 167 struct tm *t = gmtime(&seconds);
126 switch(port) { 168 switch(port) {
127 case 0x0: return (t->tm_year + 1900) >> 8; 169 case 0x0: return (t->tm_year + 1900);
128 case 0x1: return (t->tm_year + 1900); 170 case 0x1: return (t->tm_year + 1900) >> 8;
129 case 0x2: return t->tm_mon; 171 case 0x2: return t->tm_mon;
130 case 0x3: return t->tm_mday; 172 case 0x3: return t->tm_mday;
131 case 0x4: return t->tm_hour; 173 case 0x4: return t->tm_hour;
132 case 0x5: return t->tm_min; 174 case 0x5: return t->tm_min;
133 case 0x6: return t->tm_sec; 175 case 0x6: return t->tm_sec;
134 case 0x7: return t->tm_wday; 176 case 0x7: return t->tm_wday;
135 case 0x8: return t->tm_yday >> 8; 177 case 0x8: return t->tm_yday;
136 case 0x9: return t->tm_yday; 178 case 0x9: return t->tm_yday >> 8;
137 case 0xa: return t->tm_isdst; 179 case 0xa: return t->tm_isdst;
138 default: return d[port]; 180 default: return dev[port];
139 } 181 }
140} 182}
141 183
142u8 184u16
143file_dei(u8 id, u8 *d, u8 port) { 185dei_audio(u8 *dev, u8 port) {
144 // UxnFile *c = &uxn_file[id]; 186 size_t idx = (dev - (device_data + 0x30)) / 16;
145 // u16 res; 187 AudioChannel *c = &channels[idx];
146 // switch(port) { 188 switch(port) {
147 // case 0xc: 189 case 0x0:
148 // case 0xd: { 190 case 0x8:
149 // res = file_read(c, &d[port], 1); 191 case 0xa:
150 // POKE2(d + 0x2, res); 192 case 0x2: // TODO: return the position
151 // break; 193 case 0xc: return PEEK2(dev + port);
152 // } 194 // case 0x2: {
153 // } 195 // POKE2(d + 0x2, c->pos);
154 return d[port]; 196 // c->pos <<= 12; // fixed point.
155} 197 // break;
156 198 // }
157void 199 // case 0x4: return apu_get_vu(idx);
158file_deo(u8 id, u8 *ram, u8 *d, u8 port) { 200 // TODO: return the current envelope loudness (0x00-0xff).
159 // u16 a, b, res; 201 default: return dev[port];
160 // UxnFile *f = &uxn_file[id]; 202 }
161 // switch(port) { 203 return dev[port];
162 // case 0x5: {
163 // a = PEEK2(d + 0x4);
164 // b = PEEK2(d + 0xa);
165 // if(b > 0x10000 - a) {
166 // b = 0x10000 - a;
167 // }
168 // res = file_stat(f, &ram[a], b);
169 // POKE2(d + 0x2, res);
170 // } break;
171 // case 0x6: {
172 // // TODO: no file deletion for now
173 // // res = file_delete();
174 // // POKE2(d + 0x2, res);
175 // } break;
176 // case 0x9: {
177 // a = PEEK2(d + 0x8);
178 // res = file_init(f, &ram[a]);
179 // POKE2(d + 0x2, res);
180 // } break;
181 // case 0xd: {
182 // a = PEEK2(d + 0xc);
183 // b = PEEK2(d + 0xa);
184 // if(b > 0x10000 - a) {
185 // b = 0x10000 - a;
186 // }
187 // res = file_read(f, &ram[a], b);
188 // POKE2(d + 0x2, res);
189 // } break;
190 // case 0xf: {
191 // a = PEEK2(d + 0xe);
192 // b = PEEK2(d + 0xa);
193 // if(b > 0x10000 - a) {
194 // b = 0x10000 - a;
195 // }
196 // res = file_write(f, &ram[a], b, d[0x7]);
197 // POKE2(d + 0x2, res);
198 // } break;
199 // }
200} 204}
201 205
202void 206void
203console_deo(u8 *d, u8 port) { 207deo_audio(u8 *dev, u8 port) {
204 // switch(port) { 208 size_t idx = (dev - (device_data + 0x30)) / 16;
205 // case 0x8: 209 txt_printf("IDX: %d\n", idx);
206 // txt_putc(d[port]); 210 AudioChannel *c = &channels[idx];
207 // return; 211 if (port == 0xf) {
208 // case 0x9: 212 u16 length = 0;
209 // txt_printf("ERROR: %c"); 213 u16 adsr = 0;
210 // txt_putc(d[port]); 214 u16 addr = 0;
211 // return; 215 u8 pitch = dev[0xf] & 0x7f;
212 // } 216 adsr = PEEK2(dev + 0x8);
217 length = PEEK2(dev + 0xa);
218 addr = PEEK2(dev + 0xc);
219 u8 *data = &uxn_ram[addr];
220 u32 vol = MAX(dev[0xe] >> 4, dev[0xe] & 0xf) * 4 / 3;
221 bool loop = !(dev[0xf] & 0x80);
222 update_channel(c, data, length, pitch, adsr, vol, loop);
223 }
213} 224}
214 225
215#define RAM_PAGES 0x10 226u16
216 227dei_file(u8 *dev, u8 port) {
217static void 228 size_t idx = (dev - (device_data + 0xa0)) / 16;
218system_cmd(u8 *ram, u16 addr) { 229 UxnFile *c = &uxn_file[idx];
219 if(ram[addr] == 0x01) { 230 switch(port) {
220 // NOTE: Handle rom paging on a case by case basis if a rom has to be 231 case 0x0:
221 // split in multiple chunks. The GBA compiler doesn't like allocating 232 case 0x2:
222 // big arrays, but it's fine if we split it into chunks of 64KB, for 233 case 0x4:
223 // example. 234 case 0x8:
224 // 235 case 0xa:
225 // u16 i, length = PEEK2(ram + addr + 1); 236 case 0xe: return PEEK2(dev + port);
226 // u16 a_page = PEEK2(ram + addr + 1 + 2); 237 case 0xc:
227 // u16 a_addr = PEEK2(ram + addr + 1 + 4); 238 case 0xd: {
228 // u16 b_addr = PEEK2(ram + addr + 1 + 8); 239 u16 res = file_read(c, &dev[port], 1);
229 // u8 *rom = uxn_rom; 240 POKE2(dev + 0x2, res);
230 // for(i = 0; i < length; i++) { 241 return res;
231 // switch (a_page % RAM_PAGES) { 242 }
232 // case 0: { rom = uxn_rom; } break;
233 // case 1: { rom = uxn_rom_2; } break;
234 // case 2: { rom = uxn_rom_3; } break;
235 // case 3: { rom = uxn_rom_4; } break;
236 // case 4: { rom = uxn_rom_5; } break;
237 // case 5: { rom = uxn_rom_6; } break;
238 // case 6: { rom = uxn_rom_7; } break;
239 // }
240 // ram[(u16)(b_addr + i)] = rom[(u16)(a_addr + i)];
241 // }
242 } 243 }
244 return dev[port];
243} 245}
244 246
245void 247void
246system_deo(Uxn *u, u8 *d, u8 port) { 248deo_file(u8 *dev, u8 port) {
247 // switch(port) { 249 size_t idx = (dev - (device_data + 0xa0)) / 16;
248 // case 0x3: { 250 u16 a, b, res;
249 // system_cmd(u->ram, PEEK2(d + 2)); 251 UxnFile *f = &uxn_file[idx];
250 // } break; 252 switch(port) {
251 // } 253 case 0x5: {
252} 254 a = PEEK2(dev + 0x4);
253 255 b = PEEK2(dev + 0xa);
254u8 256 if(b > 0x10000 - a) {
255uxn_dei(Uxn *u, u8 addr) { 257 b = 0x10000 - a;
256 u8 p = addr & 0x0f, d = addr & 0xf0; 258 }
257 switch(d) { 259 res = file_stat(f, &uxn_ram[a], b);
258 case 0x20: return screen_dei(&u->dev[d], p); 260 POKE2(dev + 0x2, res);
259 case 0x30: return audio_dei(0, &u->dev[d], p); 261 } break;
260 case 0x40: return audio_dei(1, &u->dev[d], p); 262 case 0x6: {
261 case 0x50: return audio_dei(2, &u->dev[d], p); 263 // TODO: no file deletion for now
262 case 0x60: return audio_dei(3, &u->dev[d], p); 264 // res = file_delete();
263 case 0xa0: return file_dei(0, &u->dev[d], p); 265 // POKE2(dev + 0x2, res);
264 case 0xb0: return file_dei(1, &u->dev[d], p); 266 } break;
265 case 0xc0: return datetime_dei(&u->dev[d], p); 267 case 0x9: {
268 a = PEEK2(dev + 0x8);
269 res = file_init(f, &uxn_ram[a]);
270 POKE2(dev + 0x2, res);
271 } break;
272 case 0xd: {
273 a = PEEK2(dev + 0xc);
274 b = PEEK2(dev + 0xa);
275 if(b > 0x10000 - a) {
276 b = 0x10000 - a;
277 }
278 res = file_read(f, &uxn_ram[a], b);
279 POKE2(dev + 0x2, res);
280 } break;
281 case 0xf: {
282 a = PEEK2(dev + 0xe);
283 b = PEEK2(dev + 0xa);
284 if(b > 0x10000 - a) {
285 b = 0x10000 - a;
286 }
287 res = file_write(f, &uxn_ram[a], b, dev[0x7]);
288 POKE2(dev + 0x2, res);
289 } break;
266 } 290 }
267 return u->dev[addr];
268} 291}
269 292
270void 293void
271uxn_deo(Uxn *u, u8 addr) { 294deo_stub(u8 *dev, u8 port) {
272 u8 p = addr & 0x0f, d = addr & 0xf0; 295 (void)dev;
273 switch(d) { 296 (void)port;
274 case 0x00:
275 system_deo(u, &u->dev[d], p);
276 if(p > 0x7 && p < 0xe) {
277 putcolors(&u->dev[0x8]);
278 }
279 break;
280 case 0x10: console_deo(&u->dev[d], p); break;
281 case 0x20: screen_deo(u->ram, &u->dev[d], p); break;
282 case 0x30: audio_deo(0, &u->dev[d], p, u); break;
283 case 0x40: audio_deo(1, &u->dev[d], p, u); break;
284 case 0x50: audio_deo(2, &u->dev[d], p, u); break;
285 case 0x60: audio_deo(3, &u->dev[d], p, u); break;
286 case 0xa0: file_deo(0, u->ram, &u->dev[d], p); break;
287 case 0xb0: file_deo(1, u->ram, &u->dev[d], p); break;
288 }
289} 297}
290 298
299u16
300dei_stub(u8 *dev, u8 port) {
301 if (port == 0) {
302 return PEEK2(dev);
303 }
304 return dev[port];
305}