diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/luma.rs | 16 | ||||
-rw-r--r-- | src/luma/application.rs | 24 | ||||
-rw-r--r-- | src/luma/application/decode.rs | 11 | ||||
-rw-r--r-- | src/luma/application/initialise.rs | 22 | ||||
-rw-r--r-- | src/luma/application/load.rs | 8 | ||||
-rw-r--r-- | src/luma/application/parse_parameters.rs | 26 | ||||
-rw-r--r-- | src/luma/application/read.rs | 4 | ||||
-rw-r--r-- | src/luma/application/run.rs | 12 | ||||
-rw-r--r-- | src/luma/application/trap.rs | 6 | ||||
-rw-r--r-- | src/luma/configuration.rs | 14 | ||||
-rw-r--r-- | src/luma/configuration/create.rs | 28 | ||||
-rw-r--r-- | src/luma/configuration/load.rs | 80 | ||||
-rw-r--r-- | src/luma/configuration/new.rs | 18 | ||||
-rw-r--r-- | src/luma/configuration/overwrite.rs | 20 | ||||
-rw-r--r-- | src/luma/configuration/path.rs | 14 | ||||
-rw-r--r-- | src/main.rs | 5 |
16 files changed, 237 insertions, 71 deletions
diff --git a/src/luma.rs b/src/luma.rs index af45480..4be467a 100644 --- a/src/luma.rs +++ b/src/luma.rs @@ -1,6 +1,7 @@ // Copyright 2021-2023 Gabriel Jensen. pub mod application; +pub mod configuration; pub struct VersionType<T> { major: T, @@ -9,10 +10,21 @@ pub struct VersionType<T> { pub const VERSION: VersionType::<u32> = VersionType::<u32> { major: 0x0, - minor: 0x21, + minor: 0x22, }; +pub enum TrapKind { + BadAlignment, + InvalidOpcode, + OutOfBounds, +} + +pub const CONFIGURATION_VERSION: u32 = 0x0; + pub const MEMORY_SIZE: usize = 0x0E010000; pub const BOOTLOADER_SIZE: usize = 0x00004000; -pub const IMAGE_SIZE: usize = 0x02000000; +pub const IMAGE_SIZE: usize = 0x02000000; + +pub const SCREEN_WIDTH: u8 = 0xF0; +pub const SCREEN_HEIGHT: u8 = 0xA0; diff --git a/src/luma/application.rs b/src/luma/application.rs index 63f7d92..efb4beb 100644 --- a/src/luma/application.rs +++ b/src/luma/application.rs @@ -1,5 +1,7 @@ // Copyright 2021-2023 Gabriel Jensen. +use crate::luma::configuration::Configuration; + extern crate sdl2; use sdl2::{Sdl, VideoSubsystem}; @@ -13,26 +15,18 @@ pub mod end; pub mod image; pub mod initialise; pub mod load; -pub mod parse_parameters; pub mod read; pub mod run; pub mod trap; -pub enum TrapKind { - BadAlignment, - InvalidOpcode, - OutOfBounds, -} - pub struct Application { - bootloader: String, - image: String, - sdl: Sdl, - sdl_video: VideoSubsystem, - window: Window, - memory: *mut u8, - registers: [u32; 0x10], - psr: u32, + configuration: Configuration, + sdl: Sdl, + sdl_video: VideoSubsystem, + window: Window, + memory: *mut u8, + registers: [u32; 0x10], + psr: u32, } pub static mut GOT_SIGNAL: AtomicBool = AtomicBool::new(false); diff --git a/src/luma/application/decode.rs b/src/luma/application/decode.rs index feca794..2c18ab1 100644 --- a/src/luma/application/decode.rs +++ b/src/luma/application/decode.rs @@ -1,6 +1,7 @@ // Copyright 2021-2023 Gabriel Jensen. -use crate::luma::application::{Application, TrapKind}; +use crate::luma::application::Application; +use crate::luma::TrapKind; impl Application { pub fn decode(&mut self, opcode: u32) { @@ -20,7 +21,7 @@ impl Application { 0b11000000000000000000000000000 => self.psr & 0b01000000000000000000000000000000 == 0x00 && self.psr & 0b00010000000000000000000000000000 >> 0x1C == self.psr & 0b10000000000000000000000000000000 >> 0x1F, 0b11010000000000000000000000000 => self.psr & 0b01000000000000000000000000000000 != 0x00 || self.psr & 0b00010000000000000000000000000000 >> 0x1C != self.psr & 0b10000000000000000000000000000000 >> 0x1F, 0b11100000000000000000000000000 => true, - _ => { self.trap(TrapKind::InvalidOpcode, Some(self.registers[0xF] - 0x8), Some(opcode), None); unreachable!(); }, + _ => { self.trap(TrapKind::InvalidOpcode, Some(self.registers[0xF] - 0x8), Some(opcode), None); false }, }; if !condition { return }; @@ -28,7 +29,10 @@ impl Application { let off = opcode & 0b00000000111111111111111111111111; // Offset from pc. let inv = !(opcode - 0x1) & 0b00000000111111111111111111111111; // Inverted offset. - if opcode & 0b00000001000000000000000000000000 != 0x0 { self.registers[0xE] = self.registers[0xF] - 0x4; } + if opcode & 0b00000001000000000000000000000000 != 0x0 { + self.registers[0xE] = self.registers[0xF] - 0x4; + eprintln!("link: lr => {}", self.registers[0xE]); + } self.registers[0xF] = match (off & 0b00000000100000000000000000000000) != 0x0 { // If negative... false => self.registers[0xF] + off * 0x4 + 0x8, @@ -40,6 +44,5 @@ impl Application { } self.trap(TrapKind::InvalidOpcode, Some(self.registers[0xF] - 0x8), Some(opcode), None); - unreachable!(); } } diff --git a/src/luma/application/initialise.rs b/src/luma/application/initialise.rs index e9bf0ef..67b0133 100644 --- a/src/luma/application/initialise.rs +++ b/src/luma/application/initialise.rs @@ -1,7 +1,8 @@ // Copyright 2021-2023 Gabriel Jensen. +use crate::luma::{MEMORY_SIZE, SCREEN_HEIGHT, SCREEN_WIDTH}; use crate::luma::application::{Application, GOT_SIGNAL}; -use crate::luma::MEMORY_SIZE; +use crate::luma::configuration::Configuration; extern crate libc; extern crate sdl2; @@ -20,7 +21,7 @@ fn signal_handler(sig: c_int) { } impl Application { - pub fn initialise() -> Application { + pub fn initialise(configuration: &Configuration) -> Application { eprintln!("initialising"); unsafe { @@ -31,7 +32,7 @@ impl Application { let sdl = sdl2::init().expect("unable to initialise sdl2"); let sdl_video = sdl.video().expect("unable to initialise sdl2"); - let window = sdl_video.window("luma", 0xF0, 0xA0).position_centered().build().unwrap(); + let window = sdl_video.window("luma", SCREEN_WIDTH as u32 * configuration.scale, SCREEN_HEIGHT as u32 * configuration.scale).position_centered().build().unwrap(); let memory = unsafe { alloc_zeroed(Layout::new::<[u32; MEMORY_SIZE / size_of::<u32>()]>()) }; if memory.is_null() { panic!("unable to allocate memory buffer") } @@ -39,13 +40,12 @@ impl Application { eprintln!("allocated memory buffer at 0x{:0X}", memory as usize); return Application { - bootloader: "bootloader.bin".to_string(), - image: "image.agb".to_string(), - sdl: sdl, - sdl_video: sdl_video, - window: window, - memory: memory, - registers: [ + configuration: configuration.clone(), + sdl: sdl, + sdl_video: sdl_video, + window: window, + memory: memory, + registers: [ 0x00000000, 0x00000000, 0x00000000, @@ -63,7 +63,7 @@ impl Application { 0x00000000, 0x08000008, ], - psr: 0b00000000000000000000000000001111, + psr: 0b00000000000000000000000000001111, }; } } diff --git a/src/luma/application/load.rs b/src/luma/application/load.rs index 58491d7..bc56922 100644 --- a/src/luma/application/load.rs +++ b/src/luma/application/load.rs @@ -7,18 +7,18 @@ use std::io::Read; impl Application { pub fn load(&mut self) { - eprintln!("loading booatloader \"{}\"", self.bootloader); + eprintln!("loading booatloader \"{}\"", self.configuration.bootloader); // Open bootloader: - let mut bootloader = File::open(self.bootloader.clone()).expect("unable to open bootloader"); + let mut bootloader = File::open(self.configuration.bootloader.clone()).expect("unable to open bootloader"); // Read bootloader: bootloader.read(self.bootloader()).expect("unable to read bootloader"); - eprintln!("loading image \"{}\"", self.image); + eprintln!("loading image \"{}\"", self.configuration.image); // Open image: - let mut image = File::open(self.image.clone()).expect("unable to open image"); + let mut image = File::open(self.configuration.image.clone()).expect("unable to open image"); // Read image: image.read(self.image()).expect("unable to read image"); diff --git a/src/luma/application/parse_parameters.rs b/src/luma/application/parse_parameters.rs deleted file mode 100644 index 46e619d..0000000 --- a/src/luma/application/parse_parameters.rs +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2021-2023 Gabriel Jensen. - -use crate::luma::application::Application; - -use std::env::args; - -impl Application { - pub fn parse_parameters(&mut self) { - eprintln!("parsing parameters"); - - let parameters: Vec<String> = args().collect(); - let number = parameters.len(); - - if number >= 0x2 { - self.image = parameters[0x1].clone(); - } - - if number >= 0x3 { - self.bootloader = parameters[0x2].clone(); - } - - if number > 0x3 { - self.end(0x1, Some(format!("invalid number of parameters ({number})").as_str())); - } - } -} diff --git a/src/luma/application/read.rs b/src/luma/application/read.rs index 40604a9..ac1b4aa 100644 --- a/src/luma/application/read.rs +++ b/src/luma/application/read.rs @@ -1,7 +1,7 @@ // Copyright 2021-2023 Gabriel Jensen. -use crate::luma::application::{Application, TrapKind}; -use crate::luma::MEMORY_SIZE; +use crate::luma::application::Application; +use crate::luma::{MEMORY_SIZE, TrapKind}; impl Application { #[allow(dead_code)] diff --git a/src/luma/application/run.rs b/src/luma/application/run.rs index a0a3f83..59f2144 100644 --- a/src/luma/application/run.rs +++ b/src/luma/application/run.rs @@ -1,16 +1,20 @@ // Copyright 2021-2023 Gabriel Jensen. -use crate::luma::application::{Application, GOT_SIGNAL}; use crate::luma::VERSION; +use crate::luma::application::{Application, GOT_SIGNAL}; use sdl2::event::Event; use std::sync::atomic::Ordering; +use std::thread::sleep; +use std::time::Duration; impl Application { pub fn run(&mut self) { + eprintln!(); eprintln!("luma {}.{}", VERSION.major, VERSION.minor); + eprintln!("Copyright 2021-2023 Gabriel Jensen."); + eprintln!(); - self.parse_parameters(); self.load(); let mut event_pump = self.sdl.event_pump().expect("unable to get event pump"); @@ -24,6 +28,7 @@ impl Application { break; } + // Iterate over events: for event in event_pump.poll_iter() { match event { Event::Quit {..} => break 'main_loop, @@ -37,6 +42,9 @@ impl Application { // Continue: self.registers[0xF] += 0x4; + eprintln!("continue: pc => {:08X}", self.registers[0xF]); + + sleep(Duration::from_secs(0x1)); } } } diff --git a/src/luma/application/trap.rs b/src/luma/application/trap.rs index 7f484ba..7b7adbf 100644 --- a/src/luma/application/trap.rs +++ b/src/luma/application/trap.rs @@ -1,7 +1,7 @@ // Copyright 2021-2023 Gabriel Jensen. -use crate::luma::application::{Application, TrapKind}; -use crate::luma::MEMORY_SIZE; +use crate::luma::{MEMORY_SIZE, TrapKind}; +use crate::luma::application::Application; impl Application { pub fn trap(&mut self, kind: TrapKind, address: Option<u32>, opcode: Option<u32>, alignment: Option<u32>) { @@ -30,7 +30,5 @@ impl Application { eprintln!("\tlr: {:08X}", self.registers[0xE]); eprintln!("\tpc: {:08X}", self.registers[0xF]); eprintln!("\tcpsr: {:032b}", self.psr); - - panic!("{message}"); } } diff --git a/src/luma/configuration.rs b/src/luma/configuration.rs new file mode 100644 index 0000000..045e897 --- /dev/null +++ b/src/luma/configuration.rs @@ -0,0 +1,14 @@ +// Copyright 2021-2023 Gabriel Jensen. + +pub mod create; +pub mod load; +pub mod new; +pub mod overwrite; +pub mod path; + +#[derive(Clone)] +pub struct Configuration { + pub bootloader: String, + pub image: String, + pub scale: u32, +} diff --git a/src/luma/configuration/create.rs b/src/luma/configuration/create.rs new file mode 100644 index 0000000..b5f2312 --- /dev/null +++ b/src/luma/configuration/create.rs @@ -0,0 +1,28 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::CONFIGURATION_VERSION; +use crate::luma::configuration::Configuration; + +use std::fs::write; + +impl Configuration { + pub(super) fn create(&mut self) { + let configuration_path = Configuration::path(); + + eprintln!("creating configuration at {configuration_path}"); + + let default_configuration = format!( + "[luma]\n\ + version = {CONFIGURATION_VERSION}\n\ + \n\ + [device]\n\ + #bootloader = \n\ + #image = \n\ + \n\ + [video]\n\ + scale = 1\n" + ); + + write(configuration_path, default_configuration).unwrap(); + } +} diff --git a/src/luma/configuration/load.rs b/src/luma/configuration/load.rs new file mode 100644 index 0000000..a3fe455 --- /dev/null +++ b/src/luma/configuration/load.rs @@ -0,0 +1,80 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::CONFIGURATION_VERSION; +use crate::luma::configuration::Configuration; + +use configparser::ini::Ini; +use std::env::var; + +impl Configuration { + pub(super) fn load(&mut self) { + let configuration_path = Configuration::path(); + + eprintln!("loading configuration \"{configuration_path}\""); + + let mut configuration = Ini::new(); + + match configuration.load(configuration_path) { + Ok( _) => {}, + Err(_) => { + eprintln!("unable to read configuration"); + + return self.create(); + }, + } + + let get_path = |configuration: &mut Ini, section: &str, entry: &str| -> Option<String> { + match configuration.get(section, entry) { + Some(path) => { + if path.chars().nth(0x0).unwrap() != '/' { + let home_directory = match var("HOME") { + Ok( path) => path, + Err(_) => { eprintln!("unable to get home directory"); "".to_string() }, + }; + + return Some(home_directory + "/" + &path) + } + + return Some(path); + }, + None => None, + } + }; + + let get_unsigned = |configuration: &mut Ini, section: &str, entry: &str| -> Option<u64> { + match configuration.getuint(section, entry) { + Ok( optional) => optional, + Err(_) => panic!("invalid format of '{entry}' in configuration under '{section}"), + } + }; + + let version = get_unsigned(&mut configuration, "luma", "version").expect("'version' field not defined in configuration under 'luma'") as u32; + + if version < CONFIGURATION_VERSION { panic!("out-of-date configuration - please upgrade") }; + if version > CONFIGURATION_VERSION { panic!("future configuration - please downgrade") }; + + match get_path(&mut configuration, "device", "bootloader") { + Some(path) => { + self.bootloader = path; + }, + None => {}, + } + + match get_path(&mut configuration, "device", "image") { + Some(path) => { + self.image = path; + }, + None => {}, + } + + match get_unsigned(&mut configuration, "video", "scale") { + Some(value) => { + assert!(value >= 0x1); + assert!(value <= 0xFFFFFFFF); + + self.scale = value as u32; + }, + None => {}, + } + } +} diff --git a/src/luma/configuration/new.rs b/src/luma/configuration/new.rs new file mode 100644 index 0000000..5742dd2 --- /dev/null +++ b/src/luma/configuration/new.rs @@ -0,0 +1,18 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::configuration::Configuration; + +impl Configuration { + pub fn new() -> Configuration { + let mut configuration = Configuration { + bootloader: "bootloader.bin".to_string(), + image: "image.agb".to_string(), + scale: 0x1, + }; + + configuration.load(); + configuration.overwrite(); + + return configuration; + } +} diff --git a/src/luma/configuration/overwrite.rs b/src/luma/configuration/overwrite.rs new file mode 100644 index 0000000..ab55ff3 --- /dev/null +++ b/src/luma/configuration/overwrite.rs @@ -0,0 +1,20 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::configuration::Configuration; + +use std::env::args; + +impl Configuration { + pub(super) fn overwrite(&mut self) { + eprintln!("overwritting settings"); + + let parameters: Vec<String> = args().collect(); + let number = parameters.len(); + + if number >= 0x2 { self.image = parameters[0x1].clone() } + + if number >= 0x3 { self.bootloader = parameters[0x2].clone() } + + if number > 0x3 { panic!("invalid number of parameters ({number})") } + } +} diff --git a/src/luma/configuration/path.rs b/src/luma/configuration/path.rs new file mode 100644 index 0000000..0db3d98 --- /dev/null +++ b/src/luma/configuration/path.rs @@ -0,0 +1,14 @@ +// Copyright 2021-2023 Gabriel Jensen. + +use crate::luma::configuration::Configuration; + +use std::env::var; + +impl Configuration { + pub(super) fn path() -> String { + return match var("HOME") { + Ok( path) => path, + Err(_) => panic!("unable to get home directory"), + } + "/.luma.ini"; + } +} diff --git a/src/main.rs b/src/main.rs index 92e5dcc..4ad9cf9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,8 +3,11 @@ mod luma; use crate::luma::application::Application; +use crate::luma::configuration::Configuration; fn main() { - let mut application = Application::initialise(); + let configuration = Configuration::new(); + + let mut application = Application::initialise(&configuration); application.run(); } |