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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#include <3ds.h>
#include "../gc.h"
#include "../platform.h"
#include "../util.h"
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* These cache-size details are from
* https://www.copetti.org/writings/consoles/nintendo-3ds/. We call the second
* level of cache (only available on N3DS) L3, since the GC design only cares
* about L1D and L3.
*/
size_t get_l1d_size(void) { return 16 * 1024; }
size_t get_l3_size(void) { return 2 * 1024 * 1024; }
uintptr_t alloc_gc_region(size_t size) {
void *ptr = malloc(size);
assume(ptr != NULL);
return (uintptr_t)ptr;
}
void clear_gc_region(uintptr_t addr, size_t size) {
memset((void *)addr, 0, size);
}
void panic_begin(void) { consoleInit(GFX_TOP, NULL); }
noreturn void panic_end(void) {
printf("\nPress Start to exit.\n");
while (aptMainLoop()) {
hidScanInput();
u32 keys = hidKeysDown();
if (keys & KEY_START)
break;
gfxFlushBuffers();
gfxSwapBuffers();
gspWaitForVBlank();
}
gfxExit();
exit(1);
}
int main(int argc, char **argv) {
gfxInit(GSP_BGR8_OES, GSP_BGR8_OES, false);
gc_init();
bootstrap();
// Initialize console on top screen. Using NULL as the second argument tells
// the console library to use the internal console structure as current one
consoleInit(GFX_TOP, NULL);
// Move the cursor to row 15 and column 19 and then prints "Hello World!"
// To move the cursor you have to print "\x1b[r;cH", where r and c are
// respectively the row and column where you want your cursor to move The top
// screen has 30 rows and 50 columns The bottom screen has 30 rows and 40
// columns
printf("\x1b[16;20HHello World!");
printf("\x1b[29;16HPress Start to exit.\n");
// Main loop
const struct value ZERO = {.bits = (0 << 2) | TAG_FIXNUM};
struct object *values = gc_alloc(64, 0);
struct object *value_slot_counts = gc_alloc(64, 0);
gc_root_push(&values);
gc_root_push(&value_slot_counts);
bool gc_test = false;
while (aptMainLoop()) {
// Scan all the inputs. This should be done once for each frame
hidScanInput();
// hidKeysDown returns information about which buttons have been just
// pressed (and they weren't in the previous frame)
u32 kDown = hidKeysDown();
if (kDown & KEY_START)
break; // break in order to return to hbmenu
if (kDown & KEY_A)
gc_test = true;
circlePosition pos;
hidCircleRead(&pos);
printf("\x1b[0;0H\x1b[K(%" PRId16 ", %" PRId16 ")\n", pos.dx, pos.dy);
if (gc_test) {
for (size_t j = 0; j < 1000; j++) {
if ((rand() & 0b11) == 0) {
size_t value_slot_count = rand() & 7;
if (!value_slot_count)
value_slot_count = 1;
size_t untraced_slot_count = rand() & 7;
struct value value =
alloc_builtin_object(ZERO, value_slot_count, untraced_slot_count);
size_t i = rand() % 63;
gc_write_value_slot(values, i, value);
gc_write_value_slot(value_slot_counts, i,
integer_of_int(value_slot_count));
} else {
size_t i = rand() & 63;
struct value value = gc_read_value_slot(values, i);
struct value value_slot_count_value =
gc_read_value_slot(value_slot_counts, i);
if (!value.bits)
continue;
assume(get_tag(value) == TAG_BUILTIN_OBJECT);
assume(get_tag(value_slot_count_value) == TAG_FIXNUM);
struct object *obj = untag_ptr(value);
intptr_t value_slot_count = untag_fixnum(value_slot_count_value);
size_t j = rand() % value_slot_count;
size_t k = rand() % 63;
gc_write_value_slot(obj, j, gc_read_value_slot(values, k));
}
}
gc_debug();
}
/*
// Get the bottom screen's frame buffer
u16 w, h;
u8 *fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, &w, &h);
for (u16 j = 0; j < h; j++) {
for (u16 i = 0; i < w; i++) {
*fb++ = (u8)(((float)i / (float)w) * 255.0);
*fb++ = (u8)(((float)j / (float)h) * 255.0);
*fb++ = 0x00;
}
}
// Flush and swap framebuffers
gfxFlushBuffers();
gfxSwapBuffers();
*/
// Wait for VBlank
gspWaitForVBlank();
}
gfxExit();
return 0;
}
|