diff --git a/flake.nix b/flake.nix index de50b4d..ba4b679 100644 --- a/flake.nix +++ b/flake.nix @@ -30,10 +30,15 @@ in flake-utils.lib.eachDefaultSystem (system: let pkgs = import nixpkgs { inherit system; - overlays = [ (import rust-overlay) ]; + overlays = [ + (import rust-overlay) + ]; }; pkgsCross = import nixpkgs { inherit system; + overlays = [ + (import rust-overlay) + ]; config = { allowUnsupportedSystem = true; #replaceStdenv = ({ pkgs }: pkgs.clangStdenvNoLibs ); @@ -47,24 +52,25 @@ }; }; }; - rustToolchainFor = p: p.rust-bin.selectLatestNightlyWith ( toolchain: toolchain.minimal.override { - extensions = [ "rust-src" ]; + extensions = [ "rust-analyzer" "rust-src" "clippy" "rustfmt" ]; targets = [ ]; } ); rustToolchain = rustToolchainFor pkgs; + rustToolchainConfig = builtins.fromTOML (builtins.readFile ./rust-toolchain.toml ); + craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchainFor; katgba-emu = pkgs.callPackage ./katgba-emu.nix { inherit katgba; }; katgba = pkgs.callPackage ./package.nix { inherit craneLib rustToolchain rustTriple; }; in { devShells = let - katgba-emu = import ./shell.nix { inherit self pkgs; }; + katgba-emu = import ./shell.nix { inherit self pkgs rustToolchain; }; in { default = katgba-emu; inherit katgba-emu; diff --git a/shell.nix b/shell.nix index f2117c1..f8e02a1 100644 --- a/shell.nix +++ b/shell.nix @@ -1,4 +1,4 @@ -{pkgs, self}: let +{pkgs, self, rustToolchain}: let inherit (pkgs) lib mkShell toilet; inherit (lib.meta) getExe; in mkShell { @@ -7,5 +7,6 @@ in mkShell { ''; nativeBuildInputs = [ self.packages.${pkgs.system}.katgba-emu + rustToolchain ]; } diff --git a/src/main.rs b/src/main.rs index 67fbd78..ff1d684 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,101 +1,125 @@ #![no_std] #![no_main] -use core::fmt::Write; +use core::{error::Error, num::{NonZero, NonZeroI32}, ptr}; + use gba::prelude::*; +const SCREEN_WIDTH: u16 = 240; +const SCREEN_HEIGHT: u16 = 160; + #[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 {} +fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} } -#[allow(dead_code)] -const FOO: Align4<[u8; 14]> = include_aligned_bytes!("foo.txt"); +#[derive(Copy,Clone,PartialEq, Eq)] +struct Position(u16, u16); -#[unsafe(link_section = ".ewram")] -static FRAME_KEYS: GbaCell = GbaCell::new(KeyInput::new()); +#[derive(Copy,Clone,PartialEq, Eq)] +struct Dimensions(u16, u16); -#[unsafe(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()); +#[derive(Copy,Clone,PartialEq,Eq)] +struct Render { + position: Position, + dimensions: Dimensions, + color: Color, } +impl Render { + fn draw(&self) { + draw_rect(self.position.0, self.position.1, self.dimensions.0, self.dimensions.1, self.color); + } +} + +#[derive(Copy,Clone,PartialEq,Eq)] +struct Player(Render); +impl Player { + fn spawn() -> Player { + Self(Render { + position: Position(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2), + dimensions: Dimensions(24, 24), + color: Color::WHITE, + }) + } + fn update(&mut self) { + + } + fn draw(&self) { + self.0.draw(); + } +} + +#[derive(Copy,Clone,PartialEq,Eq)] +enum Entity { + Player(Player), +} + +#[derive(Copy,Clone)] +struct Engine { + player: Option, +} + + + +static mut ENGINE: Engine = Engine { + player: None, +}; + + +impl Engine { + fn start(mut self) { + self.player = Some(Player::spawn()); + } + + fn update(mut self) { + if let Some(player) = &mut self.player { + player.update(); + } + } + + fn draw(self) { + if let Some(player) = self.player { + player.draw(); + video3_clear_to(Color::WHITE); + } + } +} + + #[unsafe(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); +fn main() -> ! { + DISPCNT.write( + DisplayControl::new().with_video_mode(VideoMode::_3).with_show_bg2(true), + ); - if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Debug) { - writeln!(logger, "hello!").ok(); + RUST_IRQ_HANDLER.write(Some(draw_sprites)); + DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true)); + IE.write(IrqBits::VBLANK); + IME.write(true); - let fx_u: Fixed = - Fixed::::wrapping_from(7) + Fixed::::from_bits(12); - writeln!(logger, "fixed unsigned: {fx_u:?}").ok(); + unsafe { ENGINE.start(); }; - let fx_i1: Fixed = - Fixed::::wrapping_from(8) + Fixed::::from_bits(15); - writeln!(logger, "fixed signed positive: {fx_i1:?}").ok(); - let fx_i2: Fixed = Fixed::::wrapping_from(0) - - Fixed::::wrapping_from(3) - - Fixed::::from_bits(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); - } + loop { + unsafe { ENGINE.update(); }; + VBlankIntrWait(); } - } +} - { - // 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)); - } +#[unsafe(link_section = ".iwram.draw_sprites")] +extern "C" fn draw_sprites(_bits: IrqBits) { + video3_clear_to(Color::BLACK); - 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); + unsafe { ENGINE.draw(); }; +} - // 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); + +#[unsafe(link_section = ".iwram.draw_rect")] +fn draw_rect(x: u16, y: u16, width: u16, height: u16, color: Color) { + for i in 0..width { + for j in 0..height { + VIDEO3_VRAM.index((x + i) as usize, (y + j) as usize).write(color); } } }