idk wip
This commit is contained in:
parent
d8f573c678
commit
7f69f474f6
4 changed files with 636 additions and 57 deletions
141
source/main.c
141
source/main.c
|
@ -88,7 +88,7 @@ volatile FIXED_POINT K2 = (2 * CUBE_WIDTH) + 20;
|
|||
#define SQ(n) (n * n)
|
||||
#define SQ_FP(n) (MULT_FP(n, n))
|
||||
|
||||
#define COORD2INDEX(x, y) (x * VWIDTH + y)
|
||||
#define COORD2INDEX(x, y) (y * VWIDTH + x)
|
||||
#define COUPLE2INDEX(x) (COORD2INDEX(x[0], x[1]))
|
||||
|
||||
#define GET_ROTATE_X_Q(a) ({ float _a = (FIXED2FLOAT(a)) ; \
|
||||
|
@ -117,7 +117,7 @@ struct Quaternions {
|
|||
FIXED_POINT x;
|
||||
FIXED_POINT y;
|
||||
FIXED_POINT z;
|
||||
} Target, Current, Last;
|
||||
} Target, Current;
|
||||
|
||||
FIXED_POINT interpolationStep = 0;
|
||||
FIXED_POINT zBuffer[VHEIGHT * VWIDTH];
|
||||
|
@ -235,38 +235,62 @@ chooseMainFace()
|
|||
return frontFacingFace;
|
||||
}
|
||||
|
||||
void
|
||||
fill_quads(char current_face, char top_left[2], char top_right[2],
|
||||
char bot_left[2], char bot_right[2])
|
||||
char
|
||||
isInQuad(char curr[2], char top[2], char left[2],
|
||||
char right[2], char bot[2])
|
||||
{
|
||||
// calc slope foreach side
|
||||
float slope_top = 0;
|
||||
float slope_bot = 0;
|
||||
float slope_left = INFINITY;
|
||||
float slope_right = -INFINITY;
|
||||
char *points[4] = {top, left, bot, right};
|
||||
|
||||
if (top_left[0] != top_right[0])
|
||||
slope_top = (float)(top_right[1] - top_left[1]) /
|
||||
(float)(top_right[0] - top_left[0]);
|
||||
if (bot_left[0] == bot_right[0])
|
||||
slope_bot = (float)(bot_right[1] - bot_left[1]) /
|
||||
(float)(bot_right[0] - bot_left[0]);
|
||||
if (top_left[0] == bot_left[0])
|
||||
slope_left = (float)(bot_left[1] - top_left[1]) /
|
||||
(float)(bot_left[0] - top_left[0]);
|
||||
if (top_right[0] == bot_right[0])
|
||||
slope_right = (float)(bot_right[1] - top_right[1]) /
|
||||
(float)(bot_right[0] - top_right[0]);
|
||||
char pos = 0, neg = 0;
|
||||
char x = curr[0];
|
||||
char y = curr[1];;
|
||||
int d;
|
||||
|
||||
int top = top_right[1] > top_left[1] ? top_right[1]: top_left[1];
|
||||
int bot = bot_right[1] > bot_left[1] ? bot_right[1]: bot_left[1];
|
||||
int left = top_left[0] > bot_left[0] ? top_left[0]: bot_left[0];
|
||||
int right = top_right[0] > bot_right[0] ? top_right[0]: bot_right[0];
|
||||
for (int y = top ; y <= bot ; ++y) {
|
||||
for (int x = left ; x <= right ; ++x) {
|
||||
if (slope_top * x + top <= y)
|
||||
// TODO side check
|
||||
output[COORD2INDEX(x, y)] = current_face;
|
||||
for (char i = 0; i < 4; ++i) {
|
||||
if (points[i][0] == curr[0] && points[i][1] == curr[1])
|
||||
return 1;
|
||||
|
||||
//Form a segment between the i'th point
|
||||
char x1 = points[i][0];
|
||||
char y1 = points[i][1];
|
||||
|
||||
//And the i+1'th, or if i is the last, with the first point
|
||||
char i2 = (i + 1) % 4;
|
||||
|
||||
char x2 = points[i2][0];
|
||||
char y2 = points[i2][1];
|
||||
|
||||
|
||||
//Compute the cross product
|
||||
d = (x - x1) * (y2 - y1) - (y - y1) * (x2 - x1);
|
||||
|
||||
if (d > 0) ++pos;
|
||||
if (d < 0) ++neg;
|
||||
|
||||
//If the sign changes, then point is outside
|
||||
if (pos > 0 && neg > 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
fill_quads(char current_face, char top[2], char left[2],
|
||||
char right[2], char bot[2])
|
||||
{
|
||||
if (current_face != 0) return;
|
||||
output[COUPLE2INDEX(top)] = RGB15(0, 0, 15);
|
||||
output[COUPLE2INDEX(left)] = RGB15(0, 0, 15);
|
||||
output[COUPLE2INDEX(right)] = RGB15(0, 0, 15);
|
||||
|
||||
for (int y = top[1] ; y < bot[1] ; ++y) {
|
||||
for (int x = left[0] ; x < right[0] ; ++x) {
|
||||
char curr[2] = {x, y};
|
||||
if (isInQuad(curr, top, left, right, bot))
|
||||
//zbuffer issue
|
||||
{}
|
||||
//output[COORD2INDEX(x, y)] = current_face;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -275,33 +299,37 @@ void
|
|||
detect_and_fill_quads()
|
||||
{
|
||||
for (int current_face = 0 ; current_face < NUM_FACES ; ++current_face) {
|
||||
char top_left [2] = {VWIDTH, VHEIGHT};
|
||||
char top_right[2] = {0, VHEIGHT};
|
||||
char bot_left [2] = {VWIDTH, 0};
|
||||
char bot_right[2] = {0, 0};
|
||||
char last_top [2] = {VWIDTH, VHEIGHT};
|
||||
char last_left[2] = {VWIDTH, 0};
|
||||
char last_right [2] = {0, 0};
|
||||
char last_bot[2] = {0, 0};
|
||||
char top [2] = {VWIDTH, VHEIGHT};
|
||||
char left[2] = {VWIDTH, 0};
|
||||
char right [2] = {0, 0};
|
||||
char bot[2] = {0, 0};
|
||||
for (char y = 0; y < VHEIGHT; ++y) {
|
||||
for (char x = 0; x < VWIDTH; ++x) {
|
||||
if (output[COORD2INDEX(x, y)] != current_face)
|
||||
continue;
|
||||
if (x <= top_left[0] && y <= top_left[1]){
|
||||
top_left[0] = x;
|
||||
top_left[1] = y;
|
||||
if (x <= left[0]) {
|
||||
left[0] = x;
|
||||
left[1] = y;
|
||||
}
|
||||
if (x >= top_right[0] && y <= top_right[1]){
|
||||
top_right[0] = x;
|
||||
top_right[1] = y;
|
||||
if (y <= top[1]) {
|
||||
top[0] = x;
|
||||
top[1] = y;
|
||||
}
|
||||
if (x <= bot_left[0] && y >= bot_left[1]){
|
||||
bot_left[0] = x;
|
||||
bot_left[1] = y;
|
||||
if (x >= right[0]) {
|
||||
right[0] = x;
|
||||
right[1] = y;
|
||||
}
|
||||
if (x >= bot_right[0] && y >= bot_right[1]){
|
||||
bot_right[0] = x;
|
||||
bot_right[1] = y;
|
||||
if (y >= bot[1]) {
|
||||
bot[0] = x;
|
||||
bot[1] = y;
|
||||
}
|
||||
}
|
||||
}
|
||||
fill_quads(current_face, top_left, top_right, bot_left, bot_right);
|
||||
fill_quads(current_face, top, left, right, bot);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -315,7 +343,7 @@ printAscii()
|
|||
MEM_VRAM_MODE3_FB[120 + 96 * GBA_SCREEN_W] = RGB15(currentCountR, 31 - currentCountR, 0);
|
||||
currentCountR = currentCountR == 31 ? 0 : 31;
|
||||
|
||||
//detect_and_fill_quads();
|
||||
detect_and_fill_quads();
|
||||
|
||||
for (int i = 0; i < VHEIGHT; ++i) {
|
||||
for (int j = 0; j < VWIDTH; ++j) {
|
||||
|
@ -411,31 +439,30 @@ handleAngle(char input)
|
|||
// TODO
|
||||
if (currentlyMoving == 0) {
|
||||
currentlyMoving = input;
|
||||
Last = Current;
|
||||
switch (input) {
|
||||
case 'w':
|
||||
case 'W':
|
||||
Target = multQ(GET_ROTATE_X_Q(FLOAT2FIXED(M_PI_2)), Target);
|
||||
Target = multQ(GET_ROTATE_X_Q(FLOAT2FIXED(M_PI_2)), Current);
|
||||
break;
|
||||
case 'a':
|
||||
case 'A':
|
||||
Target = multQ(GET_ROTATE_Y_Q(-FLOAT2FIXED(M_PI_2)), Target);
|
||||
Target = multQ(GET_ROTATE_Y_Q(-FLOAT2FIXED(M_PI_2)), Current);
|
||||
break;
|
||||
case 's':
|
||||
case 'S':
|
||||
Target = multQ(GET_ROTATE_X_Q(-FLOAT2FIXED(M_PI_2)), Target);
|
||||
Target = multQ(GET_ROTATE_X_Q(-FLOAT2FIXED(M_PI_2)), Current);
|
||||
break;
|
||||
case 'd':
|
||||
case 'D':
|
||||
Target = multQ(GET_ROTATE_Y_Q(FLOAT2FIXED(M_PI_2)), Target);
|
||||
Target = multQ(GET_ROTATE_Y_Q(FLOAT2FIXED(M_PI_2)), Current);
|
||||
break;
|
||||
case 'q':
|
||||
case 'Q':
|
||||
Target = multQ(GET_ROTATE_Z_Q(-FLOAT2FIXED(M_PI_2)), Target);
|
||||
Target = multQ(GET_ROTATE_Z_Q(-FLOAT2FIXED(M_PI_2)), Current);
|
||||
break;
|
||||
case 'e':
|
||||
case 'E':
|
||||
Target = multQ(GET_ROTATE_Z_Q(FLOAT2FIXED(M_PI_2)), Target);
|
||||
Target = multQ(GET_ROTATE_Z_Q(FLOAT2FIXED(M_PI_2)), Current);
|
||||
break;
|
||||
default:
|
||||
currentlyMoving = 0;
|
||||
|
@ -480,7 +507,7 @@ main()
|
|||
cubeX <= CUBE_WIDTH_FP - STEP_FP; cubeX += STEP_FP) {
|
||||
for (FIXED_POINT cubeY = -CUBE_WIDTH_FP + STEP_FP;
|
||||
cubeY <= CUBE_WIDTH_FP - STEP_FP; cubeY += STEP_FP) {
|
||||
switch (frontFacingFace) {
|
||||
switch (FACE_FRONT) {
|
||||
case FACE_FRONT:
|
||||
rotateCube(cubeX, cubeY, -CUBE_WIDTH_FP, FACE_FRONT);
|
||||
break;
|
||||
|
|
233
source/sys/gba_cart.ld
Normal file
233
source/sys/gba_cart.ld
Normal file
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* SPDX-License-Identifier: CC0-1.0
|
||||
*
|
||||
* SPDX-FileContributor: Antonio Niño Díaz, 2022
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some links with information about linker scripts:
|
||||
*
|
||||
* - https://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/specialsections.html
|
||||
*
|
||||
* - https://blog.thea.codes/the-most-thoroughly-commented-linker-script/
|
||||
*
|
||||
* - http://beefchunk.com/documentation/sys-programming/binary_formats/elf/elf_from_the_programmers_perspective/node4.html
|
||||
*/
|
||||
|
||||
OUTPUT_FORMAT("elf32-littlearm")
|
||||
OUTPUT_ARCH(arm)
|
||||
ENTRY(entrypoint)
|
||||
|
||||
MEMORY {
|
||||
ROM : ORIGIN = 0x08000000, LENGTH = 32M
|
||||
IWRAM : ORIGIN = 0x03000000, LENGTH = 32K
|
||||
EWRAM : ORIGIN = 0x02000000, LENGTH = 256K
|
||||
}
|
||||
|
||||
/* Set stack pointers the same way as the BIOS */
|
||||
|
||||
__STACK_SVC_SIZE__ = 0x40;
|
||||
__STACK_IRQ_SIZE__ = 0xA0;
|
||||
__STACK_USR_SIZE_MIN__ = 0x200; /* Minimum size, the real size may be bigger */
|
||||
|
||||
__STACK_END__ = ORIGIN(IWRAM) + LENGTH(IWRAM) - 0x20; /* Used by BIOS */
|
||||
__STACK_SVC_END__ = __STACK_END__;
|
||||
__STACK_SVC_START__ = __STACK_SVC_END__ - __STACK_SVC_SIZE__;
|
||||
__STACK_IRQ_END__ = __STACK_SVC_START__;
|
||||
__STACK_IRQ_START__ = __STACK_IRQ_END__ - __STACK_IRQ_SIZE__;
|
||||
__STACK_USR_END__ = __STACK_IRQ_START__;
|
||||
__STACK_USR_START__ = __STACK_USR_END__ - __STACK_USR_SIZE_MIN__;
|
||||
__STACK_START__ = __STACK_USR_START__;
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/*
|
||||
* ROM sections
|
||||
* ============
|
||||
*/
|
||||
|
||||
/* Header and crt0 */
|
||||
|
||||
.gba_crt0 : ALIGN(4)
|
||||
{
|
||||
KEEP (*(.gba_crt0))
|
||||
} > ROM
|
||||
|
||||
/* Code */
|
||||
|
||||
.text : ALIGN(4)
|
||||
{
|
||||
*(.text)
|
||||
*(.text*)
|
||||
*(.gnu.linkonce.t.*) /* Used for vague linking */
|
||||
|
||||
/* ARM/Thumb interworking code */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
|
||||
/* Array of functions to be called at the start of the program */
|
||||
KEEP(*(.init))
|
||||
/* Array of functions to be called at the end of the program */
|
||||
KEEP(*(.fini))
|
||||
} > ROM
|
||||
|
||||
/* Read-only data */
|
||||
|
||||
.rodata : ALIGN(4)
|
||||
{
|
||||
*(.rodata)
|
||||
*(.rodata*)
|
||||
*(.gnu.linkonce.r.*) /* Used for vague linking */
|
||||
} > ROM
|
||||
|
||||
/*
|
||||
* Required for C++ and for C programs that try to examine backtraces. Each
|
||||
* function that can throw exceptions has entries in exidx and extab.
|
||||
*
|
||||
* - exidx is used to contain index entries for stack unwinding.
|
||||
* - extab names sections containing exception unwinding information.
|
||||
*/
|
||||
|
||||
.ARM.extab : ALIGN(4)
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > ROM
|
||||
|
||||
.ARM.exidx : ALIGN(4)
|
||||
{
|
||||
PROVIDE_HIDDEN(__exidx_start = .);
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
PROVIDE_HIDDEN(__exidx_end = .);
|
||||
} > ROM
|
||||
|
||||
/* Array of functions to be called during initialization of the program */
|
||||
|
||||
.preinit_array : ALIGN(4)
|
||||
{
|
||||
__preinit_array_start = .;
|
||||
KEEP(*(.preinit_array*))
|
||||
__preinit_array_end = .;
|
||||
} > ROM
|
||||
|
||||
/*
|
||||
* Array of functions to be called during initialization of the program.
|
||||
* They are called after calling everything in .preinit_array
|
||||
*/
|
||||
|
||||
.init_array : ALIGN(4)
|
||||
{
|
||||
__init_array_start = .;
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array*))
|
||||
__init_array_end = .;
|
||||
} > ROM
|
||||
|
||||
/* Array of functions called when the program ends. */
|
||||
|
||||
.fini_array : ALIGN(4)
|
||||
{
|
||||
__fini_array_start = .;
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array*))
|
||||
__fini_array_end = .;
|
||||
} > ROM
|
||||
|
||||
/*
|
||||
* IWRAM sections
|
||||
* ==============
|
||||
*/
|
||||
|
||||
/* Uninitialized variables */
|
||||
|
||||
.bss (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(.gnu.linkonce.b.*) /* Used for vague linking */
|
||||
*(COMMON) /* In case -fcommon is used in gcc (not used by default) */
|
||||
. = ALIGN(4);
|
||||
} > IWRAM
|
||||
|
||||
__IWRAM_BSS_START__ = ADDR(.bss);
|
||||
__IWRAM_BSS_SIZE__ = SIZEOF(.bss);
|
||||
__IWRAM_BSS_END__ = __IWRAM_BSS_START__ + __IWRAM_BSS_SIZE__;
|
||||
|
||||
/* Read-write data goes into IWRAM */
|
||||
|
||||
.data : ALIGN(4)
|
||||
{
|
||||
__DATA_START__ = .;
|
||||
*(.data)
|
||||
*(.data*)
|
||||
*(.gnu.linkonce.d.*) /* Used for vague linking */
|
||||
. = ALIGN(4);
|
||||
__DATA_END__ = .;
|
||||
} > IWRAM AT> ROM
|
||||
|
||||
__DATA_SIZE__ = __DATA_END__ - __DATA_START__;
|
||||
__DATA_LMA__ = LOADADDR(.data);
|
||||
|
||||
/* Sections that the user requests to add to IWRAM */
|
||||
|
||||
.iwram : ALIGN(4)
|
||||
{
|
||||
__IWRAM_START__ = .;
|
||||
*(.iwram)
|
||||
*(.iwram*)
|
||||
*iwram.*(.text*)
|
||||
*iwram.*(.data*)
|
||||
. = ALIGN(4);
|
||||
__IWRAM_END__ = .;
|
||||
} > IWRAM AT> ROM
|
||||
|
||||
__IWRAM_SIZE__ = __IWRAM_END__ - __IWRAM_START__;
|
||||
__IWRAM_LMA__ = LOADADDR(.iwram);
|
||||
|
||||
/* The stack goes afterwards, check that there aren't overflows */
|
||||
|
||||
ASSERT(__IWRAM_END__ <= __STACK_START__,
|
||||
"Not enough free IWRAM for stack")
|
||||
|
||||
/* Calculate real size of the user stack */
|
||||
|
||||
__STACK_USR_SIZE__ = __STACK_USR_END__ - __IWRAM_END__;
|
||||
|
||||
/*
|
||||
* EWRAM sections
|
||||
* ==============
|
||||
*/
|
||||
|
||||
/*
|
||||
* Uninitialized data explicitly placed in EWRAM. This section must be
|
||||
* called ".sbss" for compatibility with devkitARM.
|
||||
*/
|
||||
|
||||
.sbss (NOLOAD) : ALIGN(4)
|
||||
{
|
||||
*(.sbss)
|
||||
*(.sbss*)
|
||||
. = ALIGN(4);
|
||||
} > EWRAM
|
||||
|
||||
/* Initialized data explicitly placed in EWRAM */
|
||||
|
||||
.ewram : ALIGN(4)
|
||||
{
|
||||
__EWRAM_START__ = .;
|
||||
*(.ewram)
|
||||
*(.ewram*)
|
||||
*ewram.*(.text*)
|
||||
*ewram.*(.data*)
|
||||
. = ALIGN(4);
|
||||
__EWRAM_END__ = .;
|
||||
} > EWRAM AT > ROM
|
||||
|
||||
__EWRAM_SIZE__ = __EWRAM_END__ - __EWRAM_START__;
|
||||
__EWRAM_LMA__ = LOADADDR(.ewram);
|
||||
|
||||
/* The heap information should be after the last EWRAM section */
|
||||
|
||||
__HEAP_START__ = __EWRAM_END__;
|
||||
__HEAP_END__ = ORIGIN(EWRAM) + LENGTH(EWRAM);
|
||||
__HEAP_SIZE__ = __HEAP_END__ - __HEAP_START__;
|
||||
}
|
142
source/sys/gba_crt0.s
Normal file
142
source/sys/gba_crt0.s
Normal file
|
@ -0,0 +1,142 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
//
|
||||
// SPDX-FileContributor: Antonio Niño Díaz, 2022
|
||||
|
||||
.section .gba_crt0, "ax"
|
||||
.global entrypoint
|
||||
.cpu arm7tdmi
|
||||
|
||||
.arm
|
||||
|
||||
entrypoint:
|
||||
b header_end
|
||||
|
||||
.fill 156, 1, 0 // Nintendo Logo
|
||||
.fill 12, 1, 0 // Game Title
|
||||
.fill 4, 1, 0 // Game Code
|
||||
.byte 0x30, 0x30 // Maker Code ("00")
|
||||
.byte 0x96 // Fixed Value (must be 0x96)
|
||||
.byte 0x00 // Main unit code
|
||||
.byte 0x00 // Device Type
|
||||
.fill 7, 1, 0 // Reserved Area
|
||||
.byte 0x00 // Software version
|
||||
.byte 0x00 // Complement check (header checksum)
|
||||
.byte 0x00, 0x00 // Reserved Area
|
||||
|
||||
header_end:
|
||||
b start_vector
|
||||
|
||||
// Multiboot Header Entries
|
||||
.byte 0 // Boot mode
|
||||
.byte 0 // Slave ID Number
|
||||
.fill 26, 1, 0 // Not used
|
||||
.word 0 // JOYBUS entrypoint
|
||||
|
||||
.align
|
||||
|
||||
start_vector:
|
||||
|
||||
// Disable interrupts
|
||||
mov r0, #0x4000000
|
||||
mov r1, #0
|
||||
str r1, [r0, #0x208] // IME
|
||||
|
||||
// Setup IRQ mode stack
|
||||
mov r0, #0x12
|
||||
msr cpsr, r0
|
||||
ldr sp, =__STACK_IRQ_END__
|
||||
|
||||
// Setup system mode stack
|
||||
mov r0, #0x1F
|
||||
msr cpsr, r0
|
||||
ldr sp, =__STACK_USR_END__
|
||||
|
||||
// Switch to Thumb mode
|
||||
add r0, pc, #1
|
||||
bx r0
|
||||
|
||||
.thumb
|
||||
|
||||
// Clear IWRAM
|
||||
ldr r0, =#0x3000000
|
||||
ldr r1, =#(32 * 1024)
|
||||
bl mem_zero
|
||||
|
||||
// Copy data section from ROM to RAM
|
||||
ldr r0, =__DATA_LMA__
|
||||
ldr r1, =__DATA_START__
|
||||
ldr r2, =__DATA_SIZE__
|
||||
bl mem_copy
|
||||
|
||||
// Copy IWRAM data from ROM to RAM
|
||||
ldr r0, =__IWRAM_LMA__
|
||||
ldr r1, =__IWRAM_START__
|
||||
ldr r2, =__IWRAM_SIZE__
|
||||
bl mem_copy
|
||||
|
||||
// Clear EWRAM
|
||||
ldr r0, =#0x2000000
|
||||
ldr r1, =#(256 * 1024)
|
||||
bl mem_zero
|
||||
|
||||
// Copy EWRAM data from ROM to RAM
|
||||
ldr r0, =__EWRAM_LMA__
|
||||
ldr r1, =__EWRAM_START__
|
||||
ldr r2, =__EWRAM_SIZE__
|
||||
bl mem_copy
|
||||
|
||||
// Global constructors
|
||||
ldr r2, =__libc_init_array
|
||||
bl blx_r2_trampoline
|
||||
|
||||
// Call main()
|
||||
mov r0, #0 // int argc
|
||||
mov r1, #0 // char *argv[]
|
||||
ldr r2, =main
|
||||
bl blx_r2_trampoline
|
||||
|
||||
// Global destructors
|
||||
ldr r2, =__libc_fini_array
|
||||
bl blx_r2_trampoline
|
||||
|
||||
// If main() returns, reboot the GBA using SoftReset
|
||||
swi #0x00
|
||||
|
||||
// r0 = Base address
|
||||
// r1 = Size
|
||||
mem_zero:
|
||||
and r1, r1
|
||||
beq 2f // Return if size is 0
|
||||
|
||||
mov r2, #0
|
||||
1:
|
||||
stmia r0!, {r2}
|
||||
sub r1, #4
|
||||
bne 1b
|
||||
|
||||
2:
|
||||
bx lr
|
||||
|
||||
// r0 = Source address
|
||||
// r1 = Destination address
|
||||
// r2 = Size
|
||||
mem_copy:
|
||||
and r2, r2
|
||||
beq 2f // Return if size is 0
|
||||
|
||||
1:
|
||||
ldmia r0!, {r3}
|
||||
stmia r1!, {r3}
|
||||
sub r2, #4
|
||||
bne 1b
|
||||
|
||||
2:
|
||||
bx lr
|
||||
|
||||
// r2 = Address to jump to
|
||||
blx_r2_trampoline:
|
||||
bx r2
|
||||
|
||||
.align
|
||||
.pool
|
||||
.end
|
177
source/sys/syscalls.c
Normal file
177
source/sys/syscalls.c
Normal file
|
@ -0,0 +1,177 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
//
|
||||
// SPDX-FileContributor: Antonio Niño Díaz, 2022
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/times.h>
|
||||
#include <time.h>
|
||||
|
||||
// This file implements stubs for system calls. For more information about it,
|
||||
// check the documentation of newlib:
|
||||
//
|
||||
// https://sourceware.org/newlib/libc.html#Syscalls
|
||||
|
||||
#undef errno
|
||||
extern int errno;
|
||||
|
||||
char *__env[1] = { 0 };
|
||||
char **environ = __env;
|
||||
|
||||
int _getpid(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig)
|
||||
{
|
||||
(void)pid;
|
||||
(void)sig;
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void _exit(int status)
|
||||
{
|
||||
_kill(status, -1);
|
||||
|
||||
// Hang, there is nowhere to go
|
||||
while (1);
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _read(int file, char *ptr, int len)
|
||||
{
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
__attribute__((weak)) int _write(int file, char *ptr, int len)
|
||||
{
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
int _close(int file)
|
||||
{
|
||||
(void)file;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int _fstat(int file, struct stat *st)
|
||||
{
|
||||
(void)file;
|
||||
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty(int file)
|
||||
{
|
||||
(void)file;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
(void)file;
|
||||
(void)ptr;
|
||||
(void)dir;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _open(char *path, int flags, ...)
|
||||
{
|
||||
(void)path;
|
||||
(void)flags;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _wait(int *status)
|
||||
{
|
||||
(void)status;
|
||||
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _unlink(char *name)
|
||||
{
|
||||
(void)name;
|
||||
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _times(struct tms *buf)
|
||||
{
|
||||
(void)buf;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _stat(char *file, struct stat *st)
|
||||
{
|
||||
(void)file;
|
||||
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _link(char *old, char *new)
|
||||
{
|
||||
(void)old;
|
||||
(void)new;
|
||||
|
||||
errno = EMLINK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _fork(void)
|
||||
{
|
||||
errno = EAGAIN;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _execve(char *name, char **argv, char **env)
|
||||
{
|
||||
(void)name;
|
||||
(void)argv;
|
||||
(void)env;
|
||||
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *_sbrk(int incr)
|
||||
{
|
||||
// Symbols defined by the linker
|
||||
extern char __HEAP_START__[];
|
||||
extern char __HEAP_END__[];
|
||||
const uintptr_t HEAP_START = (uintptr_t) __HEAP_START__;
|
||||
const uintptr_t HEAP_END = (uintptr_t) __HEAP_END__;
|
||||
|
||||
// Pointer to the current end of the heap
|
||||
static uintptr_t heap_end = HEAP_START;
|
||||
|
||||
if (heap_end + incr > HEAP_END)
|
||||
{
|
||||
errno = ENOMEM;
|
||||
return (void *)-1;
|
||||
}
|
||||
|
||||
uintptr_t prev_heap_end = heap_end;
|
||||
|
||||
heap_end += incr;
|
||||
|
||||
return (void *)prev_heap_end;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue