diff options
author | Bad Diode <bd@badd10de.dev> | 2022-03-05 22:30:05 +0100 |
---|---|---|
committer | Bad Diode <bd@badd10de.dev> | 2022-03-05 22:30:05 +0100 |
commit | 4aa83a8de5e5b131ddcabc920536d9b807b608ca (patch) | |
tree | ec21c58f04d3bea23fd2859e6733075e7d7b1ccc | |
parent | c046d2a0a97c71035001a654b445de8c0f9dc933 (diff) | |
download | uxnfb-4aa83a8de5e5b131ddcabc920536d9b807b608ca.tar.gz uxnfb-4aa83a8de5e5b131ddcabc920536d9b807b608ca.zip |
[WIP] Update core to current uxn version
-rw-r--r-- | src/main.c | 544 |
1 files changed, 260 insertions, 284 deletions
@@ -10,7 +10,8 @@ | |||
10 | 10 | ||
11 | #include "shorthand.h" | 11 | #include "shorthand.h" |
12 | #include "ppu.c" | 12 | #include "ppu.c" |
13 | #include "uxn-fast.c" | 13 | #include "uxn/src/devices/system.c" |
14 | #include "uxn/src/uxn.c" | ||
14 | 15 | ||
15 | #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) | 16 | #define CLAMP(X, MIN, MAX) ((X) <= (MIN) ? (MIN) : (X) > (MAX) ? (MAX): (X)) |
16 | 17 | ||
@@ -18,7 +19,6 @@ static Uxn u; | |||
18 | static Device *devscreen; | 19 | static Device *devscreen; |
19 | static Device *devctrl; | 20 | static Device *devctrl; |
20 | static Device *devmouse; | 21 | static Device *devmouse; |
21 | static Device *devaudio; | ||
22 | 22 | ||
23 | typedef struct timespec Time; | 23 | typedef struct timespec Time; |
24 | 24 | ||
@@ -142,168 +142,168 @@ poll_input(void) { | |||
142 | 142 | ||
143 | void | 143 | void |
144 | handle_keyboard(void) { | 144 | handle_keyboard(void) { |
145 | // Find mod keys. | 145 | // // Find mod keys. |
146 | bool shift_mod = false; | 146 | // bool shift_mod = false; |
147 | // bool ctrl_mod = false; | 147 | // // bool ctrl_mod = false; |
148 | // bool alt_mod = false; | 148 | // // bool alt_mod = false; |
149 | // bool meta_mod = false; | 149 | // // bool meta_mod = false; |
150 | for (size_t i = 0; i < sizeof(in.map); i++) { | 150 | // for (size_t i = 0; i < sizeof(in.map); i++) { |
151 | for (size_t j = 0; j < 8; j++) { | 151 | // for (size_t j = 0; j < 8; j++) { |
152 | char key = in.map[i] & (1 << j); | 152 | // char key = in.map[i] & (1 << j); |
153 | if (key) { | 153 | // if (key) { |
154 | char key_code = i * 8 + j; | 154 | // char key_code = i * 8 + j; |
155 | switch (key_code) { | 155 | // switch (key_code) { |
156 | case KEY_LEFTSHIFT: | 156 | // case KEY_LEFTSHIFT: |
157 | case KEY_RIGHTSHIFT: { shift_mod = true; } break; | 157 | // case KEY_RIGHTSHIFT: { shift_mod = true; } break; |
158 | // case KEY_LEFTCTRL: | 158 | // // case KEY_LEFTCTRL: |
159 | // case KEY_RIGHTCTRL: { ctrl_mod = true; } break; | 159 | // // case KEY_RIGHTCTRL: { ctrl_mod = true; } break; |
160 | // case KEY_LEFTALT: | 160 | // // case KEY_LEFTALT: |
161 | // case KEY_RIGHTALT: { alt_mod = true; } break; | 161 | // // case KEY_RIGHTALT: { alt_mod = true; } break; |
162 | // case KEY_LEFTMETA: | 162 | // // case KEY_LEFTMETA: |
163 | // case KEY_RIGHTMETA: { meta_mod = true; } break; | 163 | // // case KEY_RIGHTMETA: { meta_mod = true; } break; |
164 | default: break; | 164 | // default: break; |
165 | } | 165 | // } |
166 | } | 166 | // } |
167 | } | 167 | // } |
168 | } | 168 | // } |
169 | 169 | ||
170 | // Handle normal keys. | 170 | // // Handle normal keys. |
171 | u8 controller_now = 0; | 171 | // u8 controller_now = 0; |
172 | for (size_t i = 0; i < sizeof(in.map); i++) { | 172 | // for (size_t i = 0; i < sizeof(in.map); i++) { |
173 | for (size_t j = 0; j < 8; j++) { | 173 | // for (size_t j = 0; j < 8; j++) { |
174 | char key = in.map[i] & (1 << j); | 174 | // char key = in.map[i] & (1 << j); |
175 | if (key) { | 175 | // if (key) { |
176 | char key_code = i * 8 + j; | 176 | // char key_code = i * 8 + j; |
177 | // Normal keys. | 177 | // // Normal keys. |
178 | u8 rune = '\0'; | 178 | // u8 rune = '\0'; |
179 | switch (key_code) { | 179 | // switch (key_code) { |
180 | case KEY_KP1: | 180 | // case KEY_KP1: |
181 | case KEY_1: { rune = shift_mod ? '!' : '1'; } break; | 181 | // case KEY_1: { rune = shift_mod ? '!' : '1'; } break; |
182 | case KEY_KP2: | 182 | // case KEY_KP2: |
183 | case KEY_2: { rune = shift_mod ? '@' : '2'; } break; | 183 | // case KEY_2: { rune = shift_mod ? '@' : '2'; } break; |
184 | case KEY_KP3: | 184 | // case KEY_KP3: |
185 | case KEY_3: { rune = shift_mod ? '#' : '3'; } break; | 185 | // case KEY_3: { rune = shift_mod ? '#' : '3'; } break; |
186 | case KEY_KP4: | 186 | // case KEY_KP4: |
187 | case KEY_4: { rune = shift_mod ? '$' : '4'; } break; | 187 | // case KEY_4: { rune = shift_mod ? '$' : '4'; } break; |
188 | case KEY_KP5: | 188 | // case KEY_KP5: |
189 | case KEY_5: { rune = shift_mod ? '%' : '5'; } break; | 189 | // case KEY_5: { rune = shift_mod ? '%' : '5'; } break; |
190 | case KEY_KP6: | 190 | // case KEY_KP6: |
191 | case KEY_6: { rune = shift_mod ? '^' : '6'; } break; | 191 | // case KEY_6: { rune = shift_mod ? '^' : '6'; } break; |
192 | case KEY_KP7: | 192 | // case KEY_KP7: |
193 | case KEY_7: { rune = shift_mod ? '&' : '7'; } break; | 193 | // case KEY_7: { rune = shift_mod ? '&' : '7'; } break; |
194 | case KEY_KP8: | 194 | // case KEY_KP8: |
195 | case KEY_8: { rune = shift_mod ? '*' : '8'; } break; | 195 | // case KEY_8: { rune = shift_mod ? '*' : '8'; } break; |
196 | case KEY_KP9: | 196 | // case KEY_KP9: |
197 | case KEY_9: { rune = shift_mod ? '(' : '9'; } break; | 197 | // case KEY_9: { rune = shift_mod ? '(' : '9'; } break; |
198 | case KEY_KP0: | 198 | // case KEY_KP0: |
199 | case KEY_0: { rune = shift_mod ? ')' : '0'; } break; | 199 | // case KEY_0: { rune = shift_mod ? ')' : '0'; } break; |
200 | case KEY_KPMINUS: | 200 | // case KEY_KPMINUS: |
201 | case KEY_MINUS: { rune = shift_mod ? '_' : '-'; } break; | 201 | // case KEY_MINUS: { rune = shift_mod ? '_' : '-'; } break; |
202 | case KEY_KPEQUAL: | 202 | // case KEY_KPEQUAL: |
203 | case KEY_EQUAL: { rune = shift_mod ? '+' : '+'; } break; | 203 | // case KEY_EQUAL: { rune = shift_mod ? '+' : '+'; } break; |
204 | case KEY_Q: { rune = shift_mod ? 'Q' : 'q'; } break; | 204 | // case KEY_Q: { rune = shift_mod ? 'Q' : 'q'; } break; |
205 | case KEY_W: { rune = shift_mod ? 'W' : 'w'; } break; | 205 | // case KEY_W: { rune = shift_mod ? 'W' : 'w'; } break; |
206 | case KEY_E: { rune = shift_mod ? 'E' : 'e'; } break; | 206 | // case KEY_E: { rune = shift_mod ? 'E' : 'e'; } break; |
207 | case KEY_R: { rune = shift_mod ? 'T' : 't'; } break; | 207 | // case KEY_R: { rune = shift_mod ? 'T' : 't'; } break; |
208 | case KEY_T: { rune = shift_mod ? 'T' : 't'; } break; | 208 | // case KEY_T: { rune = shift_mod ? 'T' : 't'; } break; |
209 | case KEY_Y: { rune = shift_mod ? 'Y' : 'y'; } break; | 209 | // case KEY_Y: { rune = shift_mod ? 'Y' : 'y'; } break; |
210 | case KEY_U: { rune = shift_mod ? 'U' : 'u'; } break; | 210 | // case KEY_U: { rune = shift_mod ? 'U' : 'u'; } break; |
211 | case KEY_I: { rune = shift_mod ? 'I' : 'i'; } break; | 211 | // case KEY_I: { rune = shift_mod ? 'I' : 'i'; } break; |
212 | case KEY_O: { rune = shift_mod ? 'O' : 'o'; } break; | 212 | // case KEY_O: { rune = shift_mod ? 'O' : 'o'; } break; |
213 | case KEY_P: { rune = shift_mod ? 'P' : 'p'; } break; | 213 | // case KEY_P: { rune = shift_mod ? 'P' : 'p'; } break; |
214 | case KEY_LEFTBRACE: { rune = shift_mod ? '{' : '['; } break; | 214 | // case KEY_LEFTBRACE: { rune = shift_mod ? '{' : '['; } break; |
215 | case KEY_RIGHTBRACE: { rune = shift_mod ? '}' : ']'; } break; | 215 | // case KEY_RIGHTBRACE: { rune = shift_mod ? '}' : ']'; } break; |
216 | case KEY_A: { rune = shift_mod ? 'A' : 'a'; } break; | 216 | // case KEY_A: { rune = shift_mod ? 'A' : 'a'; } break; |
217 | case KEY_S: { rune = shift_mod ? 'S' : 's'; } break; | 217 | // case KEY_S: { rune = shift_mod ? 'S' : 's'; } break; |
218 | case KEY_D: { rune = shift_mod ? 'D' : 'd'; } break; | 218 | // case KEY_D: { rune = shift_mod ? 'D' : 'd'; } break; |
219 | case KEY_F: { rune = shift_mod ? 'F' : 'f'; } break; | 219 | // case KEY_F: { rune = shift_mod ? 'F' : 'f'; } break; |
220 | case KEY_G: { rune = shift_mod ? 'G' : 'g'; } break; | 220 | // case KEY_G: { rune = shift_mod ? 'G' : 'g'; } break; |
221 | case KEY_H: { rune = shift_mod ? 'H' : 'h'; } break; | 221 | // case KEY_H: { rune = shift_mod ? 'H' : 'h'; } break; |
222 | case KEY_J: { rune = shift_mod ? 'J' : 'j'; } break; | 222 | // case KEY_J: { rune = shift_mod ? 'J' : 'j'; } break; |
223 | case KEY_K: { rune = shift_mod ? 'K' : 'k'; } break; | 223 | // case KEY_K: { rune = shift_mod ? 'K' : 'k'; } break; |
224 | case KEY_L: { rune = shift_mod ? 'L' : 'l'; } break; | 224 | // case KEY_L: { rune = shift_mod ? 'L' : 'l'; } break; |
225 | case KEY_SEMICOLON: { rune = shift_mod ? ':' : ';'; } break; | 225 | // case KEY_SEMICOLON: { rune = shift_mod ? ':' : ';'; } break; |
226 | case KEY_APOSTROPHE: { rune = shift_mod ? '"' : '\''; } break; | 226 | // case KEY_APOSTROPHE: { rune = shift_mod ? '"' : '\''; } break; |
227 | case KEY_GRAVE: { rune = shift_mod ? '~' : '`'; } break; | 227 | // case KEY_GRAVE: { rune = shift_mod ? '~' : '`'; } break; |
228 | case KEY_BACKSLASH: { rune = shift_mod ? '|' : '\\'; } break; | 228 | // case KEY_BACKSLASH: { rune = shift_mod ? '|' : '\\'; } break; |
229 | case KEY_Z: { rune = shift_mod ? 'Z' : 'z'; } break; | 229 | // case KEY_Z: { rune = shift_mod ? 'Z' : 'z'; } break; |
230 | case KEY_X: { rune = shift_mod ? 'X' : 'x'; } break; | 230 | // case KEY_X: { rune = shift_mod ? 'X' : 'x'; } break; |
231 | case KEY_C: { rune = shift_mod ? 'C' : 'c'; } break; | 231 | // case KEY_C: { rune = shift_mod ? 'C' : 'c'; } break; |
232 | case KEY_V: { rune = shift_mod ? 'V' : 'v'; } break; | 232 | // case KEY_V: { rune = shift_mod ? 'V' : 'v'; } break; |
233 | case KEY_B: { rune = shift_mod ? 'B' : 'b'; } break; | 233 | // case KEY_B: { rune = shift_mod ? 'B' : 'b'; } break; |
234 | case KEY_N: { rune = shift_mod ? 'N' : 'n'; } break; | 234 | // case KEY_N: { rune = shift_mod ? 'N' : 'n'; } break; |
235 | case KEY_M: { rune = shift_mod ? 'M' : 'm'; } break; | 235 | // case KEY_M: { rune = shift_mod ? 'M' : 'm'; } break; |
236 | case KEY_COMMA: { rune = shift_mod ? '<' : ','; } break; | 236 | // case KEY_COMMA: { rune = shift_mod ? '<' : ','; } break; |
237 | case KEY_DOT: { rune = shift_mod ? '>' : '.'; } break; | 237 | // case KEY_DOT: { rune = shift_mod ? '>' : '.'; } break; |
238 | case KEY_KPSLASH: | 238 | // case KEY_KPSLASH: |
239 | case KEY_SLASH: { rune = shift_mod ? '?' : '/'; } break; | 239 | // case KEY_SLASH: { rune = shift_mod ? '?' : '/'; } break; |
240 | case KEY_KPASTERISK: { rune = '*'; } break; | 240 | // case KEY_KPASTERISK: { rune = '*'; } break; |
241 | case KEY_KPPLUS: { rune = '+'; } break; | 241 | // case KEY_KPPLUS: { rune = '+'; } break; |
242 | case KEY_KPCOMMA: { rune = '.'; } break; | 242 | // case KEY_KPCOMMA: { rune = '.'; } break; |
243 | case KEY_SPACE: { rune = ' '; } break; | 243 | // case KEY_SPACE: { rune = ' '; } break; |
244 | case KEY_TAB: { rune = '\t'; } break; | 244 | // case KEY_TAB: { rune = '\t'; } break; |
245 | case KEY_ESC: { rune = 0x1b; } break; | 245 | // case KEY_ESC: { rune = 0x1b; } break; |
246 | case KEY_BACKSPACE: { rune = 0x08; } break; | 246 | // case KEY_BACKSPACE: { rune = 0x08; } break; |
247 | case KEY_ENTER: | 247 | // case KEY_ENTER: |
248 | case KEY_KPENTER: { rune = 0x0d; } break; | 248 | // case KEY_KPENTER: { rune = 0x0d; } break; |
249 | default: break; | 249 | // default: break; |
250 | } | 250 | // } |
251 | if (rune) { | 251 | // if (rune) { |
252 | devctrl->dat[3] = rune; | 252 | // devctrl->dat[3] = rune; |
253 | uxn_eval(&u, mempeek16(devctrl->dat, 0)); | 253 | // uxn_eval(&u, mempeek16(devctrl->dat, 0)); |
254 | devctrl->dat[3] = 0; | 254 | // devctrl->dat[3] = 0; |
255 | continue; | 255 | // continue; |
256 | } | 256 | // } |
257 | 257 | ||
258 | // Special keys. | 258 | // // Special keys. |
259 | switch (key_code) { | 259 | // switch (key_code) { |
260 | case KEY_LEFTCTRL: { rune = 0x01; } break; | 260 | // case KEY_LEFTCTRL: { rune = 0x01; } break; |
261 | case KEY_LEFTALT: { rune = 0x02; } break; | 261 | // case KEY_LEFTALT: { rune = 0x02; } break; |
262 | case KEY_LEFTSHIFT: { rune = 0x04; } break; | 262 | // case KEY_LEFTSHIFT: { rune = 0x04; } break; |
263 | case KEY_HOME: { rune = 0x08; } break; | 263 | // case KEY_HOME: { rune = 0x08; } break; |
264 | case KEY_UP: { rune = 0x10; } break; | 264 | // case KEY_UP: { rune = 0x10; } break; |
265 | case KEY_DOWN: { rune = 0x20; } break; | 265 | // case KEY_DOWN: { rune = 0x20; } break; |
266 | case KEY_LEFT: { rune = 0x40; } break; | 266 | // case KEY_LEFT: { rune = 0x40; } break; |
267 | case KEY_RIGHT: { rune = 0x80; } break; | 267 | // case KEY_RIGHT: { rune = 0x80; } break; |
268 | default: break; | 268 | // default: break; |
269 | } | 269 | // } |
270 | if (rune) { | 270 | // if (rune) { |
271 | controller_now |= rune; | 271 | // controller_now |= rune; |
272 | continue; | 272 | // continue; |
273 | } | 273 | // } |
274 | } | 274 | // } |
275 | } | 275 | // } |
276 | } | 276 | // } |
277 | 277 | ||
278 | if (controller_now != in.controller) { | 278 | // if (controller_now != in.controller) { |
279 | devctrl->dat[2] = controller_now; | 279 | // devctrl->dat[2] = controller_now; |
280 | uxn_eval(&u, mempeek16(devctrl->dat, 0)); | 280 | // uxn_eval(&u, mempeek16(devctrl->dat, 0)); |
281 | in.controller = controller_now; | 281 | // in.controller = controller_now; |
282 | } | 282 | // } |
283 | 283 | ||
284 | // Reset input state. | 284 | // // Reset input state. |
285 | devctrl->dat[3] = 0; | 285 | // devctrl->dat[3] = 0; |
286 | memset(in.map, 0, sizeof(in.map)); | 286 | // memset(in.map, 0, sizeof(in.map)); |
287 | } | 287 | } |
288 | 288 | ||
289 | void | 289 | void |
290 | handle_mouse(void) { | 290 | handle_mouse(void) { |
291 | if (in.mouse.update) { | 291 | // if (in.mouse.update) { |
292 | // Handle mouse keys. | 292 | // // Handle mouse keys. |
293 | devmouse->dat[6] = in.mouse.buttons; | 293 | // devmouse->dat[6] = in.mouse.buttons; |
294 | if(in.mouse.buttons == 0x10 && (devmouse->dat[6] & 0x01)) { | 294 | // if(in.mouse.buttons == 0x10 && (devmouse->dat[6] & 0x01)) { |
295 | devmouse->dat[7] = 0x01; | 295 | // devmouse->dat[7] = 0x01; |
296 | } | 296 | // } |
297 | if(in.mouse.buttons == 0x01 && (devmouse->dat[6] & 0x10)) { | 297 | // if(in.mouse.buttons == 0x01 && (devmouse->dat[6] & 0x10)) { |
298 | devmouse->dat[7] = 0x10; | 298 | // devmouse->dat[7] = 0x10; |
299 | } | 299 | // } |
300 | 300 | ||
301 | // Handle mouse location. | 301 | // // Handle mouse location. |
302 | mempoke16(devmouse->dat, 0x2, in.mouse.x); | 302 | // mempoke16(devmouse->dat, 0x2, in.mouse.x); |
303 | mempoke16(devmouse->dat, 0x4, in.mouse.y); | 303 | // mempoke16(devmouse->dat, 0x4, in.mouse.y); |
304 | uxn_eval(&u, mempeek16(devmouse->dat, 0)); | 304 | // uxn_eval(&u, mempeek16(devmouse->dat, 0)); |
305 | in.mouse.update = false; | 305 | // in.mouse.update = false; |
306 | } | 306 | // } |
307 | } | 307 | } |
308 | 308 | ||
309 | void | 309 | void |
@@ -312,11 +312,24 @@ handle_input(void) { | |||
312 | handle_mouse(); | 312 | handle_mouse(); |
313 | } | 313 | } |
314 | 314 | ||
315 | void | 315 | static Uint8 |
316 | nil_talk(Device *d, u8 b0, u8 w) { | 316 | nil_dei(Device *d, Uint8 port) { |
317 | return d->dat[port]; | ||
318 | } | ||
319 | |||
320 | static void | ||
321 | nil_deo(Device *d, Uint8 port) { | ||
317 | (void)d; | 322 | (void)d; |
318 | (void)b0; | 323 | (void)port; |
319 | (void)w; | 324 | } |
325 | |||
326 | static void | ||
327 | console_deo(Device *d, Uint8 port) { | ||
328 | FILE *fd = port == 0x8 ? stdout : port == 0x9 ? stderr : 0; | ||
329 | if(fd) { | ||
330 | fputc(d->dat[port], fd); | ||
331 | fflush(fd); | ||
332 | } | ||
320 | } | 333 | } |
321 | 334 | ||
322 | void | 335 | void |
@@ -338,8 +351,58 @@ console_talk(Device *d, u8 b0, u8 w) { | |||
338 | // } | 351 | // } |
339 | } | 352 | } |
340 | 353 | ||
354 | Uint8 | ||
355 | screen_dei(Device *d, Uint8 port) { | ||
356 | switch(port) { | ||
357 | case 0x2: return screen_width >> 8; | ||
358 | case 0x3: return screen_width; | ||
359 | case 0x4: return screen_height >> 8; | ||
360 | case 0x5: return screen_height; | ||
361 | default: return d->dat[port]; | ||
362 | } | ||
363 | } | ||
364 | |||
365 | void | ||
366 | screen_deo(Device *d, Uint8 port) { | ||
367 | switch(port) { | ||
368 | case 0xe: { | ||
369 | Uint16 x, y; | ||
370 | Uint8 layer = d->dat[0xe] & 0x40; | ||
371 | DEVPEEK16(x, 0x8); | ||
372 | DEVPEEK16(y, 0xa); | ||
373 | ppu_pixel(layer ? pixels_fg : pixels_bg, x, y, d->dat[0xe] & 0x3); | ||
374 | if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 1); /* auto x+1 */ | ||
375 | if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 1); /* auto y+1 */ | ||
376 | } break; | ||
377 | case 0xf: { | ||
378 | Uint16 x, y, addr; | ||
379 | Uint8 twobpp = !!(d->dat[0xf] & 0x80); | ||
380 | DEVPEEK16(x, 0x8); | ||
381 | DEVPEEK16(y, 0xa); | ||
382 | DEVPEEK16(addr, 0xc); | ||
383 | if(addr > 0xfff8 - twobpp * 8) { | ||
384 | return; | ||
385 | } | ||
386 | u8 *layer = (d->dat[0xf] & 0x40) ? pixels_fg : pixels_bg; | ||
387 | u8 color = d->dat[0xf] & 0xf; | ||
388 | u8 flipx = d->dat[0xf] & 0x10; | ||
389 | u8 flipy = d->dat[0xf] & 0x20; | ||
390 | u8 *sprite = &d->u->ram[addr]; | ||
391 | if (twobpp) { | ||
392 | ppu_2bpp(layer, x, y, sprite, color, flipx, flipy); | ||
393 | } else { | ||
394 | ppu_1bpp(layer, x, y, sprite, color, flipx, flipy); | ||
395 | } | ||
396 | if(d->dat[0x6] & 0x04) DEVPOKE16(0xc, addr + 8 + twobpp * 8); /* auto addr+length */ | ||
397 | if(d->dat[0x6] & 0x01) DEVPOKE16(0x8, x + 8); /* auto x+8 */ | ||
398 | if(d->dat[0x6] & 0x02) DEVPOKE16(0xa, y + 8); /* auto y+8 */ | ||
399 | } break; | ||
400 | } | ||
401 | reqdraw = 1; | ||
402 | } | ||
403 | |||
341 | static void | 404 | static void |
342 | docolors(Device *d) { | 405 | screen_palette(Device *d) { |
343 | for(size_t i = 0; i < 4; ++i) { | 406 | for(size_t i = 0; i < 4; ++i) { |
344 | u8 r = ((d->dat[0x8 + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; | 407 | u8 r = ((d->dat[0x8 + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; |
345 | u8 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; | 408 | u8 g = ((d->dat[0xa + i / 2] >> (!(i % 2) << 2)) & 0x0f) * 0x11; |
@@ -361,107 +424,13 @@ docolors(Device *d) { | |||
361 | } | 424 | } |
362 | 425 | ||
363 | void | 426 | void |
364 | system_talk(Device *d, u8 b0, u8 w) { | 427 | system_deo_special(Device *d, Uint8 port) { |
365 | if(!w) { /* read */ | 428 | if(port > 0x7 && port < 0xe) { |
366 | switch(b0) { | 429 | screen_palette(d); |
367 | case 0x2: d->dat[0x2] = d->u->wst.ptr; break; | ||
368 | case 0x3: d->dat[0x3] = d->u->rst.ptr; break; | ||
369 | } | ||
370 | } else { /* write */ | ||
371 | switch(b0) { | ||
372 | case 0x2: d->u->wst.ptr = d->dat[0x2]; break; | ||
373 | case 0x3: d->u->rst.ptr = d->dat[0x3]; break; | ||
374 | case 0xf: d->u->ram.ptr = 0x0000; break; | ||
375 | } | ||
376 | if(b0 > 0x7 && b0 < 0xe) { | ||
377 | docolors(d); | ||
378 | } | ||
379 | } | 430 | } |
380 | (void)b0; | ||
381 | } | 431 | } |
382 | 432 | ||
383 | void | 433 | void |
384 | screen_talk(Device *d, u8 b0, u8 w) { | ||
385 | if (w) { | ||
386 | switch (b0) { | ||
387 | case 0x1: { | ||
388 | d->vector = mempeek16(d->dat, 0x0); | ||
389 | } break; | ||
390 | case 0xe: { | ||
391 | u16 x = mempeek16(d->dat, 0x8); | ||
392 | u16 y = mempeek16(d->dat, 0xa); | ||
393 | u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; | ||
394 | u8 *layer = d->dat[0xe] >> 4 & 0x1 ? pixels_fg : pixels_bg; | ||
395 | u8 mode = d->dat[0xe] >> 5; | ||
396 | u8 color = d->dat[0xf] & 0xf; | ||
397 | if(!mode) { | ||
398 | ppu_pixel(layer, x, y, d->dat[0xe] & 0x3); | ||
399 | } else if(mode-- & 0x1) { | ||
400 | u8 flipx = mode & 0x2; | ||
401 | u8 flipy = mode & 0x4; | ||
402 | ppu_1bpp(layer, x, y, addr, color, flipx, flipy); | ||
403 | } else { | ||
404 | u8 flipx = mode & 0x2; | ||
405 | u8 flipy = mode & 0x4; | ||
406 | ppu_2bpp(layer, x, y, addr, color, flipx, flipy); | ||
407 | } | ||
408 | if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 1); } | ||
409 | if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 1); } | ||
410 | } break; | ||
411 | case 0xf: { | ||
412 | u16 x = mempeek16(d->dat, 0x8); | ||
413 | u16 y = mempeek16(d->dat, 0xa); | ||
414 | u8 *addr = &d->mem[mempeek16(d->dat, 0xc)]; | ||
415 | u8 *layer = d->dat[0xf] >> 6 & 0x1 ? pixels_fg : pixels_bg; | ||
416 | u8 color = d->dat[0xf] & 0xf; | ||
417 | u8 flipx = (d->dat[0xf] >> 0x4) & 0x1; | ||
418 | u8 flipy = (d->dat[0xf] >> 0x5) & 0x1; | ||
419 | if(d->dat[0xf] >> 0x7 & 0x1) { | ||
420 | ppu_2bpp(layer, x, y, addr, color, flipx, flipy); | ||
421 | if(d->dat[0x6] & 0x04) { | ||
422 | mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 16); | ||
423 | } | ||
424 | } else { | ||
425 | ppu_1bpp(layer, x, y, addr, color, flipx, flipy); | ||
426 | if(d->dat[0x6] & 0x04) { | ||
427 | mempoke16(d->dat, 0xc, mempeek16(d->dat, 0xc) + 8); | ||
428 | } | ||
429 | } | ||
430 | if(d->dat[0x6] & 0x01) { mempoke16(d->dat, 0x8, x + 8); } | ||
431 | if(d->dat[0x6] & 0x02) { mempoke16(d->dat, 0xa, y + 8); } | ||
432 | } break; | ||
433 | default: break; | ||
434 | } | ||
435 | } | ||
436 | reqdraw = 1; | ||
437 | } | ||
438 | |||
439 | static void | ||
440 | audio_talk(Device *d, u8 b0, u8 w) { | ||
441 | // TODO: Implement... | ||
442 | (void)d; | ||
443 | (void)b0; | ||
444 | (void)w; | ||
445 | } | ||
446 | |||
447 | void | ||
448 | datetime_talk(Device *d, u8 b0, u8 w) { | ||
449 | // TODO: Implement... | ||
450 | (void)d; | ||
451 | (void)b0; | ||
452 | (void)w; | ||
453 | } | ||
454 | |||
455 | void | ||
456 | file_talk(Device *d, u8 b0, u8 w) { | ||
457 | // TODO: Implement... | ||
458 | (void)d; | ||
459 | (void)b0; | ||
460 | (void)w; | ||
461 | } | ||
462 | |||
463 | |||
464 | void | ||
465 | load_rom(char *file_name) { | 434 | load_rom(char *file_name) { |
466 | FILE *file = fopen(file_name, "r"); | 435 | FILE *file = fopen(file_name, "r"); |
467 | if (!file) { | 436 | if (!file) { |
@@ -474,15 +443,16 @@ load_rom(char *file_name) { | |||
474 | fseek(file, 0, SEEK_SET); | 443 | fseek(file, 0, SEEK_SET); |
475 | char *uxn_rom = malloc(rom_size); | 444 | char *uxn_rom = malloc(rom_size); |
476 | fread(uxn_rom, 1, rom_size, file); | 445 | fread(uxn_rom, 1, rom_size, file); |
477 | memcpy(u.ram.dat + PAGE_PROGRAM, uxn_rom, rom_size); | 446 | memcpy(u.ram + PAGE_PROGRAM, uxn_rom, rom_size); |
447 | |||
478 | fclose(file); | 448 | fclose(file); |
479 | free(uxn_rom); | 449 | free(uxn_rom); |
480 | } | 450 | } |
481 | 451 | ||
482 | void | 452 | void |
483 | init_uxn(char *file_name) { | 453 | init_uxn(Uxn *u, char *file_name) { |
484 | // Clear UXN memory. | 454 | // Setup UXN memory. |
485 | memset(&u, 0, sizeof(Uxn)); | 455 | uxn_boot(u, calloc(0x10000, sizeof(Uint8))); |
486 | 456 | ||
487 | // Copy rom to VM. | 457 | // Copy rom to VM. |
488 | load_rom(file_name); | 458 | load_rom(file_name); |
@@ -494,24 +464,30 @@ init_uxn(char *file_name) { | |||
494 | init_input(); | 464 | init_input(); |
495 | 465 | ||
496 | // Prepare devices. | 466 | // Prepare devices. |
497 | uxn_port(&u, 0x0, "system", system_talk); | 467 | /* system */ uxn_port(u, 0x0, system_dei, system_deo); |
498 | uxn_port(&u, 0x1, "console", console_talk); | 468 | /* console */ uxn_port(u, 0x1, nil_dei, console_deo); |
499 | devscreen = uxn_port(&u, 0x2, "screen", screen_talk); | 469 | /* screen */ devscreen = uxn_port(u, 0x2, screen_dei, screen_deo); |
500 | devaudio = uxn_port(&u, 0x3, "audio0", audio_talk); | 470 | // TODO: |
501 | uxn_port(&u, 0x4, "audio1", audio_talk); | 471 | // /* audio0 */ devaudio0 = uxn_port(u, 0x3, audio_dei, audio_deo); |
502 | uxn_port(&u, 0x5, "audio2", audio_talk); | 472 | // /* audio1 */ uxn_port(u, 0x4, audio_dei, audio_deo); |
503 | uxn_port(&u, 0x6, "audio3", audio_talk); | 473 | // /* audio2 */ uxn_port(u, 0x5, audio_dei, audio_deo); |
504 | uxn_port(&u, 0x7, "---", nil_talk); | 474 | // /* audio3 */ uxn_port(u, 0x6, audio_dei, audio_deo); |
505 | devctrl = uxn_port(&u, 0x8, "controller", nil_talk); | 475 | /* audio0 */ uxn_port(u, 0x3, nil_dei, nil_deo); |
506 | devmouse = uxn_port(&u, 0x9, "mouse", nil_talk); | 476 | /* audio1 */ uxn_port(u, 0x4, nil_dei, nil_deo); |
507 | uxn_port(&u, 0xa, "file", file_talk); | 477 | /* audio2 */ uxn_port(u, 0x5, nil_dei, nil_deo); |
508 | uxn_port(&u, 0xb, "datetime", datetime_talk); | 478 | /* audio3 */ uxn_port(u, 0x6, nil_dei, nil_deo); |
509 | uxn_port(&u, 0xc, "---", nil_talk); | 479 | /* unused */ uxn_port(u, 0x7, nil_dei, nil_deo); |
510 | uxn_port(&u, 0xd, "---", nil_talk); | 480 | /* control */ devctrl = uxn_port(u, 0x8, nil_dei, nil_deo); |
511 | uxn_port(&u, 0xe, "---", nil_talk); | 481 | /* mouse */ devmouse = uxn_port(u, 0x9, nil_dei, nil_deo); |
512 | uxn_port(&u, 0xf, "---", nil_talk); | 482 | // TODO: |
513 | mempoke16(devscreen->dat, 2, screen_width); | 483 | // /* file */ uxn_port(u, 0xa, nil_dei, file_deo); |
514 | mempoke16(devscreen->dat, 4, screen_height); | 484 | // /* datetime */ uxn_port(u, 0xb, datetime_dei, nil_deo); |
485 | /* file */ uxn_port(u, 0xa, nil_dei, nil_deo); | ||
486 | /* datetime */ uxn_port(u, 0xb, nil_dei, nil_deo); | ||
487 | /* unused */ uxn_port(u, 0xc, nil_dei, nil_deo); | ||
488 | /* unused */ uxn_port(u, 0xd, nil_dei, nil_deo); | ||
489 | /* unused */ uxn_port(u, 0xe, nil_dei, nil_deo); | ||
490 | /* unused */ uxn_port(u, 0xf, nil_dei, nil_deo); | ||
515 | } | 491 | } |
516 | 492 | ||
517 | int | 493 | int |
@@ -521,10 +497,10 @@ main(int argc, char *argv[]) { | |||
521 | fprintf(stderr, "error: no rom selected\n"); | 497 | fprintf(stderr, "error: no rom selected\n"); |
522 | exit(EXIT_FAILURE); | 498 | exit(EXIT_FAILURE); |
523 | } | 499 | } |
524 | init_uxn(argv[1]); | 500 | init_uxn(&u, argv[1]); |
525 | 501 | ||
526 | // Main loop. | 502 | // Main loop. |
527 | uxn_eval(&u, 0x0100); | 503 | uxn_eval(&u, PAGE_PROGRAM); |
528 | Time frame_time = time_now(); | 504 | Time frame_time = time_now(); |
529 | while (true) { | 505 | while (true) { |
530 | poll_input(); | 506 | poll_input(); |
@@ -533,7 +509,7 @@ main(int argc, char *argv[]) { | |||
533 | handle_input(); | 509 | handle_input(); |
534 | 510 | ||
535 | // Echo input to standard output. | 511 | // Echo input to standard output. |
536 | uxn_eval(&u, mempeek16(devscreen->dat, 0)); | 512 | uxn_eval(&u, GETVECTOR(devscreen)); |
537 | 513 | ||
538 | // Blit ppu.pixels to the framebuffer. | 514 | // Blit ppu.pixels to the framebuffer. |
539 | blit_framebuffer(); | 515 | blit_framebuffer(); |