From 012dd6e71ad79bbcc70510a85050c59bcc1c4f32 Mon Sep 17 00:00:00 2001 From: grgr-dkrk <40130327+grgr-dkrk@users.noreply.github.com> Date: Mon, 20 Apr 2020 16:53:03 +0900 Subject: [PATCH] initial_commit --- .gitignore | 1 + Cargo.lock | 5 ++ Cargo.toml | 9 +++ README.md | 2 + crt0.s | 129 ++++++++++++++++++++++++++++++++++++++++++ linker.ld | 69 ++++++++++++++++++++++ src/main.rs | 23 ++++++++ thumbv4-none-agb.json | 39 +++++++++++++ 8 files changed, 277 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 README.md create mode 100644 crt0.s create mode 100644 linker.ld create mode 100644 src/main.rs create mode 100644 thumbv4-none-agb.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..0149c51 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "rust-gba-game" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..c86e9d1 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "rust-gba-game" +version = "0.1.0" +authors = ["grgr-dkrk <40130327+grgr-dkrk@users.noreply.github.com>"] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/README.md b/README.md new file mode 100644 index 0000000..65f1daa --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +# Rust-GBA-Game + diff --git a/crt0.s b/crt0.s new file mode 100644 index 0000000..d93cf51 --- /dev/null +++ b/crt0.s @@ -0,0 +1,129 @@ + .arm +__start: + b .Linit + + @ ROM header + .byte 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21,0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad + .byte 0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21,0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20 + .byte 0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec,0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf + .byte 0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1,0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc + .byte 0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61,0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76 + .byte 0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56,0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd + .byte 0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1,0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25 + .byte 0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2,0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44 + .byte 0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94,0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf + .byte 0xd6,0x25,0xe4,0x8b,0x38,0x0a,0xac,0x72,0x21,0xd4,0xf8,0x07 + + @ game title + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 + + @ game code + .byte 0x00,0x00,0x00,0x00 + + @ maker code + .byte 0x00,0x00 + + .byte 0x96 + + @ main unit code + .byte 0x00 + + @ device type (0x00 retail, 0x80 debug) + .byte 0x00 + + @ reserved + .byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00 + + @ software version + .byte 0x00 + + @ complement check + .byte 0x51 + + @ reserved area + .space 2 + +.Linit: + @ Set address of user IRQ handler + ldr r0, =MainIrqHandler + ldr r1, =0x03FFFFFC + str r0, [r1] + + @ set IRQ stack pointer + mov r0, #0x12 + msr CPSR_c, r0 + ldr sp, =0x3007fa0 + + @ set user stack pointer + mov r0, #0x1f + msr CPSR_c, r0 + ldr sp, =0x3007f00 + + @ copy .data section to IWRAM + ldr r0, =__data_lma @ source address + ldr r1, =__data_start @ destination address + ldr r2, =__data_end + subs r2, r1 @ length + @ these instructions are only executed if r2 is nonzero + @ (i.e. don't bother copying an empty .data section) + addne r2, #3 + asrne r2, #2 + addne r2, #0x04000000 + swine 0xb0000 + + @ jump to user code + ldr r0, =main + bx r0 + + .arm + .global MainIrqHandler + .align 4, 0 +MainIrqHandler: + @ Load base I/O register address + mov r2, #0x04000000 + add r2, r2, #0x200 + + @ Save IRQ stack pointer and IME + mrs r0, spsr + ldrh r1, [r2, #8] + stmdb sp!, {r0-r2,lr} + + @ Disable all interrupts by writing to IME + @ r2 (0x4000200) can be used as we only care about bit 0 being unset + strh r2, [r2, #8] + + @ Acknowledge all received interrupts that were enabled in IE + ldr r3, [r2, #0] + and r0, r3, r3, lsr #16 + strh r0, [r2, #2] + + @ Switch from IRQ mode to system mode + @ cpsr_c = 0b000_10010u8 | 0b000_01101u8 + mrs r2, cpsr + orr r2, r2, #0xD + msr cpsr_c, r2 + + @ Jump to user specified IRQ handler + ldr r2, =__IRQ_HANDLER + ldr r1, [r2] + stmdb sp!, {lr} + adr lr, .Lreturn + bx r1 +.Lreturn: + ldmia sp!, {lr} + + @ Switch from ??? mode to IRQ mode, disable IRQ + @ cpsr_c = ( !0b000_01101u8 & cpsr_c ) | 0b100_10010u8 + mrs r2, cpsr + bic r2, r2, #0xD + orr r2, r2, #0x92 + msr cpsr_c, r2 + + @ Restore IRQ stack pointer and IME + ldmia sp!, {r0-r2,lr} + strh r1, [r2, #8] + msr spsr_cf, r0 + + @ Return to BIOS IRQ handler + bx lr + .pool \ No newline at end of file diff --git a/linker.ld b/linker.ld new file mode 100644 index 0000000..6c32fc0 --- /dev/null +++ b/linker.ld @@ -0,0 +1,69 @@ +ENTRY(__start) + +MEMORY { + ewram (w!x) : ORIGIN = 0x2000000, LENGTH = 256K + iwram (w!x) : ORIGIN = 0x3000000, LENGTH = 32K + rom (rx) : ORIGIN = 0x8000000, LENGTH = 32M +} + +SECTIONS { + .text : { + KEEP(target/crt0.o(.text)); + *(.text .text.*); + . = ALIGN(4); + } >rom = 0xff + + .rodata : { + *(.rodata .rodata.*); + . = ALIGN(4); + } >rom = 0xff + + __data_lma = .; + .data : { + __data_start = ABSOLUTE(.); + *(.data .data.*); + . = ALIGN(4); + __data_end = ABSOLUTE(.); + } >iwram AT>rom = 0xff + + .bss : { + *(.bss .bss.*); + . = ALIGN(4); + __bss_end = ABSOLUTE(.); + } >iwram + + /* debugging sections */ + /* Stabs */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + + /* discard anything not already mentioned */ + /DISCARD/ : { *(*) } +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..8aa3c55 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,23 @@ +#![no_std] +#![feature(start)] + +#[panic_handler] +fn panic(_info: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + unsafe { + (0x400_0000 as *mut u16).write_volatile(0x0403); + (0x600_0000 as *mut u16).offset(120 + 80 * 240).write_volatile(0x001F); + (0x600_0000 as *mut u16).offset(136 + 80 * 240).write_volatile(0x03E0); + (0x600_0000 as *mut u16).offset(120 + 96 * 240).write_volatile(0x7C00); + loop {} + } +} + +#[no_mangle] +static __IRQ_HANDLER: extern "C" fn() = irq_handler; + +extern "C" fn irq_handler() {} diff --git a/thumbv4-none-agb.json b/thumbv4-none-agb.json new file mode 100644 index 0000000..6eb580e --- /dev/null +++ b/thumbv4-none-agb.json @@ -0,0 +1,39 @@ +{ + "abi-blacklist": [ + "stdcall", + "fastcall", + "vectorcall", + "thiscall", + "win64", + "sysv64" + ], + "arch": "arm", + "atomic-cas": false, + "cpu": "arm7tdmi", + "data-layout": "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64", + "emit-debug-gdb-scripts": false, + "env": "agb", + "executables": true, + "features": "+soft-float,+strict-align", + "linker": "arm-none-eabi-ld", + "linker-flavor": "ld", + "linker-is-gnu": true, + "llvm-target": "thumbv4-none-agb", + "os": "none", + "panic-strategy": "abort", + "pre-link-args-crt": { + "ld": [ + "crt0.o" + ] + }, + "pre-link-args": { + "ld": [ + "-Tlinker.ld" + ] + }, + "relocation-model": "static", + "target-c-int-width": "32", + "target-endian": "little", + "target-pointer-width": "32", + "vendor": "nintendo" +} \ No newline at end of file