... | ... |
@@ -21,7 +21,10 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
21 | 21 |
WITH REGARD TO THIS SOFTWARE. |
22 | 22 |
*/ |
23 | 23 |
|
24 |
+#define WIDTH 64 * 8 |
|
25 |
+#define HEIGHT 40 * 8 |
|
24 | 26 |
#define PAD 4 |
27 |
+ |
|
25 | 28 |
#define FIXED_SIZE 0 |
26 | 29 |
#define POLYPHONY 4 |
27 | 30 |
#define BENCH 0 |
... | ... |
@@ -36,11 +39,9 @@ static SDL_Rect gRect; |
36 | 39 |
static Ppu ppu; |
37 | 40 |
static Apu apu[POLYPHONY]; |
38 | 41 |
static Device *devsystem, *devscreen, *devmouse, *devctrl, *devaudio0, *devconsole; |
42 |
+static Uint8 zoom = 1, reqdraw = 0; |
|
39 | 43 |
static Uint32 *ppu_screen, stdin_event, audio0_event, palette[16]; |
40 | 44 |
|
41 |
-static Uint8 zoom = 1; |
|
42 |
-static unsigned int reqdraw = 0; |
|
43 |
- |
|
44 | 45 |
static Uint8 font[][8] = { |
45 | 46 |
{0x00, 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c}, |
46 | 47 |
{0x00, 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10}, |
... | ... |
@@ -72,6 +73,8 @@ error(char *msg, const char *err) |
72 | 73 |
return 0; |
73 | 74 |
} |
74 | 75 |
|
76 |
+#pragma mark - Generics |
|
77 |
+ |
|
75 | 78 |
static void |
76 | 79 |
audio_callback(void *u, Uint8 *stream, int len) |
77 | 80 |
{ |
... | ... |
@@ -85,6 +88,25 @@ audio_callback(void *u, Uint8 *stream, int len) |
85 | 88 |
(void)u; |
86 | 89 |
} |
87 | 90 |
|
91 |
+void |
|
92 |
+apu_finished_handler(Apu *c) |
|
93 |
+{ |
|
94 |
+ SDL_Event event; |
|
95 |
+ event.type = audio0_event + (c - apu); |
|
96 |
+ SDL_PushEvent(&event); |
|
97 |
+} |
|
98 |
+ |
|
99 |
+static int |
|
100 |
+stdin_handler(void *p) |
|
101 |
+{ |
|
102 |
+ SDL_Event event; |
|
103 |
+ event.type = stdin_event; |
|
104 |
+ while(read(0, &event.cbutton.button, 1) > 0) |
|
105 |
+ SDL_PushEvent(&event); |
|
106 |
+ return 0; |
|
107 |
+ (void)p; |
|
108 |
+} |
|
109 |
+ |
|
88 | 110 |
static void |
89 | 111 |
set_window_size(SDL_Window *window, int w, int h) |
90 | 112 |
{ |
... | ... |
@@ -168,9 +190,11 @@ toggle_debug(Uxn *u) |
168 | 190 |
} |
169 | 191 |
|
170 | 192 |
static void |
171 |
-toggle_zoom(Uxn *u) |
|
193 |
+set_zoom(Uxn *u, Uint8 scale) |
|
172 | 194 |
{ |
173 |
- zoom = zoom == 3 ? 1 : zoom + 1; |
|
195 |
+ if(scale == zoom) |
|
196 |
+ return; |
|
197 |
+ zoom = clamp(scale, 1, 3); |
|
174 | 198 |
set_window_size(gWindow, (ppu.width + PAD * 2) * zoom, (ppu.height + PAD * 2) * zoom); |
175 | 199 |
redraw(u); |
176 | 200 |
} |
... | ... |
@@ -192,19 +216,6 @@ capture_screen(void) |
192 | 216 |
fprintf(stderr, "Saved %s\n", fname); |
193 | 217 |
} |
194 | 218 |
|
195 |
-static void |
|
196 |
-quit(void) |
|
197 |
-{ |
|
198 |
- SDL_UnlockAudioDevice(audio_id); |
|
199 |
- SDL_DestroyTexture(gTexture); |
|
200 |
- gTexture = NULL; |
|
201 |
- SDL_DestroyRenderer(gRenderer); |
|
202 |
- gRenderer = NULL; |
|
203 |
- SDL_DestroyWindow(gWindow); |
|
204 |
- SDL_Quit(); |
|
205 |
- exit(0); |
|
206 |
-} |
|
207 |
- |
|
208 | 219 |
static int |
209 | 220 |
set_size(Uint16 width, Uint16 height, int is_resize) |
210 | 221 |
{ |
... | ... |
@@ -227,10 +238,23 @@ set_size(Uint16 width, Uint16 height, int is_resize) |
227 | 238 |
return 1; |
228 | 239 |
} |
229 | 240 |
|
241 |
+static void |
|
242 |
+quit(void) |
|
243 |
+{ |
|
244 |
+ SDL_UnlockAudioDevice(audio_id); |
|
245 |
+ SDL_DestroyTexture(gTexture); |
|
246 |
+ gTexture = NULL; |
|
247 |
+ SDL_DestroyRenderer(gRenderer); |
|
248 |
+ gRenderer = NULL; |
|
249 |
+ SDL_DestroyWindow(gWindow); |
|
250 |
+ SDL_Quit(); |
|
251 |
+ exit(0); |
|
252 |
+} |
|
253 |
+ |
|
230 | 254 |
static int |
231 |
-init(void) |
|
255 |
+init(Uxn *u) |
|
232 | 256 |
{ |
233 |
- const Uint16 width = 64 * 8, height = 40 * 8; |
|
257 |
+ SDL_DisplayMode DM; |
|
234 | 258 |
SDL_AudioSpec as; |
235 | 259 |
SDL_zero(as); |
236 | 260 |
as.freq = SAMPLE_FREQUENCY; |
... | ... |
@@ -248,16 +272,19 @@ init(void) |
248 | 272 |
if(!audio_id) |
249 | 273 |
error("sdl_audio", SDL_GetError()); |
250 | 274 |
} |
251 |
- gWindow = SDL_CreateWindow("Uxn", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, (width + PAD * 2) * zoom, (height + PAD * 2) * zoom, SDL_WINDOW_SHOWN); |
|
275 |
+ gWindow = SDL_CreateWindow("Uxn", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, (WIDTH + PAD * 2) * zoom, (HEIGHT + PAD * 2) * zoom, SDL_WINDOW_SHOWN); |
|
252 | 276 |
if(gWindow == NULL) |
253 | 277 |
return error("sdl_window", SDL_GetError()); |
254 | 278 |
gRenderer = SDL_CreateRenderer(gWindow, -1, 0); |
255 | 279 |
if(gRenderer == NULL) |
256 | 280 |
return error("sdl_renderer", SDL_GetError()); |
257 |
- if(!set_size(width, height, 0)) |
|
258 |
- return 0; |
|
281 |
+ stdin_event = SDL_RegisterEvents(1); |
|
282 |
+ audio0_event = SDL_RegisterEvents(POLYPHONY); |
|
283 |
+ SDL_CreateThread(stdin_handler, "stdin", NULL); |
|
259 | 284 |
SDL_StartTextInput(); |
260 | 285 |
SDL_ShowCursor(SDL_DISABLE); |
286 |
+ SDL_GetCurrentDisplayMode(0, &DM); |
|
287 |
+ set_zoom(u, DM.w / 1000); |
|
261 | 288 |
return 1; |
262 | 289 |
} |
263 | 290 |
|
... | ... |
@@ -299,7 +326,7 @@ doctrl(Uxn *u, SDL_Event *event, int z) |
299 | 326 |
case SDLK_DOWN: flag = 0x20; break; |
300 | 327 |
case SDLK_LEFT: flag = 0x40; break; |
301 | 328 |
case SDLK_RIGHT: flag = 0x80; break; |
302 |
- case SDLK_F1: if(z) toggle_zoom(u); break; |
|
329 |
+ case SDLK_F1: if(z) set_zoom(u, zoom == 3 ? 1 : zoom + 1); break; |
|
303 | 330 |
case SDLK_F2: if(z) toggle_debug(u); break; |
304 | 331 |
case SDLK_F3: if(z) capture_screen(); break; |
305 | 332 |
} |
... | ... |
@@ -414,10 +441,8 @@ file_talk(Device *d, Uint8 b0, Uint8 w) |
414 | 441 |
Uint16 addr = peek16(d->dat, b0 - 1); |
415 | 442 |
FILE *f = fopen(name, read ? "rb" : (offset ? "ab" : "wb")); |
416 | 443 |
if(f) { |
417 |
- /* fprintf(stderr, "%s %s %s #%04x, ", read ? "Loading" : "Saving", name, read ? "to" : "from", addr); */ |
|
418 | 444 |
if(fseek(f, offset, SEEK_SET) != -1) |
419 | 445 |
result = read ? fread(&d->mem[addr], 1, length, f) : fwrite(&d->mem[addr], 1, length, f); |
420 |
- /* fprintf(stderr, "%04x bytes\n", result); */ |
|
421 | 446 |
fclose(f); |
422 | 447 |
} |
423 | 448 |
poke16(d->dat, 0x2, result); |
... | ... |
@@ -478,27 +503,6 @@ nil_talk(Device *d, Uint8 b0, Uint8 w) |
478 | 503 |
return 1; |
479 | 504 |
} |
480 | 505 |
|
481 |
-#pragma mark - Generics |
|
482 |
- |
|
483 |
-void |
|
484 |
-apu_finished_handler(Apu *c) |
|
485 |
-{ |
|
486 |
- SDL_Event event; |
|
487 |
- event.type = audio0_event + (c - apu); |
|
488 |
- SDL_PushEvent(&event); |
|
489 |
-} |
|
490 |
- |
|
491 |
-static int |
|
492 |
-stdin_handler(void *p) |
|
493 |
-{ |
|
494 |
- SDL_Event event; |
|
495 |
- event.type = stdin_event; |
|
496 |
- while(read(0, &event.cbutton.button, 1) > 0) |
|
497 |
- SDL_PushEvent(&event); |
|
498 |
- return 0; |
|
499 |
- (void)p; |
|
500 |
-} |
|
501 |
- |
|
502 | 506 |
static const char *errors[] = {"underflow", "overflow", "division by zero"}; |
503 | 507 |
|
504 | 508 |
int |
... | ... |
@@ -508,7 +512,7 @@ uxn_halt(Uxn *u, Uint8 error, char *name, int id) |
508 | 512 |
return 0; |
509 | 513 |
} |
510 | 514 |
|
511 |
-static void |
|
515 |
+static int |
|
512 | 516 |
run(Uxn *u) |
513 | 517 |
{ |
514 | 518 |
uxn_eval(u, PAGE_PROGRAM); |
... | ... |
@@ -521,7 +525,7 @@ run(Uxn *u) |
521 | 525 |
while(SDL_PollEvent(&event) != 0) { |
522 | 526 |
switch(event.type) { |
523 | 527 |
case SDL_QUIT: |
524 |
- return; |
|
528 |
+ return error("Run", "Quit."); |
|
525 | 529 |
case SDL_TEXTINPUT: |
526 | 530 |
devctrl->dat[3] = event.text.text[0]; /* fall-thru */ |
527 | 531 |
case SDL_KEYDOWN: |
... | ... |
@@ -561,6 +565,7 @@ run(Uxn *u) |
561 | 565 |
SDL_Delay(clamp(16.666f - elapsed, 0, 1000)); |
562 | 566 |
} |
563 | 567 |
} |
568 |
+ return error("Run", "Ended."); |
|
564 | 569 |
} |
565 | 570 |
|
566 | 571 |
static int |
... | ... |
@@ -581,25 +586,19 @@ main(int argc, char **argv) |
581 | 586 |
|
582 | 587 |
if(argc < 2) return error("usage", "uxnemu file.rom"); |
583 | 588 |
if(!uxn_boot(&u)) return error("Boot", "Failed to start uxn."); |
589 |
+ if(!load(&u, argv[argc - 1])) return error("Load", "Failed to open rom."); |
|
590 |
+ if(!init(&u)) return error("Init", "Failed to initialize emulator."); |
|
591 |
+ if(!set_size(WIDTH, HEIGHT, 0)) return error("Window", "Failed to set window size."); |
|
584 | 592 |
|
585 | 593 |
for(i = 1; i < argc - 1; i++) { |
586 | 594 |
if(strcmp(argv[i], "-s") == 0) { |
587 |
- if((i + 1) < argc - 1) { |
|
588 |
- zoom = atoi(argv[++i]); |
|
589 |
- if(zoom < 1 || zoom > 3) return error("Opt", "-s Scale must be between 1 and 3."); |
|
590 |
- } else { |
|
595 |
+ if((i + 1) < argc - 1) |
|
596 |
+ set_zoom(&u, atoi(argv[++i])); |
|
597 |
+ else |
|
591 | 598 |
return error("Opt", "-s No scale provided."); |
592 |
- } |
|
593 | 599 |
} |
594 | 600 |
} |
595 | 601 |
|
596 |
- if(!load(&u, argv[argc - 1])) return error("Load", "Failed to open rom."); |
|
597 |
- if(!init()) return error("Init", "Failed to initialize emulator."); |
|
598 |
- |
|
599 |
- stdin_event = SDL_RegisterEvents(1); |
|
600 |
- audio0_event = SDL_RegisterEvents(POLYPHONY); |
|
601 |
- SDL_CreateThread(stdin_handler, "stdin", NULL); |
|
602 |
- |
|
603 | 602 |
/* system */ devsystem = uxn_port(&u, 0x0, system_talk); |
604 | 603 |
/* console */ devconsole = uxn_port(&u, 0x1, console_talk); |
605 | 604 |
/* screen */ devscreen = uxn_port(&u, 0x2, screen_talk); |