#include #include #include #include "devices/clock.h" #include "devices/math.h" #include "devices/screen.h" #include "bang.h" #include "core.h" #include "main_debug.h" Bedrock br[5] = {}; Bedrock *br_main; Bedrock *br_sub; bool main_on_bottom = TRUE; u8 main_program[] = { #include "../include/sysinfo.br.inc" }; u8 keyboard_program[] = { #include "../include/sysinfo.br.inc" }; // Change to the next screen layout. void change_layout(void) { lcdSwap(); main_on_bottom = !main_on_bottom; } // Scan for input and handle emulator-specific keys. void receive_input(void) { scanKeys(); if (keysDown() & KEY_SELECT) change_layout(); } void run_br(Bedrock *br) { if (br->awake) { switch (evaluate(br, 1000)) { case SIG_HALT: br->alive = FALSE; black_screen(br->scr.nds); br = NULL; return; case SIG_SLEEP: br->awake = FALSE; return; case SIG_DB1: debug_stacks(br); return; case SIG_DB4: debug_assert(br); return; default: return; } } } Screen scr_main = { .bgv = BG_TILE_RAM(BG_SLOT_VIS), .fgv = BG_TILE_RAM(FG_SLOT_VIS), .bg = BG_TILE_RAM(BG_SLOT), .fg = BG_TILE_RAM(FG_SLOT), .map = BG_MAP_RAM(MAP_SLOT), .pal = BG_PALETTE, }; Screen scr_sub = { .bgv = BG_TILE_RAM_SUB(BG_SLOT_VIS), .fgv = BG_TILE_RAM_SUB(FG_SLOT_VIS), .bg = BG_TILE_RAM_SUB(BG_SLOT), .fg = BG_TILE_RAM_SUB(FG_SLOT), .map = BG_MAP_RAM_SUB(MAP_SLOT), .pal = BG_PALETTE_SUB, }; int main(void) { #define ALIVE(br) (br && br->alive) #define AWAKE(br) (br && br->alive && br->awake) #define ASLEEP(br) (br && br->alive && !br->awake) init_screens(); init_clock(); lcdMainOnBottom(); // TODO: Remove // consoleDemoInit(); // Load program start_br(&br[0], main_program, sizeof(main_program)); start_br(&br[1], keyboard_program, sizeof(keyboard_program)); br_main = &br[0]; br_sub = &br[1]; br_main->scr.nds = &scr_main; br_sub->scr.nds = &scr_sub; while (1) { if (AWAKE(br_main)) run_br(br_main); if (AWAKE(br_sub)) run_br(br_sub); bool main_flip = ASLEEP(br_main) && br_main->scr.dirty; bool sub_flip = ASLEEP(br_sub) && br_sub->scr.dirty; if (main_flip || sub_flip) swiWaitForVBlank(); if (main_flip) { flip_buffer(br_main->scr.nds); br_main->scr.dirty = false; } if (sub_flip) { flip_buffer(br_sub->scr.nds); br_sub->scr.dirty = false; } rouse: receive_input(); if (ALIVE(br_main)) { inp_read_navigation(&br_main->inp); inp_read_gamepad(&br_main->inp); if (main_on_bottom) inp_read_touch(&br_main->inp); } if (ALIVE(br_sub)) { inp_read_navigation(&br_sub->inp); inp_read_gamepad(&br_sub->inp); if (!main_on_bottom) inp_read_touch(&br_sub->inp); } if (ASLEEP(br_main)) rouse_br(br_main); if (ASLEEP(br_sub)) rouse_br(br_sub); if (ASLEEP(br_main) && ASLEEP(br_sub)) { // Sleep until next keypad event or clock tick. swiIntrWait(1, IRQ_KEYS | IRQ_TIMER0); goto rouse; } if (!br_main && !br_sub) return 0; } }