minimal template project for gba-0.11.3

This commit is contained in:
lif 2023-12-09 01:07:49 -08:00
commit d250bb5c46
6 changed files with 260 additions and 0 deletions

13
.cargo/config.toml Normal file
View file

@ -0,0 +1,13 @@
[build]
target = "armv4t-none-eabi"
[unstable]
build-std = ["core"]
[target.thumbv4t-none-eabi]
runner = "mgba-qt"
rustflags = ["-Clink-arg=-Tlinker_scripts/mono_boot.ld"]
[target.armv4t-none-eabi]
runner = "mgba-qt"
rustflags = ["-Clink-arg=-Tlinker_scripts/mono_boot.ld"]

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
/target

39
Cargo.lock generated Normal file
View file

@ -0,0 +1,39 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "bitfrob"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a96c7c818dc8807bb1982dd2cba4c7de0ed6eba4ffb5fc24321d1b38676a120"
[[package]]
name = "bracer"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6559b8c3065745016f5cc2d1095273fe8a175e953c976426947ad828d6ba6fda"
[[package]]
name = "gba"
version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab90d1de12c1323d80d9850c55d68931512ef7f0462a8c79e92b726f5037ad6"
dependencies = [
"bitfrob",
"bracer",
"voladdress",
]
[[package]]
name = "gba-template"
version = "0.1.0"
dependencies = [
"gba",
]
[[package]]
name = "voladdress"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fbf3fef7bc995d3f8350936bdd07966c7a1f96183d52e3f28c29d099d0b5ecc"

9
Cargo.toml Normal file
View file

@ -0,0 +1,9 @@
[package]
name = "gba-template"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
gba = "0.11.3"

100
linker_scripts/mono_boot.ld Normal file
View file

@ -0,0 +1,100 @@
/* THIS LINKER SCRIPT FILE IS RELEASED TO THE PUBLIC DOMAIN (SPDX: CC0-1.0) */
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 : {
/* be sure that the ROM header is the very first */
*(.text.gba_rom_header);
*(.text .text.*);
. = ALIGN(4);
} >rom = 0x00
.rodata : {
*(.rodata .rodata.*);
. = ALIGN(4);
} >rom = 0x00
. = ALIGN(4);
__iwram_position_in_rom = .;
.data : {
__iwram_start = ABSOLUTE(.);
*(.data .data.*);
*(.iwram .iwram.*);
. = ALIGN(4);
__iwram_end = ABSOLUTE(.);
} >iwram AT>rom = 0x00
. = ALIGN(4);
__ewram_position_in_rom = __iwram_position_in_rom + (__iwram_end - __iwram_start);
.ewram : {
__ewram_start = ABSOLUTE(.);
*(.ewram .ewram.*);
. = ALIGN(4);
__ewram_end = ABSOLUTE(.);
} >ewram AT>rom = 0x00
. = ALIGN(4);
__bss_position_in_rom = __ewram_position_in_rom + (__ewram_end - __ewram_start);
.bss : {
__bss_start = ABSOLUTE(.);
*(.bss .bss.*);
. = ALIGN(4);
__bss_end = ABSOLUTE(.);
} >iwram
__iwram_word_copy_count = (__iwram_end - __iwram_start) / 4;
__ewram_word_copy_count = (__ewram_end - __ewram_start) / 4;
__bss_word_clear_count = (__bss_end - __bss_start) / 4;
/* rust-lld demands we keep the `section header string table` */
.shstrtab 0 : { *(.shstrtab) }
/* 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/ : { *(*) }
}

98
src/main.rs Normal file
View file

@ -0,0 +1,98 @@
// from https://github.com/rust-console/gba/blob/main/examples/hello.rs
#![no_std]
#![no_main]
use core::fmt::Write;
use gba::prelude::*;
#[panic_handler]
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
#[cfg(debug_assertions)]
if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Fatal) {
writeln!(logger, "{info}").ok();
}
loop {}
}
#[link_section = ".ewram"]
static FRAME_KEYS: GbaCell<KeyInput> = GbaCell::new(KeyInput::new());
#[link_section = ".iwram"]
extern "C" fn irq_handler(_: IrqBits) {
// We'll read the keys during vblank and store it for later.
FRAME_KEYS.write(KEYINPUT.read());
}
#[no_mangle]
extern "C" fn main() -> ! {
RUST_IRQ_HANDLER.write(Some(irq_handler));
DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true));
IE.write(IrqBits::VBLANK);
IME.write(true);
if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Debug) {
writeln!(logger, "hello!").ok();
let fx_u: Fixed<u32, 8> = Fixed::<u32, 8>::wrapping_from(7) + Fixed::<u32, 8>::from_raw(12);
writeln!(logger, "fixed unsigned: {fx_u:?}").ok();
let fx_i1: Fixed<i32, 8> =
Fixed::<i32, 8>::wrapping_from(8) + Fixed::<i32, 8>::from_raw(15);
writeln!(logger, "fixed signed positive: {fx_i1:?}").ok();
let fx_i2: Fixed<i32, 8> = Fixed::<i32, 8>::wrapping_from(0)
- Fixed::<i32, 8>::wrapping_from(3)
- Fixed::<i32, 8>::from_raw(17);
writeln!(logger, "fixed signed negative: {fx_i2:?}").ok();
}
{
// get our tile data into memory.
Cga8x8Thick.bitunpack_4bpp(CHARBLOCK0_4BPP.as_region(), 0);
}
{
// set up the tilemap
let tsb = TEXT_SCREENBLOCKS.get_frame(31).unwrap();
for y in 0..16 {
let row = tsb.get_row(y).unwrap();
for (x, addr) in row.iter().enumerate().take(16) {
let te = TextEntry::new().with_tile((y * 16 + x) as u16);
addr.write(te);
}
}
}
{
// Set BG0 to use the tilemap we just made, and set it to be shown.
BG0CNT.write(BackgroundControl::new().with_screenblock(31));
DISPCNT.write(DisplayControl::new().with_show_bg0(true));
}
let mut x_off = 0_u32;
let mut y_off = 0_u32;
let mut backdrop_color = Color(0);
loop {
VBlankIntrWait();
// show current frame
BACKDROP_COLOR.write(backdrop_color);
BG0HOFS.write(x_off as u16);
BG0VOFS.write(y_off as u16);
// prep next frame
let k = FRAME_KEYS.read();
backdrop_color = Color(k.to_u16());
if k.up() {
y_off = y_off.wrapping_add(1);
}
if k.down() {
y_off = y_off.wrapping_sub(1);
}
if k.left() {
x_off = x_off.wrapping_add(1);
}
if k.right() {
x_off = x_off.wrapping_sub(1);
}
}
}