| ... | ... |
@@ -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); |