mirror of
https://github.com/kittywitch/katgba.git
synced 2025-12-22 08:19:15 -08:00
feat: mwee
This commit is contained in:
parent
cd75ebcf4f
commit
ff59f63baf
3 changed files with 113 additions and 82 deletions
14
flake.nix
14
flake.nix
|
|
@ -30,10 +30,15 @@
|
||||||
in flake-utils.lib.eachDefaultSystem (system: let
|
in flake-utils.lib.eachDefaultSystem (system: let
|
||||||
pkgs = import nixpkgs {
|
pkgs = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
overlays = [ (import rust-overlay) ];
|
overlays = [
|
||||||
|
(import rust-overlay)
|
||||||
|
];
|
||||||
};
|
};
|
||||||
pkgsCross = import nixpkgs {
|
pkgsCross = import nixpkgs {
|
||||||
inherit system;
|
inherit system;
|
||||||
|
overlays = [
|
||||||
|
(import rust-overlay)
|
||||||
|
];
|
||||||
config = {
|
config = {
|
||||||
allowUnsupportedSystem = true;
|
allowUnsupportedSystem = true;
|
||||||
#replaceStdenv = ({ pkgs }: pkgs.clangStdenvNoLibs );
|
#replaceStdenv = ({ pkgs }: pkgs.clangStdenvNoLibs );
|
||||||
|
|
@ -47,24 +52,25 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
rustToolchainFor =
|
rustToolchainFor =
|
||||||
p:
|
p:
|
||||||
p.rust-bin.selectLatestNightlyWith (
|
p.rust-bin.selectLatestNightlyWith (
|
||||||
toolchain:
|
toolchain:
|
||||||
toolchain.minimal.override {
|
toolchain.minimal.override {
|
||||||
extensions = [ "rust-src" ];
|
extensions = [ "rust-analyzer" "rust-src" "clippy" "rustfmt" ];
|
||||||
targets = [ ];
|
targets = [ ];
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
rustToolchain = rustToolchainFor pkgs;
|
rustToolchain = rustToolchainFor pkgs;
|
||||||
|
|
||||||
|
rustToolchainConfig = builtins.fromTOML (builtins.readFile ./rust-toolchain.toml );
|
||||||
|
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchainFor;
|
craneLib = (crane.mkLib pkgs).overrideToolchain rustToolchainFor;
|
||||||
katgba-emu = pkgs.callPackage ./katgba-emu.nix { inherit katgba; };
|
katgba-emu = pkgs.callPackage ./katgba-emu.nix { inherit katgba; };
|
||||||
katgba = pkgs.callPackage ./package.nix { inherit craneLib rustToolchain rustTriple; };
|
katgba = pkgs.callPackage ./package.nix { inherit craneLib rustToolchain rustTriple; };
|
||||||
in {
|
in {
|
||||||
devShells = let
|
devShells = let
|
||||||
katgba-emu = import ./shell.nix { inherit self pkgs; };
|
katgba-emu = import ./shell.nix { inherit self pkgs rustToolchain; };
|
||||||
in {
|
in {
|
||||||
default = katgba-emu;
|
default = katgba-emu;
|
||||||
inherit katgba-emu;
|
inherit katgba-emu;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
{pkgs, self}: let
|
{pkgs, self, rustToolchain}: let
|
||||||
inherit (pkgs) lib mkShell toilet;
|
inherit (pkgs) lib mkShell toilet;
|
||||||
inherit (lib.meta) getExe;
|
inherit (lib.meta) getExe;
|
||||||
in mkShell {
|
in mkShell {
|
||||||
|
|
@ -7,5 +7,6 @@ in mkShell {
|
||||||
'';
|
'';
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [
|
||||||
self.packages.${pkgs.system}.katgba-emu
|
self.packages.${pkgs.system}.katgba-emu
|
||||||
|
rustToolchain
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
172
src/main.rs
172
src/main.rs
|
|
@ -1,101 +1,125 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
use core::fmt::Write;
|
use core::{error::Error, num::{NonZero, NonZeroI32}, ptr};
|
||||||
|
|
||||||
use gba::prelude::*;
|
use gba::prelude::*;
|
||||||
|
|
||||||
|
const SCREEN_WIDTH: u16 = 240;
|
||||||
|
const SCREEN_HEIGHT: u16 = 160;
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
|
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Fatal) {
|
|
||||||
writeln!(logger, "{info}").ok();
|
|
||||||
}
|
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[derive(Copy,Clone,PartialEq, Eq)]
|
||||||
const FOO: Align4<[u8; 14]> = include_aligned_bytes!("foo.txt");
|
struct Position(u16, u16);
|
||||||
|
|
||||||
#[unsafe(link_section = ".ewram")]
|
#[derive(Copy,Clone,PartialEq, Eq)]
|
||||||
static FRAME_KEYS: GbaCell<KeyInput> = GbaCell::new(KeyInput::new());
|
struct Dimensions(u16, u16);
|
||||||
|
|
||||||
#[unsafe(link_section = ".iwram")]
|
#[derive(Copy,Clone,PartialEq,Eq)]
|
||||||
extern "C" fn irq_handler(_: IrqBits) {
|
struct Render {
|
||||||
// We'll read the keys during vblank and store it for later.
|
position: Position,
|
||||||
FRAME_KEYS.write(KEYINPUT.read());
|
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<Player>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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)]
|
#[unsafe(no_mangle)]
|
||||||
extern "C" fn main() -> ! {
|
fn main() -> ! {
|
||||||
RUST_IRQ_HANDLER.write(Some(irq_handler));
|
DISPCNT.write(
|
||||||
|
DisplayControl::new().with_video_mode(VideoMode::_3).with_show_bg2(true),
|
||||||
|
);
|
||||||
|
|
||||||
|
RUST_IRQ_HANDLER.write(Some(draw_sprites));
|
||||||
DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true));
|
DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true));
|
||||||
IE.write(IrqBits::VBLANK);
|
IE.write(IrqBits::VBLANK);
|
||||||
IME.write(true);
|
IME.write(true);
|
||||||
|
|
||||||
if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Debug) {
|
unsafe { ENGINE.start(); };
|
||||||
writeln!(logger, "hello!").ok();
|
|
||||||
|
|
||||||
let fx_u: Fixed<u32, 8> =
|
|
||||||
Fixed::<u32, 8>::wrapping_from(7) + Fixed::<u32, 8>::from_bits(12);
|
|
||||||
writeln!(logger, "fixed unsigned: {fx_u:?}").ok();
|
|
||||||
|
|
||||||
let fx_i1: Fixed<i32, 8> =
|
|
||||||
Fixed::<i32, 8>::wrapping_from(8) + Fixed::<i32, 8>::from_bits(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_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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// 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 {
|
loop {
|
||||||
|
unsafe { ENGINE.update(); };
|
||||||
VBlankIntrWait();
|
VBlankIntrWait();
|
||||||
// show current frame
|
}
|
||||||
BACKDROP_COLOR.write(backdrop_color);
|
}
|
||||||
BG0HOFS.write(x_off as u16);
|
|
||||||
BG0VOFS.write(y_off as u16);
|
|
||||||
|
|
||||||
// prep next frame
|
#[unsafe(link_section = ".iwram.draw_sprites")]
|
||||||
let k = FRAME_KEYS.read();
|
extern "C" fn draw_sprites(_bits: IrqBits) {
|
||||||
backdrop_color = Color(k.to_u16());
|
video3_clear_to(Color::BLACK);
|
||||||
if k.up() {
|
|
||||||
y_off = y_off.wrapping_add(1);
|
unsafe { ENGINE.draw(); };
|
||||||
}
|
}
|
||||||
if k.down() {
|
|
||||||
y_off = y_off.wrapping_sub(1);
|
|
||||||
}
|
#[unsafe(link_section = ".iwram.draw_rect")]
|
||||||
if k.left() {
|
fn draw_rect(x: u16, y: u16, width: u16, height: u16, color: Color) {
|
||||||
x_off = x_off.wrapping_add(1);
|
for i in 0..width {
|
||||||
}
|
for j in 0..height {
|
||||||
if k.right() {
|
VIDEO3_VRAM.index((x + i) as usize, (y + j) as usize).write(color);
|
||||||
x_off = x_off.wrapping_sub(1);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue