diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/luma.rs | 30 | ||||
-rw-r--r-- | src/luma/app.rs | 15 | ||||
-rw-r--r-- | src/luma/app/emu.rs | 64 | ||||
-rw-r--r-- | src/luma/app/end.rs | 21 | ||||
-rw-r--r-- | src/luma/app/ini.rs | 16 | ||||
-rw-r--r-- | src/luma/app/new.rs | 17 | ||||
-rw-r--r-- | src/luma/app/prspar.rs | 26 | ||||
-rw-r--r-- | src/luma/app/run.rs | 44 | ||||
-rw-r--r-- | src/luma/app/trp.rs | 29 | ||||
-rw-r--r-- | src/main.rs | 10 |
10 files changed, 272 insertions, 0 deletions
diff --git a/src/luma.rs b/src/luma.rs new file mode 100644 index 0000000..57c2768 --- /dev/null +++ b/src/luma.rs @@ -0,0 +1,30 @@ +// Copyright 2021-2023 Gabriel Jensen. + +pub mod app; + +pub const VER: u32 = 0x1E; + +pub const MEMSIZ: usize = 0x0E010000; + +pub const BTLSIZ: usize = 0x00004000; +pub const IMGSIZ: usize = 0x06000000; + +pub struct Reg { + r0: u32, + r1: u32, + r2: u32, + r3: u32, + r4: u32, + r5: u32, + r6: u32, + r7: u32, + r8: u32, + r9: u32, + r10: u32, + r11: u32, + r12: u32, + sp: u32, + lr: u32, + pc: u32, + cpsr: u32, +} diff --git a/src/luma/app.rs b/src/luma/app.rs new file mode 100644 index 0000000..d12dbfa --- /dev/null +++ b/src/luma/app.rs @@ -0,0 +1,15 @@ +// Copyright 2021-2023 Gabriel Jensen. + +pub mod emu; +pub mod end; +pub mod ini; +pub mod new; +pub mod prspar; +pub mod run; +pub mod trp; + +pub struct App { + btl: String, + img: String, + mem: *mut u8, +} diff --git a/src/luma/app/emu.rs b/src/luma/app/emu.rs new file mode 100644 index 0000000..3dad048 --- /dev/null +++ b/src/luma/app/emu.rs @@ -0,0 +1,64 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::{MEMSIZ, Reg}; +use crate::luma::app::App; + +impl App { + pub fn emu(&mut self) { + eprintln!("starting emulation"); + + // Initialise registers: + let mut reg = Reg { + r0: 0x00000000, + r1: 0x00000000, + r2: 0x00000000, + r3: 0x00000000, + r4: 0x00000000, + r5: 0x00000000, + r6: 0x00000000, + r7: 0x00000000, + r8: 0x00000000, + r9: 0x00000000, + r10: 0x00000000, + r11: 0x00000000, + r12: 0x00000000, + sp: 0x00000000, + lr: 0x00000000, + pc: 0x08000008, + cpsr: 0b00000000000000000000000000001111, + }; + + //let mem = self.mem; // For convenience. + + eprintln!("starting at 0x{:08X}",reg.pc - 0x8); + + loop { + // Check the current address: + if reg.pc >= MEMSIZ as u32 { + self.end(0x1, Some(format!("out-of-bounds address {:X}",reg.pc).as_str())); + } + + // Decode opcode: + let opc = unsafe { *(self.mem.add((reg.pc - 0x8) as usize) as *mut u32) }; + + // Currently, we only support the bal.w instruction. + if opc & 0b11111111000000000000000000000000 == 0b11101010000000000000000000000000 { + let off: u32 = opc & 0b00000000111111111111111111111111; + let abs: u32 = !(opc - 0x1) & 0b00000000111111111111111111111111; + + reg.pc = match (off & 0b00000000100000000000000000000000) != 0x0 { // If negative... + false => reg.pc + off * 0x4 + 0x8, + true => reg.pc - abs * 0x4 + 0x8, + }; + eprintln!("branch {off:X} => {:X}",reg.pc); + + continue; + } else { + self.trp(®, opc); + } + + // Continue: + reg.pc += 0x4; + } + } +} diff --git a/src/luma/app/end.rs b/src/luma/app/end.rs new file mode 100644 index 0000000..db2c842 --- /dev/null +++ b/src/luma/app/end.rs @@ -0,0 +1,21 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::MEMSIZ; +use crate::luma::app::App; + +use std::alloc::{dealloc, Layout}; +use std::process::exit; + +impl App { + pub fn end(&mut self, cod: u8, msg: Option<&str>) { + if cod != 0x0 { + eprintln!("error: {}", msg.unwrap()); + } + + eprintln!("ending"); + + unsafe { dealloc(self.mem, Layout::new::<[u32; MEMSIZ/0x20usize]>()) }; + + exit(cod as i32); + } +} diff --git a/src/luma/app/ini.rs b/src/luma/app/ini.rs new file mode 100644 index 0000000..f4ee5e7 --- /dev/null +++ b/src/luma/app/ini.rs @@ -0,0 +1,16 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::MEMSIZ; +use crate::luma::app::App; + +use std::alloc::{alloc_zeroed, Layout}; + +impl App { + pub fn ini(&mut self) { + eprintln!("initialising"); + + self.mem = unsafe { alloc_zeroed(Layout::new::<[u32; MEMSIZ]>()) }; + + eprintln!("allocated memory buffer at 0x{:0X}", self.mem as usize); + } +} diff --git a/src/luma/app/new.rs b/src/luma/app/new.rs new file mode 100644 index 0000000..1b30f3e --- /dev/null +++ b/src/luma/app/new.rs @@ -0,0 +1,17 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::app::App; + +use std::ptr::null; + +impl App { + pub fn new() -> App { + let app = App { + btl: "bootloader.bin".to_string(), + img: "image.agb".to_string(), + mem: null::<u8>() as *mut u8, + }; + + return app; + } +} diff --git a/src/luma/app/prspar.rs b/src/luma/app/prspar.rs new file mode 100644 index 0000000..2353787 --- /dev/null +++ b/src/luma/app/prspar.rs @@ -0,0 +1,26 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::app::App; + +use std::env::args; + +impl App { + pub fn prspar(&mut self) { + eprintln!("parsing parameters"); + + let arg: Vec<String> = args().collect(); + let num = arg.len(); + + if num >= 0x2 { + self.img = arg[0x1].clone(); + } + + if num >= 0x3 { + self.btl = arg[0x2].clone(); + } + + if num > 0x3 { + self.end(0x1,Some(format!("invalid number of parameters ({num})").as_str())); + } + } +} diff --git a/src/luma/app/run.rs b/src/luma/app/run.rs new file mode 100644 index 0000000..3abbc0a --- /dev/null +++ b/src/luma/app/run.rs @@ -0,0 +1,44 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::{BTLSIZ, IMGSIZ, VER}; +use crate::luma::app::App; + +use std::fs::File; +use std::io::Read; +use std::slice; + +impl App { + pub fn run(&mut self) { + eprintln!("luma {VER}"); + + self.prspar(); + + self.ini(); + + { + eprintln!("loading booatloader \"{}\"",self.btl); + + // Open bootloader: + let mut btl = File::open(self.btl.clone()).expect("unable to open bootloader"); + + // Read bootloader: + let slc = unsafe { slice::from_raw_parts_mut(self.mem.offset(0x00000000), BTLSIZ) }; + btl.read(slc).expect("unable to read bootloader"); + } + + { + eprintln!("loading image \"{}\"",self.img); + + // Open image: + let mut img = File::open(self.img.clone()).expect("unable to open image"); + + // Read image: + let slc = unsafe { slice::from_raw_parts_mut(self.mem.offset(0x08000000), IMGSIZ) }; + img.read(slc).expect("unable to read image"); + } + + self.emu(); + + self.end(0x0,None); + } +} diff --git a/src/luma/app/trp.rs b/src/luma/app/trp.rs new file mode 100644 index 0000000..7ec4cec --- /dev/null +++ b/src/luma/app/trp.rs @@ -0,0 +1,29 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::Reg; +use crate::luma::app::App; + +impl App { + pub fn trp(&mut self, reg: &Reg, opc: u32) { + eprintln!("trap - register dump:"); + eprintln!("\tr0: {:08X}", reg.r0); + eprintln!("\tr1: {:08X}", reg.r1); + eprintln!("\tr2: {:08X}", reg.r2); + eprintln!("\tr3: {:08X}", reg.r3); + eprintln!("\tr4: {:08X}", reg.r4); + eprintln!("\tr5: {:08X}", reg.r5); + eprintln!("\tr6: {:08X}", reg.r6); + eprintln!("\tr7: {:08X}", reg.r7); + eprintln!("\tr8: {:08X}", reg.r8); + eprintln!("\tr9: {:08X}", reg.r9); + eprintln!("\tr10: {:08X}", reg.r10); + eprintln!("\tr11: {:08X}", reg.r11); + eprintln!("\tr12: {:08X}", reg.r12); + eprintln!("\tsp: {:08X}", reg.sp); + eprintln!("\tlr: {:08X}", reg.lr); + eprintln!("\tpc: {:08X}", reg.pc); + eprintln!("\tcpsr: {:032b}", reg.cpsr); + + self.end(0x1, Some(format!("invalid opcode 0x{opc:08X} at 0x{:08X}",reg.pc-0x8).as_str())); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..aaa0e2b --- /dev/null +++ b/src/main.rs @@ -0,0 +1,10 @@ +// Copyright 2021-2023 Gabriel Jensen. + +mod luma; + +use crate::luma::app::App; + +fn main() { + let mut app = App::new(); + app.run(); +} |