From 3bcd64f28cf6e73d8a47e251403f7dc7346ff049 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Wed, 31 Mar 2021 20:22:42 -0600 Subject: [PATCH] update to voladdress-0.4 (#120) * update to voladdress-0.4 (via git) * restore the imports rust-analyzer told me to break. --- Cargo.toml | 3 +- examples/irq.rs | 14 ++++---- examples/test_savegame.rs | 13 +++---- src/bios.rs | 5 ++- src/debug.rs | 11 ++---- src/debug/mgba.rs | 10 +++--- src/debug/nocash.rs | 7 ++-- src/{base => }/fixed_point.rs | 3 ++ src/io/background.rs | 28 ++++++++------- src/io/color_blend.rs | 8 +++-- src/io/display.rs | 10 +++--- src/io/dma.rs | 36 +++++++++++--------- src/io/irq.rs | 10 +++--- src/io/keypad.rs | 5 +-- src/io/sio.rs | 9 ++--- src/io/sound.rs | 64 +++++++++++++++++++++-------------- src/io/timers.rs | 20 ++++++----- src/io/window.rs | 18 ++++++---- src/lib.rs | 10 +++--- src/oam.rs | 7 ++-- src/palram.rs | 26 ++++++-------- src/save/eeprom.rs | 54 ++++++++++++++--------------- src/save/flash.rs | 13 ++++--- src/save/utils.rs | 8 ++--- src/sync.rs | 16 ++++++--- src/sync/statics.rs | 20 ++++++----- src/vram.rs | 21 ++++++------ src/vram/bitmap.rs | 50 ++++++++++++--------------- 28 files changed, 260 insertions(+), 239 deletions(-) rename src/{base => }/fixed_point.rs (98%) diff --git a/Cargo.toml b/Cargo.toml index f9a15e5..46f0845 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,7 @@ default = [] serial = ["embedded-hal", "nb"] [dependencies] -typenum = "1.10" -voladdress = "0.2" +voladdress = { version = "0.4.0-alpha.0", git = "https://github.com/rust-console/voladdress" } gba-proc-macro = "0.5" embedded-hal = { version = "0.2.4", optional = true } nb = { version = "1.0.0", optional = true } diff --git a/examples/irq.rs b/examples/irq.rs index 98a390b..2b77b0b 100644 --- a/examples/irq.rs +++ b/examples/irq.rs @@ -44,7 +44,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { irq::set_irq_handler(irq_handler); // Enable all interrupts that are set in the IE register. - IME.write(IrqEnableSetting::IRQ_YES); + unsafe { IME.write(IrqEnableSetting::IRQ_YES) }; // Request that VBlank, HBlank and VCount will generate IRQs. const DISPLAY_SETTINGS: DisplayStatusSetting = DisplayStatusSetting::new() @@ -78,7 +78,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { flags = flags.with_timer1(true); } - IE.write(flags); + unsafe { IE.write(flags) }; // Puts the CPU into low power mode until a VBlank IRQ is received. This // will yield considerably better power efficiency as opposed to spin @@ -119,29 +119,29 @@ fn vblank_handler() { // When using `interrupt_wait()` or `vblank_interrupt_wait()`, IRQ handlers must acknowledge // the IRQ on the BIOS Interrupt Flags register. - BIOS_IF.write(BIOS_IF.read().with_vblank(true)); + unsafe { BIOS_IF.write(BIOS_IF.read().with_vblank(true)) }; } fn hblank_handler() { write_pixel(GREEN); - BIOS_IF.write(BIOS_IF.read().with_hblank(true)); + unsafe { BIOS_IF.write(BIOS_IF.read().with_hblank(true)) }; } fn vcounter_handler() { write_pixel(RED); - BIOS_IF.write(BIOS_IF.read().with_vcounter(true)); + unsafe { BIOS_IF.write(BIOS_IF.read().with_vcounter(true)) }; } fn timer0_handler() { write_pixel(YELLOW); - BIOS_IF.write(BIOS_IF.read().with_timer0(true)); + unsafe { BIOS_IF.write(BIOS_IF.read().with_timer0(true)) }; } fn timer1_handler() { write_pixel(PINK); - BIOS_IF.write(BIOS_IF.read().with_timer1(true)); + unsafe { BIOS_IF.write(BIOS_IF.read().with_timer1(true)) }; } diff --git a/examples/test_savegame.rs b/examples/test_savegame.rs index 9a8513f..1ef4194 100644 --- a/examples/test_savegame.rs +++ b/examples/test_savegame.rs @@ -4,14 +4,14 @@ use core::cmp; use gba::{ - fatal, warn, + fatal, io::{ display::{DisplayControlSetting, DisplayMode, DISPCNT}, timers::{TimerControlSetting, TimerTickRate, TM0CNT_H, TM0CNT_L, TM1CNT_H, TM1CNT_L}, }, save::*, vram::bitmap::Mode3, - Color, + warn, Color, }; fn set_screen_color(r: u16, g: u16, b: u16) { @@ -34,7 +34,6 @@ fn set_screen_progress(cur: usize, max: usize) { fn panic(info: &core::panic::PanicInfo) -> ! { set_screen_color(31, 0, 0); fatal!("{}", info); - loop {} } #[derive(Clone)] @@ -90,7 +89,7 @@ fn do_test(seed: Rng, offset: usize, len: usize, block_size: usize) -> Result<() let mut buffer = [0; MAX_BLOCK_SIZE]; output!(" - Clearing media..."); - access.prepare_write(offset..offset+len)?; + access.prepare_write(offset..offset + len)?; output!(" - Writing media..."); let mut rng = seed.clone(); @@ -168,7 +167,9 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { output!( "[ Partial, offset = 0x{:06x}, len = {}, bs = {}]", - rand_offset, rand_length, block_size, + rand_offset, + rand_length, + block_size, ); check_status(do_test(Rng(i * 10000), rand_offset, rand_length, block_size)); set_screen_progress(3 + i as usize, 10); @@ -176,5 +177,5 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { // show a pattern so we know it worked set_screen_color(0, 31, 0); - loop { } + loop {} } diff --git a/src/bios.rs b/src/bios.rs index 326b9e4..3b4144a 100644 --- a/src/bios.rs +++ b/src/bios.rs @@ -10,7 +10,6 @@ #![cfg_attr(not(target_arch = "arm"), allow(unused_variables))] -use core::mem; use super::*; use io::irq::IrqFlags; @@ -184,8 +183,8 @@ pub fn interrupt_wait(ignore_current_flags: bool, target_flags: IrqFlags) { unsafe { asm!( "swi 0x04", - in("r0") mem::transmute::(ignore_current_flags), - in("r1") mem::transmute::(target_flags), + in("r0") ignore_current_flags as u8, + in("r1") target_flags.0, ); } } diff --git a/src/debug.rs b/src/debug.rs index 8e03309..fc6a48b 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -3,15 +3,8 @@ //! This is the underlying implementation behind the various print macros in //! the gba crate. It currently supports the latest versions of mGBA and NO$GBA. -use crate::{ - io::{ - dma::{DMAControlSetting, DMA0, DMA1, DMA2, DMA3}, - irq::{IrqEnableSetting, IME}, - }, - sync::{InitOnce, RawMutex, Static}, -}; +use crate::sync::{InitOnce, RawMutex, Static}; use core::fmt::{Arguments, Error}; -use voladdress::VolAddress; pub mod mgba; pub mod nocash; @@ -127,5 +120,5 @@ pub fn crash() -> ! { } #[cfg(not(all(target_vendor = "nintendo", target_env = "agb")))] - loop { } + loop {} } diff --git a/src/debug/mgba.rs b/src/debug/mgba.rs index ad381a5..dc42ff8 100644 --- a/src/debug/mgba.rs +++ b/src/debug/mgba.rs @@ -7,7 +7,7 @@ use super::{DebugInterface, DebugLevel}; use crate::sync::InitOnce; use core::fmt::{Arguments, Write}; -use voladdress::VolAddress; +use voladdress::*; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u16)] @@ -22,13 +22,13 @@ pub enum MGBADebugLevel { } // MGBADebug related addresses. -const ENABLE_ADDRESS: VolAddress = unsafe { VolAddress::new(0x4fff780) }; +const ENABLE_ADDRESS: VolAddress = unsafe { VolAddress::new(0x4fff780) }; const ENABLE_ADDRESS_INPUT: u16 = 0xC0DE; const ENABLE_ADDRESS_OUTPUT: u16 = 0x1DEA; -const OUTPUT_BASE: VolAddress = unsafe { VolAddress::new(0x4fff600) }; +const OUTPUT_BLOCK: VolBlock = unsafe { VolBlock::new(0x4fff600) }; -const SEND_ADDRESS: VolAddress = unsafe { VolAddress::new(0x4fff700) }; +const SEND_ADDRESS: VolAddress = unsafe { VolAddress::new(0x4fff700) }; const SEND_FLAG: u16 = 0x100; // Only enable MGBA debugging once. @@ -82,7 +82,7 @@ impl MGBADebug { impl core::fmt::Write for MGBADebug { fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { unsafe { - let mut current = OUTPUT_BASE.offset(self.bytes_written as isize); + let mut current = OUTPUT_BLOCK.index(self.bytes_written as usize); let mut str_iter = s.bytes(); while self.bytes_written < 255 { match str_iter.next() { diff --git a/src/debug/nocash.rs b/src/debug/nocash.rs index 42214a6..953dc64 100644 --- a/src/debug/nocash.rs +++ b/src/debug/nocash.rs @@ -9,11 +9,10 @@ use crate::{ sync::InitOnce, }; use core::fmt::{Arguments, Write}; -use typenum::consts::U16; -use voladdress::{VolAddress, VolBlock}; +use voladdress::*; -const CHAR_OUT: VolAddress = unsafe { VolAddress::new(0x04FFFA1C) }; -const SIGNATURE_ADDR: VolBlock = unsafe { VolBlock::new(0x04FFFA00) }; +const CHAR_OUT: VolAddress = unsafe { VolAddress::new(0x04FFFA1C) }; +const SIGNATURE_ADDR: VolBlock = unsafe { VolBlock::new(0x04FFFA00) }; const SIGNATURE: [u8; 7] = *b"no$gba "; static NO_CASH_DEBUGGING: InitOnce = InitOnce::new(); diff --git a/src/base/fixed_point.rs b/src/fixed_point.rs similarity index 98% rename from src/base/fixed_point.rs rename to src/fixed_point.rs index fbd9ef8..249ed91 100644 --- a/src/base/fixed_point.rs +++ b/src/fixed_point.rs @@ -1,4 +1,7 @@ #![allow(non_camel_case_types)] +// Note(Lokathor): NOT CURRENTLY USED. +// +// If we want this in the future we can convert it to const generics. //! Module for fixed point math types and operations. diff --git a/src/io/background.rs b/src/io/background.rs index 6b34f2a..7cd9f5e 100644 --- a/src/io/background.rs +++ b/src/io/background.rs @@ -3,13 +3,17 @@ use super::*; /// BG0 Control. Read/Write. Display Mode 0/1 only. -pub const BG0CNT: VolAddress = unsafe { VolAddress::new(0x400_0008) }; +pub const BG0CNT: VolAddress = + unsafe { VolAddress::new(0x400_0008) }; /// BG1 Control. Read/Write. Display Mode 0/1 only. -pub const BG1CNT: VolAddress = unsafe { VolAddress::new(0x400_000A) }; +pub const BG1CNT: VolAddress = + unsafe { VolAddress::new(0x400_000A) }; /// BG2 Control. Read/Write. Display Mode 0/1/2 only. -pub const BG2CNT: VolAddress = unsafe { VolAddress::new(0x400_000C) }; +pub const BG2CNT: VolAddress = + unsafe { VolAddress::new(0x400_000C) }; /// BG3 Control. Read/Write. Display Mode 0/2 only. -pub const BG3CNT: VolAddress = unsafe { VolAddress::new(0x400_000E) }; +pub const BG3CNT: VolAddress = + unsafe { VolAddress::new(0x400_000E) }; newtype! { /// Allows configuration of a background layer. @@ -66,24 +70,24 @@ pub enum BGSize { } /// BG0 X-Offset. Write only. Text mode only. 9 bits. -pub const BG0HOFS: VolAddress = unsafe { VolAddress::new(0x400_0010) }; +pub const BG0HOFS: VolAddress = unsafe { VolAddress::new(0x400_0010) }; /// BG0 Y-Offset. Write only. Text mode only. 9 bits. -pub const BG0VOFS: VolAddress = unsafe { VolAddress::new(0x400_0012) }; +pub const BG0VOFS: VolAddress = unsafe { VolAddress::new(0x400_0012) }; /// BG1 X-Offset. Write only. Text mode only. 9 bits. -pub const BG1HOFS: VolAddress = unsafe { VolAddress::new(0x400_0014) }; +pub const BG1HOFS: VolAddress = unsafe { VolAddress::new(0x400_0014) }; /// BG1 Y-Offset. Write only. Text mode only. 9 bits. -pub const BG1VOFS: VolAddress = unsafe { VolAddress::new(0x400_0016) }; +pub const BG1VOFS: VolAddress = unsafe { VolAddress::new(0x400_0016) }; /// BG2 X-Offset. Write only. Text mode only. 9 bits. -pub const BG2HOFS: VolAddress = unsafe { VolAddress::new(0x400_0018) }; +pub const BG2HOFS: VolAddress = unsafe { VolAddress::new(0x400_0018) }; /// BG2 Y-Offset. Write only. Text mode only. 9 bits. -pub const BG2VOFS: VolAddress = unsafe { VolAddress::new(0x400_001A) }; +pub const BG2VOFS: VolAddress = unsafe { VolAddress::new(0x400_001A) }; /// BG3 X-Offset. Write only. Text mode only. 9 bits. -pub const BG3HOFS: VolAddress = unsafe { VolAddress::new(0x400_001C) }; +pub const BG3HOFS: VolAddress = unsafe { VolAddress::new(0x400_001C) }; /// BG3 Y-Offset. Write only. Text mode only. 9 bits. -pub const BG3VOFS: VolAddress = unsafe { VolAddress::new(0x400_001E) }; +pub const BG3VOFS: VolAddress = unsafe { VolAddress::new(0x400_001E) }; // TODO: affine backgrounds // BG2X_L diff --git a/src/io/color_blend.rs b/src/io/color_blend.rs index 6eea535..bcabc84 100644 --- a/src/io/color_blend.rs +++ b/src/io/color_blend.rs @@ -3,7 +3,8 @@ use super::*; /// Color Special Effects Selection (R/W) -pub const BLDCNT: VolAddress = unsafe { VolAddress::new(0x400_0050) }; +pub const BLDCNT: VolAddress = + unsafe { VolAddress::new(0x400_0050) }; newtype! { /// TODO: docs @@ -43,7 +44,8 @@ newtype_enum! { } /// Alpha Blending Coefficients (R/W) (not W) -pub const BLDALPHA: VolAddress = unsafe { VolAddress::new(0x400_0052) }; +pub const BLDALPHA: VolAddress = + unsafe { VolAddress::new(0x400_0052) }; newtype! { /// TODO: docs @@ -59,7 +61,7 @@ impl AlphaBlendingSetting { } /// Brightness (Fade-In/Out) Coefficient (W) (not R/W) -pub const BLDY: VolAddress = unsafe { VolAddress::new(0x400_0054) }; +pub const BLDY: VolAddress = unsafe { VolAddress::new(0x400_0054) }; newtype! { /// TODO: docs diff --git a/src/io/display.rs b/src/io/display.rs index 553967c..bfdb546 100644 --- a/src/io/display.rs +++ b/src/io/display.rs @@ -5,7 +5,8 @@ use super::*; /// LCD Control. Read/Write. /// /// The "force vblank" bit is always set when your Rust code first executes. -pub const DISPCNT: VolAddress = unsafe { VolAddress::new(0x400_0000) }; +pub const DISPCNT: VolAddress = + unsafe { VolAddress::new(0x400_0000) }; newtype!( /// Setting for the display control register. @@ -96,7 +97,8 @@ pub fn display_control() -> DisplayControlSetting { } /// Display Status and IRQ Control. Read/Write. -pub const DISPSTAT: VolAddress = unsafe { VolAddress::new(0x400_0004) }; +pub const DISPSTAT: VolAddress = + unsafe { VolAddress::new(0x400_0004) }; newtype!( /// A newtype over display status and interrupt control values. @@ -122,13 +124,13 @@ impl DisplayStatusSetting { /// Gives the current scanline that the display controller is working on. If /// this is at or above the `VBLANK_SCANLINE` value then the display controller /// is in a "vertical blank" period. -pub const VCOUNT: ROVolAddress = unsafe { ROVolAddress::new(0x400_0006) }; +pub const VCOUNT: VolAddress = unsafe { VolAddress::new(0x400_0006) }; /// If the `VCOUNT` register reads equal to or above this then you're in vblank. pub const VBLANK_SCANLINE: u16 = 160; /// Global mosaic effect control. Write-only. -pub const MOSAIC: VolAddress = unsafe { VolAddress::new(0x400_004C) }; +pub const MOSAIC: VolAddress = unsafe { VolAddress::new(0x400_004C) }; newtype! { /// Allows control of the Mosaic effect. diff --git a/src/io/dma.rs b/src/io/dma.rs index 4507c07..ee59cf2 100644 --- a/src/io/dma.rs +++ b/src/io/dma.rs @@ -127,13 +127,14 @@ pub enum DMAStartTiming { pub struct DMA0; impl DMA0 { /// DMA 0 Source Address, read only. - const DMA0SAD: VolAddress<*const u32> = unsafe { VolAddress::new(0x400_00B0) }; + const DMA0SAD: VolAddress<*const u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00B0) }; /// DMA 0 Destination Address, read only. - const DMA0DAD: VolAddress<*mut u32> = unsafe { VolAddress::new(0x400_00B4) }; + const DMA0DAD: VolAddress<*mut u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00B4) }; /// DMA 0 Word Count, read only. - const DMA0CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00B8) }; + const DMA0CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00B8) }; /// DMA 0 Control, read/write. - const DMA0CNT_H: VolAddress = unsafe { VolAddress::new(0x400_00BA) }; + const DMA0CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_00BA) }; /// Assigns the source register. /// @@ -190,13 +191,14 @@ impl DMA0 { pub struct DMA1; impl DMA1 { /// DMA 1 Source Address, read only. - const DMA1SAD: VolAddress<*const u32> = unsafe { VolAddress::new(0x400_00BC) }; + const DMA1SAD: VolAddress<*const u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00BC) }; /// DMA 1 Destination Address, read only. - const DMA1DAD: VolAddress<*mut u32> = unsafe { VolAddress::new(0x400_00C0) }; + const DMA1DAD: VolAddress<*mut u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00C0) }; /// DMA 1 Word Count, read only. - const DMA1CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00C4) }; + const DMA1CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00C4) }; /// DMA 1 Control, read/write. - const DMA1CNT_H: VolAddress = unsafe { VolAddress::new(0x400_00C6) }; + const DMA1CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_00C6) }; /// Assigns the source register. /// @@ -253,13 +255,14 @@ impl DMA1 { pub struct DMA2; impl DMA2 { /// DMA 2 Source Address, read only. - const DMA2SAD: VolAddress<*const u32> = unsafe { VolAddress::new(0x400_00C8) }; + const DMA2SAD: VolAddress<*const u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00C8) }; /// DMA 2 Destination Address, read only. - const DMA2DAD: VolAddress<*mut u32> = unsafe { VolAddress::new(0x400_00CC) }; + const DMA2DAD: VolAddress<*mut u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00CC) }; /// DMA 2 Word Count, read only. - const DMA2CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00D0) }; + const DMA2CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00D0) }; /// DMA 2 Control, read/write. - const DMA2CNT_H: VolAddress = unsafe { VolAddress::new(0x400_00D2) }; + const DMA2CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_00D2) }; /// Assigns the source register. /// @@ -317,13 +320,14 @@ impl DMA2 { pub struct DMA3; impl DMA3 { /// DMA 3 Source Address, read only. - const DMA3SAD: VolAddress<*const u32> = unsafe { VolAddress::new(0x400_00D4) }; + const DMA3SAD: VolAddress<*const u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00D4) }; /// DMA 3 Destination Address, read only. - const DMA3DAD: VolAddress<*mut u32> = unsafe { VolAddress::new(0x400_00D8) }; + const DMA3DAD: VolAddress<*mut u32, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00D8) }; /// DMA 3 Word Count, read only. - const DMA3CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00DC) }; + const DMA3CNT_L: VolAddress = unsafe { VolAddress::new(0x400_00DC) }; /// DMA 3 Control, read/write. - const DMA3CNT_H: VolAddress = unsafe { VolAddress::new(0x400_00DE) }; + const DMA3CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_00DE) }; /// Assigns the source register. /// diff --git a/src/io/irq.rs b/src/io/irq.rs index f225629..56ae2e6 100644 --- a/src/io/irq.rs +++ b/src/io/irq.rs @@ -103,7 +103,7 @@ use super::*; newtype!( /// A newtype over all interrupt flags. IrqFlags, - u16 + pub(crate) u16 ); impl IrqFlags { @@ -130,7 +130,7 @@ impl IrqFlags { /// /// After setting up interrupt handlers, set the flags on this register type corresponding to the /// IRQs you want to handle. -pub const IE: VolAddress = unsafe { VolAddress::new(0x400_0200) }; +pub const IE: VolAddress = unsafe { VolAddress::new(0x400_0200) }; /// Interrupt Request Flags / IRQ Acknowledge. Read/Write. /// @@ -139,7 +139,7 @@ pub const IE: VolAddress = unsafe { VolAddress::new(0x400_0200) }; /// However, if the main interrupt handler in `rsrt0.S` is changed, then the /// handler must write a `1` bit to all bits that are enabled on this register /// when it is called. -pub const IF: VolAddress = unsafe { VolAddress::new(0x400_0202) }; +pub const IF: VolAddress = unsafe { VolAddress::new(0x400_0202) }; newtype! { /// Setting to control whether interrupts are enabled. @@ -161,7 +161,7 @@ impl IrqEnableSetting { } /// Interrupt Master Enable Register. Read/Write. -pub const IME: VolAddress = unsafe { VolAddress::new(0x400_0208) }; +pub const IME: VolAddress = unsafe { VolAddress::new(0x400_0208) }; /// BIOS Interrupt Flags. Read/Write. /// @@ -169,7 +169,7 @@ pub const IME: VolAddress = unsafe { VolAddress::new(0x400_020 /// [`vblank_interrupt_wait`](bios::vblank_interrupt_wait), the corresponding /// interrupt handler MUST set the flag of the interrupt it has handled on this /// register in addition to the usual interrupt acknowledgement. -pub const BIOS_IF: VolAddress = unsafe { VolAddress::new(0x0300_7FF8) }; +pub const BIOS_IF: VolAddress = unsafe { VolAddress::new(0x0300_7FF8) }; /// A function pointer for use as an interrupt handler. pub type IrqHandler = extern "C" fn(IrqFlags); diff --git a/src/io/keypad.rs b/src/io/keypad.rs index 5805e12..eaa90b3 100644 --- a/src/io/keypad.rs +++ b/src/io/keypad.rs @@ -8,7 +8,7 @@ use super::*; /// follow the "high-active" convention (hint: you probably do, it's far easier /// to work with) then call `read_key_input()` rather than reading this register /// directly. It will perform the necessary bit flip operation for you. -pub const KEYINPUT: ROVolAddress = unsafe { ROVolAddress::new(0x400_0130) }; +pub const KEYINPUT: VolAddress = unsafe { VolAddress::new(0x400_0130) }; /// A "tribool" value helps us interpret the arrow pad. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -88,7 +88,8 @@ pub fn read_key_input() -> KeyInput { /// Use this to configure when a keypad interrupt happens. /// /// See the `KeyInterruptSetting` type for more. -pub const KEYCNT: VolAddress = unsafe { VolAddress::new(0x400_0132) }; +pub const KEYCNT: VolAddress = + unsafe { VolAddress::new(0x400_0132) }; newtype! { /// Allows configuration of when a keypad interrupt fires. diff --git a/src/io/sio.rs b/src/io/sio.rs index 31d10ce..c6296e2 100644 --- a/src/io/sio.rs +++ b/src/io/sio.rs @@ -3,13 +3,14 @@ use super::*; /// Serial IO Control. Read/Write. -pub const SIOCNT: VolAddress = unsafe { VolAddress::new(0x400_0128) }; +pub const SIOCNT: VolAddress = + unsafe { VolAddress::new(0x400_0128) }; /// Serial IO Data. Read/Write. -pub const SIODATA8: VolAddress = unsafe { VolAddress::new(0x400_012A) }; +pub const SIODATA8: VolAddress = unsafe { VolAddress::new(0x400_012A) }; /// General IO Control. Read/Write. -pub const RCNT: VolAddress = unsafe { VolAddress::new(0x400_0134) }; +pub const RCNT: VolAddress = unsafe { VolAddress::new(0x400_0134) }; newtype!( /// Setting for the serial IO control register. @@ -122,7 +123,7 @@ newtype_enum! { JoyBus = 3, } -/// Empty stuct that implements embedded_hal traits. +/// Empty struct that implements embedded_hal traits. #[cfg(feature = "serial")] #[derive(Clone)] pub struct SioSerial; diff --git a/src/io/sound.rs b/src/io/sound.rs index dcb6736..163e8b1 100644 --- a/src/io/sound.rs +++ b/src/io/sound.rs @@ -5,7 +5,8 @@ use super::*; //TODO within these "read/write" registers only some bits are actually read/write! /// Sound Channel 1 Sweep Register (`NR10`). Read/Write. -pub const SOUND1CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0060) }; +pub const SOUND1CNT_L: VolAddress = + unsafe { VolAddress::new(0x400_0060) }; newtype! { /// TODO: docs @@ -22,7 +23,8 @@ impl SweepRegisterSetting { } /// Sound Channel 1 Duty/Length/Envelope (`NR11`, `NR12`). Read/Write. -pub const SOUND1CNT_H: VolAddress = unsafe { VolAddress::new(0x400_0062) }; +pub const SOUND1CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_0062) }; newtype! { /// TODO: docs @@ -41,7 +43,8 @@ impl DutyLenEnvelopeSetting { } /// Sound Channel 1 Frequency/Control (`NR13`, `NR14`). Read/Write. -pub const SOUND1CNT_X: VolAddress = unsafe { VolAddress::new(0x400_0064) }; +pub const SOUND1CNT_X: VolAddress = + unsafe { VolAddress::new(0x400_0064) }; newtype! { /// TODO: docs @@ -58,13 +61,15 @@ impl FrequencyControlSetting { } /// Sound Channel 2 Channel 2 Duty/Length/Envelope (`NR21`, `NR22`). Read/Write. -pub const SOUND2CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0068) }; +pub const SOUND2CNT_L: VolAddress = + unsafe { VolAddress::new(0x400_0068) }; /// Sound Channel 2 Frequency/Control (`NR23`, `NR24`). Read/Write. -pub const SOUND2CNT_H: VolAddress = unsafe { VolAddress::new(0x400_006C) }; +pub const SOUND2CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_006C) }; /// Sound Channel 3 Stop/Wave RAM select (`NR23`, `NR24`). Read/Write. -pub const SOUND3CNT_L: VolAddress = +pub const SOUND3CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0070) }; newtype! { @@ -82,7 +87,8 @@ impl StopWaveRAMSelectSetting { } /// Sound Channel 3 Length/Volume (`NR23`, `NR24`). Read/Write. -pub const SOUND3CNT_H: VolAddress = unsafe { VolAddress::new(0x400_0072) }; +pub const SOUND3CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_0072) }; newtype! { /// TODO: docs @@ -99,27 +105,29 @@ impl LengthVolumeSetting { } /// Sound Channel 3 Frequency/Control (`NR33`, `NR34`). Read/Write. -pub const SOUND3CNT_X: VolAddress = unsafe { VolAddress::new(0x400_0074) }; +pub const SOUND3CNT_X: VolAddress = + unsafe { VolAddress::new(0x400_0074) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM0_L: VolAddress = unsafe { VolAddress::new(0x400_0090) }; +pub const WAVE_RAM0_L: VolAddress = unsafe { VolAddress::new(0x400_0090) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM0_H: VolAddress = unsafe { VolAddress::new(0x400_0092) }; +pub const WAVE_RAM0_H: VolAddress = unsafe { VolAddress::new(0x400_0092) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM1_L: VolAddress = unsafe { VolAddress::new(0x400_0094) }; +pub const WAVE_RAM1_L: VolAddress = unsafe { VolAddress::new(0x400_0094) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM1_H: VolAddress = unsafe { VolAddress::new(0x400_0096) }; +pub const WAVE_RAM1_H: VolAddress = unsafe { VolAddress::new(0x400_0096) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM2_L: VolAddress = unsafe { VolAddress::new(0x400_0098) }; +pub const WAVE_RAM2_L: VolAddress = unsafe { VolAddress::new(0x400_0098) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM2_H: VolAddress = unsafe { VolAddress::new(0x400_009A) }; +pub const WAVE_RAM2_H: VolAddress = unsafe { VolAddress::new(0x400_009A) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM3_L: VolAddress = unsafe { VolAddress::new(0x400_009C) }; +pub const WAVE_RAM3_L: VolAddress = unsafe { VolAddress::new(0x400_009C) }; /// Channel 3 Wave Pattern RAM (W/R) -pub const WAVE_RAM3_H: VolAddress = unsafe { VolAddress::new(0x400_009E) }; +pub const WAVE_RAM3_H: VolAddress = unsafe { VolAddress::new(0x400_009E) }; /// Sound Channel 4 Length/Envelope (`NR41`, `NR42`). Read/Write. -pub const SOUND4CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0078) }; +pub const SOUND4CNT_L: VolAddress = + unsafe { VolAddress::new(0x400_0078) }; newtype! { /// TODO: docs @@ -137,7 +145,8 @@ impl LengthEnvelopeSetting { } /// Sound Channel 4 Frequency/Control (`NR43`, `NR44`). Read/Write. -pub const SOUND4CNT_H: VolAddress = unsafe { VolAddress::new(0x400_007C) }; +pub const SOUND4CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_007C) }; newtype! { /// TODO: docs @@ -158,16 +167,16 @@ impl NoiseFrequencySetting { // TODO: unify FIFO as /// Sound A FIFO, Data 0 and Data 1 (W) -pub const FIFO_A_L: VolAddress = unsafe { VolAddress::new(0x400_00A0) }; +pub const FIFO_A_L: VolAddress = unsafe { VolAddress::new(0x400_00A0) }; /// Sound A FIFO, Data 2 and Data 3 (W) -pub const FIFO_A_H: VolAddress = unsafe { VolAddress::new(0x400_00A2) }; +pub const FIFO_A_H: VolAddress = unsafe { VolAddress::new(0x400_00A2) }; /// Sound B FIFO, Data 0 and Data 1 (W) -pub const FIFO_B_L: VolAddress = unsafe { VolAddress::new(0x400_00A4) }; +pub const FIFO_B_L: VolAddress = unsafe { VolAddress::new(0x400_00A4) }; /// Sound B FIFO, Data 2 and Data 3 (W) -pub const FIFO_B_H: VolAddress = unsafe { VolAddress::new(0x400_00A6) }; +pub const FIFO_B_H: VolAddress = unsafe { VolAddress::new(0x400_00A6) }; /// Channel L/R Volume/Enable (`NR50`, `NR51`). Read/Write. -pub const SOUNDCNT_L: VolAddress = +pub const SOUNDCNT_L: VolAddress = unsafe { VolAddress::new(0x400_0080) }; newtype! { @@ -186,7 +195,8 @@ impl NonWaveVolumeEnableSetting { } /// DMA Sound Control/Mixing. Read/Write. -pub const SOUNDCNT_H: VolAddress = unsafe { VolAddress::new(0x400_0082) }; +pub const SOUNDCNT_H: VolAddress = + unsafe { VolAddress::new(0x400_0082) }; newtype! { /// TODO: docs @@ -222,7 +232,8 @@ newtype_enum! { } /// Sound on/off (`NR52`). Read/Write. -pub const SOUNDCNT_X: VolAddress = unsafe { VolAddress::new(0x400_0084) }; +pub const SOUNDCNT_X: VolAddress = + unsafe { VolAddress::new(0x400_0084) }; newtype! { /// TODO: docs @@ -241,7 +252,8 @@ impl SoundMasterSetting { } /// Sound on/off (`NR52`). Read/Write. -pub const SOUNDBIAS: VolAddress = unsafe { VolAddress::new(0x400_0088) }; +pub const SOUNDBIAS: VolAddress = + unsafe { VolAddress::new(0x400_0088) }; newtype! { /// TODO: docs diff --git a/src/io/timers.rs b/src/io/timers.rs index 1257ba4..8903176 100644 --- a/src/io/timers.rs +++ b/src/io/timers.rs @@ -28,28 +28,32 @@ use super::*; // TODO: striding blocks? /// Timer 0 Counter/Reload. Special (see module). -pub const TM0CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0100) }; +pub const TM0CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0100) }; /// Timer 1 Counter/Reload. Special (see module). -pub const TM1CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0104) }; +pub const TM1CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0104) }; /// Timer 2 Counter/Reload. Special (see module). -pub const TM2CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0108) }; +pub const TM2CNT_L: VolAddress = unsafe { VolAddress::new(0x400_0108) }; /// Timer 3 Counter/Reload. Special (see module). -pub const TM3CNT_L: VolAddress = unsafe { VolAddress::new(0x400_010C) }; +pub const TM3CNT_L: VolAddress = unsafe { VolAddress::new(0x400_010C) }; /// Timer 0 Control. Read/Write. -pub const TM0CNT_H: VolAddress = unsafe { VolAddress::new(0x400_0102) }; +pub const TM0CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_0102) }; /// Timer 1 Control. Read/Write. -pub const TM1CNT_H: VolAddress = unsafe { VolAddress::new(0x400_0106) }; +pub const TM1CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_0106) }; /// Timer 2 Control. Read/Write. -pub const TM2CNT_H: VolAddress = unsafe { VolAddress::new(0x400_010A) }; +pub const TM2CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_010A) }; /// Timer 3 Control. Read/Write. -pub const TM3CNT_H: VolAddress = unsafe { VolAddress::new(0x400_010E) }; +pub const TM3CNT_H: VolAddress = + unsafe { VolAddress::new(0x400_010E) }; newtype! { /// Allows control of a timer unit. diff --git a/src/io/window.rs b/src/io/window.rs index c163824..0daeaeb 100644 --- a/src/io/window.rs +++ b/src/io/window.rs @@ -3,10 +3,12 @@ use super::*; /// Window 0 Horizontal Dimensions (W) -pub const WIN0H: VolAddress = unsafe { VolAddress::new(0x400_0040) }; +pub const WIN0H: VolAddress = + unsafe { VolAddress::new(0x400_0040) }; /// Window 1 Horizontal Dimensions (W) -pub const WIN1H: VolAddress = unsafe { VolAddress::new(0x400_0042) }; +pub const WIN1H: VolAddress = + unsafe { VolAddress::new(0x400_0042) }; newtype! { /// TODO: docs @@ -22,10 +24,12 @@ impl HorizontalWindowSetting { } /// Window 0 Vertical Dimensions (W) -pub const WIN0V: VolAddress = unsafe { VolAddress::new(0x400_0044) }; +pub const WIN0V: VolAddress = + unsafe { VolAddress::new(0x400_0044) }; /// Window 1 Vertical Dimensions (W) -pub const WIN1V: VolAddress = unsafe { VolAddress::new(0x400_0046) }; +pub const WIN1V: VolAddress = + unsafe { VolAddress::new(0x400_0046) }; newtype! { /// TODO: docs @@ -41,7 +45,8 @@ impl VerticalWindowSetting { } /// Control of Inside of Window(s) (R/W) -pub const WININ: VolAddress = unsafe { VolAddress::new(0x400_0048) }; +pub const WININ: VolAddress = + unsafe { VolAddress::new(0x400_0048) }; newtype! { /// TODO: docs @@ -67,7 +72,8 @@ impl InsideWindowSetting { } /// Control of Outside of Windows & Inside of OBJ Window (R/W) -pub const WINOUT: VolAddress = unsafe { VolAddress::new(0x400_004A) }; +pub const WINOUT: VolAddress = + unsafe { VolAddress::new(0x400_004A) }; newtype! { /// TODO: docs diff --git a/src/lib.rs b/src/lib.rs index 636bc1d..ecf25bd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,8 +1,7 @@ #![cfg_attr(not(test), no_std)] #![feature(asm, global_asm, isa_attribute)] -#![allow(clippy::cast_lossless)] -#![deny(clippy::float_arithmetic)] -#![warn(missing_docs)] +#![allow(unused_imports)] +//#![warn(missing_docs)] //! This crate helps you write GBA ROMs. //! @@ -18,12 +17,11 @@ //! do, it's a giant bag of Undefined Behavior. pub(crate) use gba_proc_macro::phantom_fields; -pub(crate) use voladdress::{read_only::ROVolAddress, VolAddress, VolBlock}; + +use voladdress::*; pub mod macros; -pub mod base; - pub mod bios; pub mod iwram; diff --git a/src/oam.rs b/src/oam.rs index 82b3f58..8c3c622 100644 --- a/src/oam.rs +++ b/src/oam.rs @@ -2,8 +2,6 @@ use super::*; -use typenum::consts::{U128, U32}; - newtype! { /// 0th part of an object's attributes. /// @@ -139,7 +137,7 @@ pub struct ObjectAttributes { /// The object attributes, but there are gaps in the array, so we must not /// expose this directly. -const OBJ_ATTR_APPROX: VolBlock<[u16; 4], U128> = unsafe { VolBlock::new(0x700_0000) }; +const OBJ_ATTR_APPROX: VolBlock<[u16; 4], Safe, Safe, 128> = unsafe { VolBlock::new(0x700_0000) }; // TODO: VolSeries pub fn write_obj_attributes(slot: usize, attributes: ObjectAttributes) -> Option<()> { @@ -172,7 +170,8 @@ pub struct AffineParameters { /// The object attributes, but there are gaps in the array, so we must not /// expose this directly. -const AFFINE_PARAMS_APPROX: VolBlock<[i16; 16], U32> = unsafe { VolBlock::new(0x700_0000) }; +const AFFINE_PARAMS_APPROX: VolBlock<[i16; 16], Safe, Safe, 32> = + unsafe { VolBlock::new(0x700_0000) }; // TODO: VolSeries pub fn write_affine_parameters(slot: usize, params: AffineParameters) -> Option<()> { diff --git a/src/palram.rs b/src/palram.rs index 7d8769e..bf9037f 100644 --- a/src/palram.rs +++ b/src/palram.rs @@ -25,42 +25,36 @@ use super::*; -use typenum::consts::U256; - // TODO: PalIndex newtypes? /// The `PALRAM` for background colors, 256 slot view. -pub const PALRAM_BG: VolBlock = unsafe { VolBlock::new(0x500_0000) }; +pub const PALRAM_BG: VolBlock = unsafe { VolBlock::new(0x500_0000) }; /// The `PALRAM` for object colors, 256 slot view. -pub const PALRAM_OBJ: VolBlock = unsafe { VolBlock::new(0x500_0200) }; +pub const PALRAM_OBJ: VolBlock = unsafe { VolBlock::new(0x500_0200) }; /// Obtains the address of the specified 8bpp background palette slot. -pub const fn index_palram_bg_8bpp(slot: u8) -> VolAddress { - // Note(Lokathor): because of the `u8` limit we can't go out of bounds here. - unsafe { PALRAM_BG.index_unchecked(slot as usize) } +pub const fn index_palram_bg_8bpp(slot: u8) -> VolAddress { + PALRAM_BG.index(slot as usize) } /// Obtains the address of the specified 8bpp object palette slot. -pub const fn index_palram_obj_8bpp(slot: u8) -> VolAddress { - // Note(Lokathor): because of the `u8` limit we can't go out of bounds here. - unsafe { PALRAM_OBJ.index_unchecked(slot as usize) } +pub const fn index_palram_obj_8bpp(slot: u8) -> VolAddress { + PALRAM_OBJ.index(slot as usize) } /// Obtains the address of the specified 4bpp background palbank and palslot. /// /// Accesses `palbank * 16 + palslot`, if this is out of bounds the computation /// will wrap. -pub const fn index_palram_bg_4bpp(palbank: u8, palslot: u8) -> VolAddress { - // Note(Lokathor): because of the `u8` limit we can't go out of bounds here. - unsafe { PALRAM_BG.index_unchecked(palbank.wrapping_mul(16).wrapping_add(palslot) as usize) } +pub const fn index_palram_bg_4bpp(palbank: u8, palslot: u8) -> VolAddress { + PALRAM_BG.index(palbank.wrapping_mul(16).wrapping_add(palslot) as usize) } /// Obtains the address of the specified 4bpp object palbank and palslot. /// /// Accesses `palbank * 16 + palslot`, if this is out of bounds the computation /// will wrap. -pub const fn index_palram_obj_4bpp(palbank: u8, palslot: u8) -> VolAddress { - // Note(Lokathor): because of the `u8` limit we can't go out of bounds here. - unsafe { PALRAM_OBJ.index_unchecked(palbank.wrapping_mul(16).wrapping_add(palslot) as usize) } +pub const fn index_palram_obj_4bpp(palbank: u8, palslot: u8) -> VolAddress { + PALRAM_OBJ.index(palbank.wrapping_mul(16).wrapping_add(palslot) as usize) } diff --git a/src/save/eeprom.rs b/src/save/eeprom.rs index 9fa0c7c..a32fa90 100644 --- a/src/save/eeprom.rs +++ b/src/save/eeprom.rs @@ -9,9 +9,9 @@ use crate::{ sync::with_irqs_disabled, }; use core::cmp; -use voladdress::VolAddress; +use voladdress::*; -const PORT: VolAddress = unsafe { VolAddress::new(0x0DFFFF00) }; +const PORT: VolAddress = unsafe { VolAddress::new(0x0DFFFF00) }; const SECTOR_SHIFT: usize = 3; const SECTOR_LEN: usize = 1 << SECTOR_SHIFT; const SECTOR_MASK: usize = SECTOR_LEN - 1; @@ -156,32 +156,30 @@ impl EepromProperties { /// Writes a sector directly. fn write_sector_raw(&self, word: usize, block: &[u8]) -> Result<(), Error> { - unsafe { - // Write sector command. The command is a one bit, followed by a - // zero bit, followed by the address, followed by 64 bits of data. - // - // 512B Command: [1 0|n n n n n n|v v v v ...] - // 8KiB Command: [1 0|n n n n n n n n n n n n n n|v v v v ...] - let mut buf = BufferData::new(); - buf.write_bit(1); - buf.write_bit(0); - buf.write_num(self.addr_bits, word as u32); - for i in 0..8 { - buf.write_num(8, block[i] as u32); - } - buf.write_bit(0); - buf.submit(); - - // Wait for the sector to be written for 10 milliseconds. - let timeout = Timeout::new()?; - timeout.start(); - while PORT.read() & 1 != 1 { - if timeout.is_timeout_met(10) { - return Err(Error::OperationTimedOut); - } - } - Ok(()) + // Write sector command. The command is a one bit, followed by a + // zero bit, followed by the address, followed by 64 bits of data. + // + // 512B Command: [1 0|n n n n n n|v v v v ...] + // 8KiB Command: [1 0|n n n n n n n n n n n n n n|v v v v ...] + let mut buf = BufferData::new(); + buf.write_bit(1); + buf.write_bit(0); + buf.write_num(self.addr_bits, word as u32); + for i in 0..8 { + buf.write_num(8, block[i] as u32); } + buf.write_bit(0); + buf.submit(); + + // Wait for the sector to be written for 10 milliseconds. + let timeout = Timeout::new()?; + timeout.start(); + while PORT.read() & 1 != 1 { + if timeout.is_timeout_met(10) { + return Err(Error::OperationTimedOut); + } + } + Ok(()) } /// Writes a sector to the EEPROM, keeping any current contents outside the @@ -218,7 +216,7 @@ impl EepromProperties { let start = offset & SECTOR_MASK; let end_len = cmp::min(SECTOR_LEN - start, buf.len()); let sector = self.read_sector(offset >> SECTOR_SHIFT); - buf[..end_len].copy_from_slice(§or[start..start+end_len]); + buf[..end_len].copy_from_slice(§or[start..start + end_len]); buf = &mut buf[end_len..]; offset += end_len; } diff --git a/src/save/flash.rs b/src/save/flash.rs index fbff0b9..7ea7e56 100644 --- a/src/save/flash.rs +++ b/src/save/flash.rs @@ -9,14 +9,13 @@ use super::{ }; use crate::sync::{with_irqs_disabled, InitOnce, Static}; use core::cmp; -use typenum::consts::U65536; -use voladdress::{VolAddress, VolBlock}; +use voladdress::*; // Volatile address ports for flash -const FLASH_PORT_BANK: VolAddress = unsafe { VolAddress::new(0x0E000000) }; -const FLASH_PORT_A: VolAddress = unsafe { VolAddress::new(0x0E005555) }; -const FLASH_PORT_B: VolAddress = unsafe { VolAddress::new(0x0E002AAA) }; -const FLASH_DATA: VolBlock = unsafe { VolBlock::new(0x0E000000) }; +const FLASH_PORT_BANK: VolAddress = unsafe { VolAddress::new(0x0E000000) }; +const FLASH_PORT_A: VolAddress = unsafe { VolAddress::new(0x0E005555) }; +const FLASH_PORT_B: VolAddress = unsafe { VolAddress::new(0x0E002AAA) }; +const FLASH_DATA: VolBlock = unsafe { VolBlock::new(0x0E000000) }; // Various constants related to sector sizes const BANK_SHIFT: usize = 16; // 64 KiB @@ -133,7 +132,7 @@ struct ChipInfo { /// The timeout in milliseconds for writes to this chip. write_timeout: u16, - /// The timeout in mililseconds for erasing a sector in this chip. + /// The timeout in milliseconds for erasing a sector in this chip. erase_sector_timeout: u16, /// The timeout in milliseconds for erasing the entire chip. erase_chip_timeout: u16, diff --git a/src/save/utils.rs b/src/save/utils.rs index d3fc55a..5db996b 100644 --- a/src/save/utils.rs +++ b/src/save/utils.rs @@ -1,12 +1,12 @@ //! A package containing useful utilities for writing save accessors. This is -//! mainly used internally, although the types inside are exposed publically. +//! mainly used internally, although the types inside are exposed publicly. use super::Error; use crate::{ io::timers::*, sync::{RawMutex, RawMutexGuard, Static}, }; -use voladdress::VolAddress; +use voladdress::*; /// Internal representation for our active timer. #[derive(Copy, Clone, PartialEq)] @@ -44,8 +44,8 @@ pub fn disable_timeout() { pub struct Timeout { _lock_guard: RawMutexGuard<'static>, active: bool, - timer_l: VolAddress, - timer_h: VolAddress, + timer_l: VolAddress, + timer_h: VolAddress, } impl Timeout { /// Creates a new timeout from the timer passed to [`set_timer_for_timeout`]. diff --git a/src/sync.rs b/src/sync.rs index 239b8f0..d2086e0 100644 --- a/src/sync.rs +++ b/src/sync.rs @@ -29,13 +29,19 @@ pub fn memory_write_hint(val: *mut T) { } /// An internal function used as a temporary hack to get `compiler_fence` -/// working. While this call is not properly inlined, working is better than -/// not working at all. +/// working. While this call is not properly inlined, working is better than not +/// working at all. /// /// This seems to be a problem caused by Rust issue #62256: /// /// /// Not public API, obviously. +/// +/// NOTE TO ANYONE WHO FINDS THIS: THIS FUNCTION SHOULD NOT NORMALLY BE BLANK. +/// Having a blank version of this function is *only* correct because the GBA is +/// so old that it doesn't actually have atomics to sync to begin with (just a +/// main thread + interrupts). On any modern CPU, having this function be blank +/// is extremely likely to be incorrect. #[doc(hidden)] #[deprecated] #[allow(dead_code)] @@ -49,15 +55,15 @@ pub unsafe extern "C" fn __sync_synchronize() {} /// for game functionality. pub fn with_irqs_disabled(mut func: impl FnOnce() -> T) -> T { let current_ime = IME.read(); - IME.write(IrqEnableSetting::IRQ_NO); + unsafe { IME.write(IrqEnableSetting::IRQ_NO) }; // prevents the contents of the function from being reordered before IME is disabled. memory_write_hint(&mut func); let mut result = func(); - // prevents the contents of the function from being reordered after IME is reenabled. + // prevents the contents of the function from being reordered after IME is re-enabled. memory_write_hint(&mut result); - IME.write(current_ime); + unsafe { IME.write(current_ime) }; result } diff --git a/src/sync/statics.rs b/src/sync/statics.rs index d85a1e1..a986472 100644 --- a/src/sync/statics.rs +++ b/src/sync/statics.rs @@ -1,15 +1,19 @@ #![cfg_attr(not(target_arch = "arm"), allow(unused_variables))] -use super::*; -use core::{cell::UnsafeCell, mem, mem::MaybeUninit, ptr}; +use crate::sync::with_irqs_disabled; +use core::{ + cell::UnsafeCell, + mem::{align_of, size_of, MaybeUninit}, + ptr, +}; /// The internal function for replacing a `Copy` (really `!Drop`) value in a /// [`Static`]. This uses assembly to use an `stmia` instruction to ensure /// an IRQ cannot occur during the write operation. #[cfg(target_arch = "arm")] unsafe fn transfer(dst: *mut T, src: *const T) { - let align = mem::align_of::(); - let size = mem::size_of::(); + let align = align_of::(); + let size = size_of::(); if size == 0 { // Do nothing with ZSTs. Obviously. } else if size <= 16 && align % 4 == 0 { @@ -41,7 +45,7 @@ unsafe fn transfer(dst: *mut T, src: *const T) { #[cfg(target_arch = "arm")] #[allow(unused_assignments)] unsafe fn transfer_align4_thumb(mut dst: *mut T, mut src: *const T) { - let size = mem::size_of::(); + let size = size_of::(); if size <= 4 { // We use assembly here regardless to just do the word aligned copy. This // ensures it's done with a single ldr/str instruction. @@ -82,7 +86,7 @@ unsafe fn transfer_align4_thumb(mut dst: *mut T, mut src: *const T) { #[instruction_set(arm::a32)] #[allow(unused_assignments)] unsafe fn transfer_align4_arm(mut dst: *mut T, mut src: *const T) { - let size = mem::size_of::(); + let size = size_of::(); if size <= 16 { unimplemented!("This should be done via transfer_thumb."); } else if size <= 20 { @@ -134,8 +138,8 @@ unsafe fn transfer_align4_arm(mut dst: *mut T, mut src: *const T) { /// another value. #[cfg(target_arch = "arm")] unsafe fn exchange(dst: *mut T, src: *const T) -> T { - let align = mem::align_of::(); - let size = mem::size_of::(); + let align = align_of::(); + let size = size_of::(); if size == 0 { // Do nothing with ZSTs. ptr::read(dst) diff --git a/src/vram.rs b/src/vram.rs index f87dd04..5bfeb27 100644 --- a/src/vram.rs +++ b/src/vram.rs @@ -15,8 +15,6 @@ pub(crate) use super::*; -use typenum::{U1024, consts::{U256, U32, U512, U6}}; - pub mod affine; pub mod bitmap; pub mod text; @@ -34,10 +32,11 @@ pub const VRAM_BASE_USIZE: usize = 0x600_0000; pub const PAGE1_OFFSET: usize = 0xA000; /// The character base blocks. -pub const CHAR_BASE_BLOCKS: VolBlock<[u8; 0x4000], U6> = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; +pub const CHAR_BASE_BLOCKS: VolBlock<[u8; 0x4000], Safe, Safe, 6> = + unsafe { VolBlock::new(VRAM_BASE_USIZE) }; /// The screen entry base blocks. -pub const SCREEN_BASE_BLOCKS: VolBlock<[u8; 0x800], U32> = +pub const SCREEN_BASE_BLOCKS: VolBlock<[u8; 0x800], Safe, Safe, 32> = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; newtype! { @@ -53,15 +52,15 @@ newtype! { } /// Gives the specified charblock in 4bpp view. -pub fn get_4bpp_character_block(slot: usize) -> VolBlock { - unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).to_usize()) } +pub fn get_4bpp_character_block(slot: usize) -> VolBlock { + unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).as_usize()) } } /// Gives the specified charblock in 8bpp view. -pub fn get_8bpp_character_block(slot: usize) -> VolBlock { - unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).to_usize()) } +pub fn get_8bpp_character_block(slot: usize) -> VolBlock { + unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).as_usize()) } } -pub fn get_screen_block(slot: usize) -> VolBlock { - unsafe { VolBlock::new(SCREEN_BASE_BLOCKS.index(slot).to_usize()) } -} \ No newline at end of file +pub fn get_screen_block(slot: usize) -> VolBlock { + unsafe { VolBlock::new(SCREEN_BASE_BLOCKS.index(slot).as_usize()) } +} diff --git a/src/vram/bitmap.rs b/src/vram/bitmap.rs index f21919a..2ae38f9 100644 --- a/src/vram/bitmap.rs +++ b/src/vram/bitmap.rs @@ -1,8 +1,6 @@ //! Module for the Bitmap video modes. use super::*; -use core::ops::{Div, Mul}; -use typenum::consts::{U128, U160, U2, U256, U4}; /// A bitmap video mode with full color and full resolution. /// @@ -23,10 +21,10 @@ impl Mode3 { /// The screen's height in this mode. pub const HEIGHT: usize = 160; - const VRAM: VolBlock>::Output> = + const VRAM: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; - const WORDS_BLOCK: VolBlock>::Output as Div>::Output> = + const WORDS_BLOCK: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; /// Gets the address of the pixel specified. @@ -34,7 +32,7 @@ impl Mode3 { /// ## Failure /// /// Gives `None` if out of bounds - fn get(col: usize, row: usize) -> Option> { + fn get(col: usize, row: usize) -> Option> { Self::VRAM.get(col + row * Self::WIDTH) } @@ -44,7 +42,7 @@ impl Mode3 { /// /// Gives `None` if out of bounds pub fn read(col: usize, row: usize) -> Option { - Self::get(col, row).map(VolAddress::read) + Self::get(col, row).map(VolAddress::::read) } /// Writes a color to the pixel specified. @@ -164,16 +162,16 @@ impl Mode4 { /// The screen's height in this mode. pub const HEIGHT: usize = 160; - const PAGE0_INDEXES: VolBlock>::Output> = + const PAGE0_INDEXES: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; - const PAGE1_INDEXES: VolBlock>::Output> = + const PAGE1_INDEXES: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; - const PAGE0_WORDS: VolBlock>::Output as Div>::Output> = + const PAGE0_WORDS: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; - const PAGE1_WORDS: VolBlock>::Output as Div>::Output> = + const PAGE1_WORDS: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; /// Reads the color of the pixel specified. @@ -187,7 +185,7 @@ impl Mode4 { Page::One => Self::PAGE1_INDEXES, } .get(col + row * Self::WIDTH) - .map(VolAddress::read) + .map(VolAddress::::read) } /// Writes a color to the pixel specified. @@ -201,12 +199,12 @@ impl Mode4 { if col < Self::WIDTH && row < Self::HEIGHT { let real_index = col + row * Self::WIDTH; let rounded_down_index = real_index & !1; - let address: VolAddress = unsafe { + let address: VolAddress = unsafe { match page { Page::Zero => Self::PAGE0_INDEXES, Page::One => Self::PAGE1_INDEXES, } - .index_unchecked(rounded_down_index) + .index(rounded_down_index) .cast::() }; if real_index != rounded_down_index { @@ -247,11 +245,9 @@ impl Mode4 { let pal8bpp_32 = pal8bpp as u32; let bulk_color = (pal8bpp_32 << 24) | (pal8bpp_32 << 16) | (pal8bpp_32 << 8) | pal8bpp_32; - let words_address = unsafe { - match page { - Page::Zero => Self::PAGE0_WORDS.index_unchecked(0).to_usize(), - Page::One => Self::PAGE1_WORDS.index_unchecked(0).to_usize(), - } + let words_address = match page { + Page::Zero => Self::PAGE0_WORDS.index(0).as_usize(), + Page::One => Self::PAGE1_WORDS.index(0).as_usize(), }; unsafe { DMA3::fill32(&bulk_color, words_address as *mut u32, Self::PAGE0_WORDS.len() as u16) }; } @@ -331,16 +327,16 @@ impl Mode5 { /// The screen's height in this mode. pub const HEIGHT: usize = 128; - const PAGE0_PIXELS: VolBlock>::Output> = + const PAGE0_PIXELS: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; - const PAGE1_PIXELS: VolBlock>::Output> = + const PAGE1_PIXELS: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; - const PAGE0_WORDS: VolBlock>::Output as Div>::Output> = + const PAGE0_WORDS: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE) }; - const PAGE1_WORDS: VolBlock>::Output as Div>::Output> = + const PAGE1_WORDS: VolBlock = unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; /// Reads the color of the pixel specified. @@ -354,7 +350,7 @@ impl Mode5 { Page::One => Self::PAGE1_PIXELS, } .get(col + row * Self::WIDTH) - .map(VolAddress::read) + .map(VolAddress::::read) } /// Writes a color to the pixel specified. @@ -394,11 +390,9 @@ impl Mode5 { let color32 = color.0 as u32; let bulk_color = color32 << 16 | color32; - let words_address = unsafe { - match page { - Page::Zero => Self::PAGE0_WORDS.index_unchecked(0).to_usize(), - Page::One => Self::PAGE1_WORDS.index_unchecked(0).to_usize(), - } + let words_address = match page { + Page::Zero => Self::PAGE0_WORDS.index(0).as_usize(), + Page::One => Self::PAGE1_WORDS.index(0).as_usize(), }; unsafe { DMA3::fill32(&bulk_color, words_address as *mut u32, Self::PAGE0_WORDS.len() as u16) }; }