summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/luma.rs16
-rw-r--r--src/luma/application.rs24
-rw-r--r--src/luma/application/decode.rs11
-rw-r--r--src/luma/application/initialise.rs22
-rw-r--r--src/luma/application/load.rs8
-rw-r--r--src/luma/application/parse_parameters.rs26
-rw-r--r--src/luma/application/read.rs4
-rw-r--r--src/luma/application/run.rs12
-rw-r--r--src/luma/application/trap.rs6
-rw-r--r--src/luma/configuration.rs14
-rw-r--r--src/luma/configuration/create.rs28
-rw-r--r--src/luma/configuration/load.rs80
-rw-r--r--src/luma/configuration/new.rs18
-rw-r--r--src/luma/configuration/overwrite.rs20
-rw-r--r--src/luma/configuration/path.rs14
-rw-r--r--src/main.rs5
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();
}