summaryrefslogtreecommitdiff
path: root/arm9/source/main.c
blob: 8bb78d81aa6c6eb7b638b35cb77f322971d369d3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#include <stdio.h>
#include <time.h>
#include <nds.h>
#include "devices/clock.h"
#include "devices/math.h"
#include "devices/screen.h"
#include "bang.h"
#include "core.h"

#define NUM_BR 5

Bedrock br[NUM_BR] = {};
Bedrock *br_main;
Bedrock *br_sub;
bool main_on_bottom = TRUE;


u8 main_program[] = {
    #include "../include/cobalt.br.inc"
};
u8 keyboard_program[] = {
    00 //#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();
}


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)

    // Set memory identifiers.
    for (int i=0; i<NUM_BR; i++) {
        br[i].mem.id = i+1;
    }

    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;
    }
}