update to voladdress-0.4 (#120)

* update to voladdress-0.4 (via git)

* restore the imports rust-analyzer told me to break.
This commit is contained in:
Lokathor 2021-03-31 20:22:42 -06:00 committed by GitHub
parent 7b2a067aad
commit 3bcd64f28c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 260 additions and 239 deletions

View file

@ -16,8 +16,7 @@ default = []
serial = ["embedded-hal", "nb"] serial = ["embedded-hal", "nb"]
[dependencies] [dependencies]
typenum = "1.10" voladdress = { version = "0.4.0-alpha.0", git = "https://github.com/rust-console/voladdress" }
voladdress = "0.2"
gba-proc-macro = "0.5" gba-proc-macro = "0.5"
embedded-hal = { version = "0.2.4", optional = true } embedded-hal = { version = "0.2.4", optional = true }
nb = { version = "1.0.0", optional = true } nb = { version = "1.0.0", optional = true }

View file

@ -44,7 +44,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
irq::set_irq_handler(irq_handler); irq::set_irq_handler(irq_handler);
// Enable all interrupts that are set in the IE register. // 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. // Request that VBlank, HBlank and VCount will generate IRQs.
const DISPLAY_SETTINGS: DisplayStatusSetting = DisplayStatusSetting::new() const DISPLAY_SETTINGS: DisplayStatusSetting = DisplayStatusSetting::new()
@ -78,7 +78,7 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
flags = flags.with_timer1(true); 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 // Puts the CPU into low power mode until a VBlank IRQ is received. This
// will yield considerably better power efficiency as opposed to spin // 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 // When using `interrupt_wait()` or `vblank_interrupt_wait()`, IRQ handlers must acknowledge
// the IRQ on the BIOS Interrupt Flags register. // 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() { fn hblank_handler() {
write_pixel(GREEN); 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() { fn vcounter_handler() {
write_pixel(RED); 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() { fn timer0_handler() {
write_pixel(YELLOW); 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() { fn timer1_handler() {
write_pixel(PINK); write_pixel(PINK);
BIOS_IF.write(BIOS_IF.read().with_timer1(true)); unsafe { BIOS_IF.write(BIOS_IF.read().with_timer1(true)) };
} }

View file

@ -4,14 +4,14 @@
use core::cmp; use core::cmp;
use gba::{ use gba::{
fatal, warn, fatal,
io::{ io::{
display::{DisplayControlSetting, DisplayMode, DISPCNT}, display::{DisplayControlSetting, DisplayMode, DISPCNT},
timers::{TimerControlSetting, TimerTickRate, TM0CNT_H, TM0CNT_L, TM1CNT_H, TM1CNT_L}, timers::{TimerControlSetting, TimerTickRate, TM0CNT_H, TM0CNT_L, TM1CNT_H, TM1CNT_L},
}, },
save::*, save::*,
vram::bitmap::Mode3, vram::bitmap::Mode3,
Color, warn, Color,
}; };
fn set_screen_color(r: u16, g: u16, b: u16) { 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) -> ! { fn panic(info: &core::panic::PanicInfo) -> ! {
set_screen_color(31, 0, 0); set_screen_color(31, 0, 0);
fatal!("{}", info); fatal!("{}", info);
loop {}
} }
#[derive(Clone)] #[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]; let mut buffer = [0; MAX_BLOCK_SIZE];
output!(" - Clearing media..."); output!(" - Clearing media...");
access.prepare_write(offset..offset+len)?; access.prepare_write(offset..offset + len)?;
output!(" - Writing media..."); output!(" - Writing media...");
let mut rng = seed.clone(); let mut rng = seed.clone();
@ -168,7 +167,9 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
output!( output!(
"[ Partial, offset = 0x{:06x}, len = {}, bs = {}]", "[ 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)); check_status(do_test(Rng(i * 10000), rand_offset, rand_length, block_size));
set_screen_progress(3 + i as usize, 10); 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 // show a pattern so we know it worked
set_screen_color(0, 31, 0); set_screen_color(0, 31, 0);
loop { } loop {}
} }

View file

@ -10,7 +10,6 @@
#![cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #![cfg_attr(not(target_arch = "arm"), allow(unused_variables))]
use core::mem;
use super::*; use super::*;
use io::irq::IrqFlags; use io::irq::IrqFlags;
@ -184,8 +183,8 @@ pub fn interrupt_wait(ignore_current_flags: bool, target_flags: IrqFlags) {
unsafe { unsafe {
asm!( asm!(
"swi 0x04", "swi 0x04",
in("r0") mem::transmute::<bool, u8>(ignore_current_flags), in("r0") ignore_current_flags as u8,
in("r1") mem::transmute::<IrqFlags, u16>(target_flags), in("r1") target_flags.0,
); );
} }
} }

View file

@ -3,15 +3,8 @@
//! This is the underlying implementation behind the various print macros in //! 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. //! the gba crate. It currently supports the latest versions of mGBA and NO$GBA.
use crate::{ use crate::sync::{InitOnce, RawMutex, Static};
io::{
dma::{DMAControlSetting, DMA0, DMA1, DMA2, DMA3},
irq::{IrqEnableSetting, IME},
},
sync::{InitOnce, RawMutex, Static},
};
use core::fmt::{Arguments, Error}; use core::fmt::{Arguments, Error};
use voladdress::VolAddress;
pub mod mgba; pub mod mgba;
pub mod nocash; pub mod nocash;
@ -127,5 +120,5 @@ pub fn crash() -> ! {
} }
#[cfg(not(all(target_vendor = "nintendo", target_env = "agb")))] #[cfg(not(all(target_vendor = "nintendo", target_env = "agb")))]
loop { } loop {}
} }

View file

@ -7,7 +7,7 @@
use super::{DebugInterface, DebugLevel}; use super::{DebugInterface, DebugLevel};
use crate::sync::InitOnce; use crate::sync::InitOnce;
use core::fmt::{Arguments, Write}; use core::fmt::{Arguments, Write};
use voladdress::VolAddress; use voladdress::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u16)] #[repr(u16)]
@ -22,13 +22,13 @@ pub enum MGBADebugLevel {
} }
// MGBADebug related addresses. // MGBADebug related addresses.
const ENABLE_ADDRESS: VolAddress<u16> = unsafe { VolAddress::new(0x4fff780) }; const ENABLE_ADDRESS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x4fff780) };
const ENABLE_ADDRESS_INPUT: u16 = 0xC0DE; const ENABLE_ADDRESS_INPUT: u16 = 0xC0DE;
const ENABLE_ADDRESS_OUTPUT: u16 = 0x1DEA; const ENABLE_ADDRESS_OUTPUT: u16 = 0x1DEA;
const OUTPUT_BASE: VolAddress<u8> = unsafe { VolAddress::new(0x4fff600) }; const OUTPUT_BLOCK: VolBlock<u8, Safe, Safe, 256> = unsafe { VolBlock::new(0x4fff600) };
const SEND_ADDRESS: VolAddress<u16> = unsafe { VolAddress::new(0x4fff700) }; const SEND_ADDRESS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x4fff700) };
const SEND_FLAG: u16 = 0x100; const SEND_FLAG: u16 = 0x100;
// Only enable MGBA debugging once. // Only enable MGBA debugging once.
@ -82,7 +82,7 @@ impl MGBADebug {
impl core::fmt::Write for MGBADebug { impl core::fmt::Write for MGBADebug {
fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> { fn write_str(&mut self, s: &str) -> Result<(), core::fmt::Error> {
unsafe { 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(); let mut str_iter = s.bytes();
while self.bytes_written < 255 { while self.bytes_written < 255 {
match str_iter.next() { match str_iter.next() {

View file

@ -9,11 +9,10 @@ use crate::{
sync::InitOnce, sync::InitOnce,
}; };
use core::fmt::{Arguments, Write}; use core::fmt::{Arguments, Write};
use typenum::consts::U16; use voladdress::*;
use voladdress::{VolAddress, VolBlock};
const CHAR_OUT: VolAddress<u8> = unsafe { VolAddress::new(0x04FFFA1C) }; const CHAR_OUT: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x04FFFA1C) };
const SIGNATURE_ADDR: VolBlock<u8, U16> = unsafe { VolBlock::new(0x04FFFA00) }; const SIGNATURE_ADDR: VolBlock<u8, Safe, Safe, 16> = unsafe { VolBlock::new(0x04FFFA00) };
const SIGNATURE: [u8; 7] = *b"no$gba "; const SIGNATURE: [u8; 7] = *b"no$gba ";
static NO_CASH_DEBUGGING: InitOnce<bool> = InitOnce::new(); static NO_CASH_DEBUGGING: InitOnce<bool> = InitOnce::new();

View file

@ -1,4 +1,7 @@
#![allow(non_camel_case_types)] #![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. //! Module for fixed point math types and operations.

View file

@ -3,13 +3,17 @@
use super::*; use super::*;
/// BG0 Control. Read/Write. Display Mode 0/1 only. /// BG0 Control. Read/Write. Display Mode 0/1 only.
pub const BG0CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new(0x400_0008) }; pub const BG0CNT: VolAddress<BackgroundControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0008) };
/// BG1 Control. Read/Write. Display Mode 0/1 only. /// BG1 Control. Read/Write. Display Mode 0/1 only.
pub const BG1CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new(0x400_000A) }; pub const BG1CNT: VolAddress<BackgroundControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_000A) };
/// BG2 Control. Read/Write. Display Mode 0/1/2 only. /// BG2 Control. Read/Write. Display Mode 0/1/2 only.
pub const BG2CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new(0x400_000C) }; pub const BG2CNT: VolAddress<BackgroundControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_000C) };
/// BG3 Control. Read/Write. Display Mode 0/2 only. /// BG3 Control. Read/Write. Display Mode 0/2 only.
pub const BG3CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new(0x400_000E) }; pub const BG3CNT: VolAddress<BackgroundControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_000E) };
newtype! { newtype! {
/// Allows configuration of a background layer. /// Allows configuration of a background layer.
@ -66,24 +70,24 @@ pub enum BGSize {
} }
/// BG0 X-Offset. Write only. Text mode only. 9 bits. /// BG0 X-Offset. Write only. Text mode only. 9 bits.
pub const BG0HOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_0010) }; pub const BG0HOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0010) };
/// BG0 Y-Offset. Write only. Text mode only. 9 bits. /// BG0 Y-Offset. Write only. Text mode only. 9 bits.
pub const BG0VOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_0012) }; pub const BG0VOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0012) };
/// BG1 X-Offset. Write only. Text mode only. 9 bits. /// BG1 X-Offset. Write only. Text mode only. 9 bits.
pub const BG1HOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_0014) }; pub const BG1HOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0014) };
/// BG1 Y-Offset. Write only. Text mode only. 9 bits. /// BG1 Y-Offset. Write only. Text mode only. 9 bits.
pub const BG1VOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_0016) }; pub const BG1VOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0016) };
/// BG2 X-Offset. Write only. Text mode only. 9 bits. /// BG2 X-Offset. Write only. Text mode only. 9 bits.
pub const BG2HOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_0018) }; pub const BG2HOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0018) };
/// BG2 Y-Offset. Write only. Text mode only. 9 bits. /// BG2 Y-Offset. Write only. Text mode only. 9 bits.
pub const BG2VOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_001A) }; pub const BG2VOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_001A) };
/// BG3 X-Offset. Write only. Text mode only. 9 bits. /// BG3 X-Offset. Write only. Text mode only. 9 bits.
pub const BG3HOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_001C) }; pub const BG3HOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_001C) };
/// BG3 Y-Offset. Write only. Text mode only. 9 bits. /// BG3 Y-Offset. Write only. Text mode only. 9 bits.
pub const BG3VOFS: VolAddress<u16> = unsafe { VolAddress::new(0x400_001E) }; pub const BG3VOFS: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_001E) };
// TODO: affine backgrounds // TODO: affine backgrounds
// BG2X_L // BG2X_L

View file

@ -3,7 +3,8 @@
use super::*; use super::*;
/// Color Special Effects Selection (R/W) /// Color Special Effects Selection (R/W)
pub const BLDCNT: VolAddress<ColorEffectSetting> = unsafe { VolAddress::new(0x400_0050) }; pub const BLDCNT: VolAddress<ColorEffectSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0050) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -43,7 +44,8 @@ newtype_enum! {
} }
/// Alpha Blending Coefficients (R/W) (not W) /// Alpha Blending Coefficients (R/W) (not W)
pub const BLDALPHA: VolAddress<AlphaBlendingSetting> = unsafe { VolAddress::new(0x400_0052) }; pub const BLDALPHA: VolAddress<AlphaBlendingSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0052) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -59,7 +61,7 @@ impl AlphaBlendingSetting {
} }
/// Brightness (Fade-In/Out) Coefficient (W) (not R/W) /// Brightness (Fade-In/Out) Coefficient (W) (not R/W)
pub const BLDY: VolAddress<BrightnessSetting> = unsafe { VolAddress::new(0x400_0054) }; pub const BLDY: VolAddress<BrightnessSetting, Safe, Safe> = unsafe { VolAddress::new(0x400_0054) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs

View file

@ -5,7 +5,8 @@ use super::*;
/// LCD Control. Read/Write. /// LCD Control. Read/Write.
/// ///
/// The "force vblank" bit is always set when your Rust code first executes. /// The "force vblank" bit is always set when your Rust code first executes.
pub const DISPCNT: VolAddress<DisplayControlSetting> = unsafe { VolAddress::new(0x400_0000) }; pub const DISPCNT: VolAddress<DisplayControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0000) };
newtype!( newtype!(
/// Setting for the display control register. /// Setting for the display control register.
@ -96,7 +97,8 @@ pub fn display_control() -> DisplayControlSetting {
} }
/// Display Status and IRQ Control. Read/Write. /// Display Status and IRQ Control. Read/Write.
pub const DISPSTAT: VolAddress<DisplayStatusSetting> = unsafe { VolAddress::new(0x400_0004) }; pub const DISPSTAT: VolAddress<DisplayStatusSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0004) };
newtype!( newtype!(
/// A newtype over display status and interrupt control values. /// 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 /// 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 /// this is at or above the `VBLANK_SCANLINE` value then the display controller
/// is in a "vertical blank" period. /// is in a "vertical blank" period.
pub const VCOUNT: ROVolAddress<u16> = unsafe { ROVolAddress::new(0x400_0006) }; pub const VCOUNT: VolAddress<u16, Safe, ()> = unsafe { VolAddress::new(0x400_0006) };
/// If the `VCOUNT` register reads equal to or above this then you're in vblank. /// If the `VCOUNT` register reads equal to or above this then you're in vblank.
pub const VBLANK_SCANLINE: u16 = 160; pub const VBLANK_SCANLINE: u16 = 160;
/// Global mosaic effect control. Write-only. /// Global mosaic effect control. Write-only.
pub const MOSAIC: VolAddress<MosaicSetting> = unsafe { VolAddress::new(0x400_004C) }; pub const MOSAIC: VolAddress<MosaicSetting, Safe, Safe> = unsafe { VolAddress::new(0x400_004C) };
newtype! { newtype! {
/// Allows control of the Mosaic effect. /// Allows control of the Mosaic effect.

View file

@ -127,13 +127,14 @@ pub enum DMAStartTiming {
pub struct DMA0; pub struct DMA0;
impl DMA0 { impl DMA0 {
/// DMA 0 Source Address, read only. /// 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. /// 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. /// DMA 0 Word Count, read only.
const DMA0CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_00B8) }; const DMA0CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00B8) };
/// DMA 0 Control, read/write. /// DMA 0 Control, read/write.
const DMA0CNT_H: VolAddress<DMAControlSetting> = unsafe { VolAddress::new(0x400_00BA) }; const DMA0CNT_H: VolAddress<DMAControlSetting, Safe, Unsafe> =
unsafe { VolAddress::new(0x400_00BA) };
/// Assigns the source register. /// Assigns the source register.
/// ///
@ -190,13 +191,14 @@ impl DMA0 {
pub struct DMA1; pub struct DMA1;
impl DMA1 { impl DMA1 {
/// DMA 1 Source Address, read only. /// 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. /// 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. /// DMA 1 Word Count, read only.
const DMA1CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_00C4) }; const DMA1CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00C4) };
/// DMA 1 Control, read/write. /// DMA 1 Control, read/write.
const DMA1CNT_H: VolAddress<DMAControlSetting> = unsafe { VolAddress::new(0x400_00C6) }; const DMA1CNT_H: VolAddress<DMAControlSetting, Safe, Unsafe> =
unsafe { VolAddress::new(0x400_00C6) };
/// Assigns the source register. /// Assigns the source register.
/// ///
@ -253,13 +255,14 @@ impl DMA1 {
pub struct DMA2; pub struct DMA2;
impl DMA2 { impl DMA2 {
/// DMA 2 Source Address, read only. /// 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. /// 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. /// DMA 2 Word Count, read only.
const DMA2CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_00D0) }; const DMA2CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00D0) };
/// DMA 2 Control, read/write. /// DMA 2 Control, read/write.
const DMA2CNT_H: VolAddress<DMAControlSetting> = unsafe { VolAddress::new(0x400_00D2) }; const DMA2CNT_H: VolAddress<DMAControlSetting, Safe, Unsafe> =
unsafe { VolAddress::new(0x400_00D2) };
/// Assigns the source register. /// Assigns the source register.
/// ///
@ -317,13 +320,14 @@ impl DMA2 {
pub struct DMA3; pub struct DMA3;
impl DMA3 { impl DMA3 {
/// DMA 3 Source Address, read only. /// 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. /// 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. /// DMA 3 Word Count, read only.
const DMA3CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_00DC) }; const DMA3CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00DC) };
/// DMA 3 Control, read/write. /// DMA 3 Control, read/write.
const DMA3CNT_H: VolAddress<DMAControlSetting> = unsafe { VolAddress::new(0x400_00DE) }; const DMA3CNT_H: VolAddress<DMAControlSetting, Safe, Unsafe> =
unsafe { VolAddress::new(0x400_00DE) };
/// Assigns the source register. /// Assigns the source register.
/// ///

View file

@ -103,7 +103,7 @@ use super::*;
newtype!( newtype!(
/// A newtype over all interrupt flags. /// A newtype over all interrupt flags.
IrqFlags, IrqFlags,
u16 pub(crate) u16
); );
impl IrqFlags { impl IrqFlags {
@ -130,7 +130,7 @@ impl IrqFlags {
/// ///
/// After setting up interrupt handlers, set the flags on this register type corresponding to the /// After setting up interrupt handlers, set the flags on this register type corresponding to the
/// IRQs you want to handle. /// IRQs you want to handle.
pub const IE: VolAddress<IrqFlags> = unsafe { VolAddress::new(0x400_0200) }; pub const IE: VolAddress<IrqFlags, Safe, Unsafe> = unsafe { VolAddress::new(0x400_0200) };
/// Interrupt Request Flags / IRQ Acknowledge. Read/Write. /// Interrupt Request Flags / IRQ Acknowledge. Read/Write.
/// ///
@ -139,7 +139,7 @@ pub const IE: VolAddress<IrqFlags> = unsafe { VolAddress::new(0x400_0200) };
/// However, if the main interrupt handler in `rsrt0.S` is changed, then the /// 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 /// handler must write a `1` bit to all bits that are enabled on this register
/// when it is called. /// when it is called.
pub const IF: VolAddress<IrqFlags> = unsafe { VolAddress::new(0x400_0202) }; pub const IF: VolAddress<IrqFlags, Safe, Unsafe> = unsafe { VolAddress::new(0x400_0202) };
newtype! { newtype! {
/// Setting to control whether interrupts are enabled. /// Setting to control whether interrupts are enabled.
@ -161,7 +161,7 @@ impl IrqEnableSetting {
} }
/// Interrupt Master Enable Register. Read/Write. /// Interrupt Master Enable Register. Read/Write.
pub const IME: VolAddress<IrqEnableSetting> = unsafe { VolAddress::new(0x400_0208) }; pub const IME: VolAddress<IrqEnableSetting, Safe, Unsafe> = unsafe { VolAddress::new(0x400_0208) };
/// BIOS Interrupt Flags. Read/Write. /// BIOS Interrupt Flags. Read/Write.
/// ///
@ -169,7 +169,7 @@ pub const IME: VolAddress<IrqEnableSetting> = unsafe { VolAddress::new(0x400_020
/// [`vblank_interrupt_wait`](bios::vblank_interrupt_wait), the corresponding /// [`vblank_interrupt_wait`](bios::vblank_interrupt_wait), the corresponding
/// interrupt handler MUST set the flag of the interrupt it has handled on this /// interrupt handler MUST set the flag of the interrupt it has handled on this
/// register in addition to the usual interrupt acknowledgement. /// register in addition to the usual interrupt acknowledgement.
pub const BIOS_IF: VolAddress<IrqFlags> = unsafe { VolAddress::new(0x0300_7FF8) }; pub const BIOS_IF: VolAddress<IrqFlags, Safe, Unsafe> = unsafe { VolAddress::new(0x0300_7FF8) };
/// A function pointer for use as an interrupt handler. /// A function pointer for use as an interrupt handler.
pub type IrqHandler = extern "C" fn(IrqFlags); pub type IrqHandler = extern "C" fn(IrqFlags);

View file

@ -8,7 +8,7 @@ use super::*;
/// follow the "high-active" convention (hint: you probably do, it's far easier /// 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 /// to work with) then call `read_key_input()` rather than reading this register
/// directly. It will perform the necessary bit flip operation for you. /// directly. It will perform the necessary bit flip operation for you.
pub const KEYINPUT: ROVolAddress<u16> = unsafe { ROVolAddress::new(0x400_0130) }; pub const KEYINPUT: VolAddress<u16, Safe, ()> = unsafe { VolAddress::new(0x400_0130) };
/// A "tribool" value helps us interpret the arrow pad. /// A "tribool" value helps us interpret the arrow pad.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[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. /// Use this to configure when a keypad interrupt happens.
/// ///
/// See the `KeyInterruptSetting` type for more. /// See the `KeyInterruptSetting` type for more.
pub const KEYCNT: VolAddress<KeyInterruptSetting> = unsafe { VolAddress::new(0x400_0132) }; pub const KEYCNT: VolAddress<KeyInterruptSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0132) };
newtype! { newtype! {
/// Allows configuration of when a keypad interrupt fires. /// Allows configuration of when a keypad interrupt fires.

View file

@ -3,13 +3,14 @@
use super::*; use super::*;
/// Serial IO Control. Read/Write. /// Serial IO Control. Read/Write.
pub const SIOCNT: VolAddress<SioControlSetting> = unsafe { VolAddress::new(0x400_0128) }; pub const SIOCNT: VolAddress<SioControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0128) };
/// Serial IO Data. Read/Write. /// Serial IO Data. Read/Write.
pub const SIODATA8: VolAddress<u16> = unsafe { VolAddress::new(0x400_012A) }; pub const SIODATA8: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_012A) };
/// General IO Control. Read/Write. /// General IO Control. Read/Write.
pub const RCNT: VolAddress<IoControlSetting> = unsafe { VolAddress::new(0x400_0134) }; pub const RCNT: VolAddress<IoControlSetting, Safe, Safe> = unsafe { VolAddress::new(0x400_0134) };
newtype!( newtype!(
/// Setting for the serial IO control register. /// Setting for the serial IO control register.
@ -122,7 +123,7 @@ newtype_enum! {
JoyBus = 3, JoyBus = 3,
} }
/// Empty stuct that implements embedded_hal traits. /// Empty struct that implements embedded_hal traits.
#[cfg(feature = "serial")] #[cfg(feature = "serial")]
#[derive(Clone)] #[derive(Clone)]
pub struct SioSerial; pub struct SioSerial;

View file

@ -5,7 +5,8 @@ use super::*;
//TODO within these "read/write" registers only some bits are actually read/write! //TODO within these "read/write" registers only some bits are actually read/write!
/// Sound Channel 1 Sweep Register (`NR10`). Read/Write. /// Sound Channel 1 Sweep Register (`NR10`). Read/Write.
pub const SOUND1CNT_L: VolAddress<SweepRegisterSetting> = unsafe { VolAddress::new(0x400_0060) }; pub const SOUND1CNT_L: VolAddress<SweepRegisterSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0060) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -22,7 +23,8 @@ impl SweepRegisterSetting {
} }
/// Sound Channel 1 Duty/Length/Envelope (`NR11`, `NR12`). Read/Write. /// Sound Channel 1 Duty/Length/Envelope (`NR11`, `NR12`). Read/Write.
pub const SOUND1CNT_H: VolAddress<DutyLenEnvelopeSetting> = unsafe { VolAddress::new(0x400_0062) }; pub const SOUND1CNT_H: VolAddress<DutyLenEnvelopeSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0062) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -41,7 +43,8 @@ impl DutyLenEnvelopeSetting {
} }
/// Sound Channel 1 Frequency/Control (`NR13`, `NR14`). Read/Write. /// Sound Channel 1 Frequency/Control (`NR13`, `NR14`). Read/Write.
pub const SOUND1CNT_X: VolAddress<FrequencyControlSetting> = unsafe { VolAddress::new(0x400_0064) }; pub const SOUND1CNT_X: VolAddress<FrequencyControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0064) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -58,13 +61,15 @@ impl FrequencyControlSetting {
} }
/// Sound Channel 2 Channel 2 Duty/Length/Envelope (`NR21`, `NR22`). Read/Write. /// Sound Channel 2 Channel 2 Duty/Length/Envelope (`NR21`, `NR22`). Read/Write.
pub const SOUND2CNT_L: VolAddress<DutyLenEnvelopeSetting> = unsafe { VolAddress::new(0x400_0068) }; pub const SOUND2CNT_L: VolAddress<DutyLenEnvelopeSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0068) };
/// Sound Channel 2 Frequency/Control (`NR23`, `NR24`). Read/Write. /// Sound Channel 2 Frequency/Control (`NR23`, `NR24`). Read/Write.
pub const SOUND2CNT_H: VolAddress<FrequencyControlSetting> = unsafe { VolAddress::new(0x400_006C) }; pub const SOUND2CNT_H: VolAddress<FrequencyControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_006C) };
/// Sound Channel 3 Stop/Wave RAM select (`NR23`, `NR24`). Read/Write. /// Sound Channel 3 Stop/Wave RAM select (`NR23`, `NR24`). Read/Write.
pub const SOUND3CNT_L: VolAddress<StopWaveRAMSelectSetting> = pub const SOUND3CNT_L: VolAddress<StopWaveRAMSelectSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0070) }; unsafe { VolAddress::new(0x400_0070) };
newtype! { newtype! {
@ -82,7 +87,8 @@ impl StopWaveRAMSelectSetting {
} }
/// Sound Channel 3 Length/Volume (`NR23`, `NR24`). Read/Write. /// Sound Channel 3 Length/Volume (`NR23`, `NR24`). Read/Write.
pub const SOUND3CNT_H: VolAddress<LengthVolumeSetting> = unsafe { VolAddress::new(0x400_0072) }; pub const SOUND3CNT_H: VolAddress<LengthVolumeSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0072) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -99,27 +105,29 @@ impl LengthVolumeSetting {
} }
/// Sound Channel 3 Frequency/Control (`NR33`, `NR34`). Read/Write. /// Sound Channel 3 Frequency/Control (`NR33`, `NR34`). Read/Write.
pub const SOUND3CNT_X: VolAddress<FrequencyControlSetting> = unsafe { VolAddress::new(0x400_0074) }; pub const SOUND3CNT_X: VolAddress<FrequencyControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0074) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM0_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_0090) }; pub const WAVE_RAM0_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0090) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM0_H: VolAddress<u16> = unsafe { VolAddress::new(0x400_0092) }; pub const WAVE_RAM0_H: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0092) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM1_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_0094) }; pub const WAVE_RAM1_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0094) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM1_H: VolAddress<u16> = unsafe { VolAddress::new(0x400_0096) }; pub const WAVE_RAM1_H: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0096) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM2_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_0098) }; pub const WAVE_RAM2_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0098) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM2_H: VolAddress<u16> = unsafe { VolAddress::new(0x400_009A) }; pub const WAVE_RAM2_H: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_009A) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM3_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_009C) }; pub const WAVE_RAM3_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_009C) };
/// Channel 3 Wave Pattern RAM (W/R) /// Channel 3 Wave Pattern RAM (W/R)
pub const WAVE_RAM3_H: VolAddress<u16> = unsafe { VolAddress::new(0x400_009E) }; pub const WAVE_RAM3_H: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_009E) };
/// Sound Channel 4 Length/Envelope (`NR41`, `NR42`). Read/Write. /// Sound Channel 4 Length/Envelope (`NR41`, `NR42`). Read/Write.
pub const SOUND4CNT_L: VolAddress<LengthEnvelopeSetting> = unsafe { VolAddress::new(0x400_0078) }; pub const SOUND4CNT_L: VolAddress<LengthEnvelopeSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0078) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -137,7 +145,8 @@ impl LengthEnvelopeSetting {
} }
/// Sound Channel 4 Frequency/Control (`NR43`, `NR44`). Read/Write. /// Sound Channel 4 Frequency/Control (`NR43`, `NR44`). Read/Write.
pub const SOUND4CNT_H: VolAddress<NoiseFrequencySetting> = unsafe { VolAddress::new(0x400_007C) }; pub const SOUND4CNT_H: VolAddress<NoiseFrequencySetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_007C) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -158,16 +167,16 @@ impl NoiseFrequencySetting {
// TODO: unify FIFO as // TODO: unify FIFO as
/// Sound A FIFO, Data 0 and Data 1 (W) /// Sound A FIFO, Data 0 and Data 1 (W)
pub const FIFO_A_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_00A0) }; pub const FIFO_A_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_00A0) };
/// Sound A FIFO, Data 2 and Data 3 (W) /// Sound A FIFO, Data 2 and Data 3 (W)
pub const FIFO_A_H: VolAddress<u16> = unsafe { VolAddress::new(0x400_00A2) }; pub const FIFO_A_H: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_00A2) };
/// Sound B FIFO, Data 0 and Data 1 (W) /// Sound B FIFO, Data 0 and Data 1 (W)
pub const FIFO_B_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_00A4) }; pub const FIFO_B_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_00A4) };
/// Sound B FIFO, Data 2 and Data 3 (W) /// Sound B FIFO, Data 2 and Data 3 (W)
pub const FIFO_B_H: VolAddress<u16> = unsafe { VolAddress::new(0x400_00A6) }; pub const FIFO_B_H: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_00A6) };
/// Channel L/R Volume/Enable (`NR50`, `NR51`). Read/Write. /// Channel L/R Volume/Enable (`NR50`, `NR51`). Read/Write.
pub const SOUNDCNT_L: VolAddress<NonWaveVolumeEnableSetting> = pub const SOUNDCNT_L: VolAddress<NonWaveVolumeEnableSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0080) }; unsafe { VolAddress::new(0x400_0080) };
newtype! { newtype! {
@ -186,7 +195,8 @@ impl NonWaveVolumeEnableSetting {
} }
/// DMA Sound Control/Mixing. Read/Write. /// DMA Sound Control/Mixing. Read/Write.
pub const SOUNDCNT_H: VolAddress<WaveVolumeEnableSetting> = unsafe { VolAddress::new(0x400_0082) }; pub const SOUNDCNT_H: VolAddress<WaveVolumeEnableSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0082) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -222,7 +232,8 @@ newtype_enum! {
} }
/// Sound on/off (`NR52`). Read/Write. /// Sound on/off (`NR52`). Read/Write.
pub const SOUNDCNT_X: VolAddress<SoundMasterSetting> = unsafe { VolAddress::new(0x400_0084) }; pub const SOUNDCNT_X: VolAddress<SoundMasterSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0084) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -241,7 +252,8 @@ impl SoundMasterSetting {
} }
/// Sound on/off (`NR52`). Read/Write. /// Sound on/off (`NR52`). Read/Write.
pub const SOUNDBIAS: VolAddress<SoundPWMSetting> = unsafe { VolAddress::new(0x400_0088) }; pub const SOUNDBIAS: VolAddress<SoundPWMSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0088) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs

View file

@ -28,28 +28,32 @@ use super::*;
// TODO: striding blocks? // TODO: striding blocks?
/// Timer 0 Counter/Reload. Special (see module). /// Timer 0 Counter/Reload. Special (see module).
pub const TM0CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_0100) }; pub const TM0CNT_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0100) };
/// Timer 1 Counter/Reload. Special (see module). /// Timer 1 Counter/Reload. Special (see module).
pub const TM1CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_0104) }; pub const TM1CNT_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0104) };
/// Timer 2 Counter/Reload. Special (see module). /// Timer 2 Counter/Reload. Special (see module).
pub const TM2CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_0108) }; pub const TM2CNT_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_0108) };
/// Timer 3 Counter/Reload. Special (see module). /// Timer 3 Counter/Reload. Special (see module).
pub const TM3CNT_L: VolAddress<u16> = unsafe { VolAddress::new(0x400_010C) }; pub const TM3CNT_L: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x400_010C) };
/// Timer 0 Control. Read/Write. /// Timer 0 Control. Read/Write.
pub const TM0CNT_H: VolAddress<TimerControlSetting> = unsafe { VolAddress::new(0x400_0102) }; pub const TM0CNT_H: VolAddress<TimerControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0102) };
/// Timer 1 Control. Read/Write. /// Timer 1 Control. Read/Write.
pub const TM1CNT_H: VolAddress<TimerControlSetting> = unsafe { VolAddress::new(0x400_0106) }; pub const TM1CNT_H: VolAddress<TimerControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0106) };
/// Timer 2 Control. Read/Write. /// Timer 2 Control. Read/Write.
pub const TM2CNT_H: VolAddress<TimerControlSetting> = unsafe { VolAddress::new(0x400_010A) }; pub const TM2CNT_H: VolAddress<TimerControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_010A) };
/// Timer 3 Control. Read/Write. /// Timer 3 Control. Read/Write.
pub const TM3CNT_H: VolAddress<TimerControlSetting> = unsafe { VolAddress::new(0x400_010E) }; pub const TM3CNT_H: VolAddress<TimerControlSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_010E) };
newtype! { newtype! {
/// Allows control of a timer unit. /// Allows control of a timer unit.

View file

@ -3,10 +3,12 @@
use super::*; use super::*;
/// Window 0 Horizontal Dimensions (W) /// Window 0 Horizontal Dimensions (W)
pub const WIN0H: VolAddress<HorizontalWindowSetting> = unsafe { VolAddress::new(0x400_0040) }; pub const WIN0H: VolAddress<HorizontalWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0040) };
/// Window 1 Horizontal Dimensions (W) /// Window 1 Horizontal Dimensions (W)
pub const WIN1H: VolAddress<HorizontalWindowSetting> = unsafe { VolAddress::new(0x400_0042) }; pub const WIN1H: VolAddress<HorizontalWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0042) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -22,10 +24,12 @@ impl HorizontalWindowSetting {
} }
/// Window 0 Vertical Dimensions (W) /// Window 0 Vertical Dimensions (W)
pub const WIN0V: VolAddress<VerticalWindowSetting> = unsafe { VolAddress::new(0x400_0044) }; pub const WIN0V: VolAddress<VerticalWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0044) };
/// Window 1 Vertical Dimensions (W) /// Window 1 Vertical Dimensions (W)
pub const WIN1V: VolAddress<VerticalWindowSetting> = unsafe { VolAddress::new(0x400_0046) }; pub const WIN1V: VolAddress<VerticalWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0046) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -41,7 +45,8 @@ impl VerticalWindowSetting {
} }
/// Control of Inside of Window(s) (R/W) /// Control of Inside of Window(s) (R/W)
pub const WININ: VolAddress<InsideWindowSetting> = unsafe { VolAddress::new(0x400_0048) }; pub const WININ: VolAddress<InsideWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0048) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs
@ -67,7 +72,8 @@ impl InsideWindowSetting {
} }
/// Control of Outside of Windows & Inside of OBJ Window (R/W) /// Control of Outside of Windows & Inside of OBJ Window (R/W)
pub const WINOUT: VolAddress<OutsideWindowSetting> = unsafe { VolAddress::new(0x400_004A) }; pub const WINOUT: VolAddress<OutsideWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_004A) };
newtype! { newtype! {
/// TODO: docs /// TODO: docs

View file

@ -1,8 +1,7 @@
#![cfg_attr(not(test), no_std)] #![cfg_attr(not(test), no_std)]
#![feature(asm, global_asm, isa_attribute)] #![feature(asm, global_asm, isa_attribute)]
#![allow(clippy::cast_lossless)] #![allow(unused_imports)]
#![deny(clippy::float_arithmetic)] //#![warn(missing_docs)]
#![warn(missing_docs)]
//! This crate helps you write GBA ROMs. //! This crate helps you write GBA ROMs.
//! //!
@ -18,12 +17,11 @@
//! do, it's a giant bag of Undefined Behavior. //! do, it's a giant bag of Undefined Behavior.
pub(crate) use gba_proc_macro::phantom_fields; pub(crate) use gba_proc_macro::phantom_fields;
pub(crate) use voladdress::{read_only::ROVolAddress, VolAddress, VolBlock};
use voladdress::*;
pub mod macros; pub mod macros;
pub mod base;
pub mod bios; pub mod bios;
pub mod iwram; pub mod iwram;

View file

@ -2,8 +2,6 @@
use super::*; use super::*;
use typenum::consts::{U128, U32};
newtype! { newtype! {
/// 0th part of an object's attributes. /// 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 /// The object attributes, but there are gaps in the array, so we must not
/// expose this directly. /// 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 // TODO: VolSeries
pub fn write_obj_attributes(slot: usize, attributes: ObjectAttributes) -> Option<()> { 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 /// The object attributes, but there are gaps in the array, so we must not
/// expose this directly. /// 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 // TODO: VolSeries
pub fn write_affine_parameters(slot: usize, params: AffineParameters) -> Option<()> { pub fn write_affine_parameters(slot: usize, params: AffineParameters) -> Option<()> {

View file

@ -25,42 +25,36 @@
use super::*; use super::*;
use typenum::consts::U256;
// TODO: PalIndex newtypes? // TODO: PalIndex newtypes?
/// The `PALRAM` for background colors, 256 slot view. /// The `PALRAM` for background colors, 256 slot view.
pub const PALRAM_BG: VolBlock<Color, U256> = unsafe { VolBlock::new(0x500_0000) }; pub const PALRAM_BG: VolBlock<Color, Safe, Safe, 256> = unsafe { VolBlock::new(0x500_0000) };
/// The `PALRAM` for object colors, 256 slot view. /// The `PALRAM` for object colors, 256 slot view.
pub const PALRAM_OBJ: VolBlock<Color, U256> = unsafe { VolBlock::new(0x500_0200) }; pub const PALRAM_OBJ: VolBlock<Color, Safe, Safe, 256> = unsafe { VolBlock::new(0x500_0200) };
/// Obtains the address of the specified 8bpp background palette slot. /// Obtains the address of the specified 8bpp background palette slot.
pub const fn index_palram_bg_8bpp(slot: u8) -> VolAddress<Color> { pub const fn index_palram_bg_8bpp(slot: u8) -> VolAddress<Color, Safe, Safe> {
// Note(Lokathor): because of the `u8` limit we can't go out of bounds here. PALRAM_BG.index(slot as usize)
unsafe { PALRAM_BG.index_unchecked(slot as usize) }
} }
/// Obtains the address of the specified 8bpp object palette slot. /// Obtains the address of the specified 8bpp object palette slot.
pub const fn index_palram_obj_8bpp(slot: u8) -> VolAddress<Color> { pub const fn index_palram_obj_8bpp(slot: u8) -> VolAddress<Color, Safe, Safe> {
// Note(Lokathor): because of the `u8` limit we can't go out of bounds here. PALRAM_OBJ.index(slot as usize)
unsafe { PALRAM_OBJ.index_unchecked(slot as usize) }
} }
/// Obtains the address of the specified 4bpp background palbank and palslot. /// Obtains the address of the specified 4bpp background palbank and palslot.
/// ///
/// Accesses `palbank * 16 + palslot`, if this is out of bounds the computation /// Accesses `palbank * 16 + palslot`, if this is out of bounds the computation
/// will wrap. /// will wrap.
pub const fn index_palram_bg_4bpp(palbank: u8, palslot: u8) -> VolAddress<Color> { pub const fn index_palram_bg_4bpp(palbank: u8, palslot: u8) -> VolAddress<Color, Safe, Safe> {
// Note(Lokathor): because of the `u8` limit we can't go out of bounds here. PALRAM_BG.index(palbank.wrapping_mul(16).wrapping_add(palslot) as usize)
unsafe { PALRAM_BG.index_unchecked(palbank.wrapping_mul(16).wrapping_add(palslot) as usize) }
} }
/// Obtains the address of the specified 4bpp object palbank and palslot. /// Obtains the address of the specified 4bpp object palbank and palslot.
/// ///
/// Accesses `palbank * 16 + palslot`, if this is out of bounds the computation /// Accesses `palbank * 16 + palslot`, if this is out of bounds the computation
/// will wrap. /// will wrap.
pub const fn index_palram_obj_4bpp(palbank: u8, palslot: u8) -> VolAddress<Color> { pub const fn index_palram_obj_4bpp(palbank: u8, palslot: u8) -> VolAddress<Color, Safe, Safe> {
// Note(Lokathor): because of the `u8` limit we can't go out of bounds here. PALRAM_OBJ.index(palbank.wrapping_mul(16).wrapping_add(palslot) as usize)
unsafe { PALRAM_OBJ.index_unchecked(palbank.wrapping_mul(16).wrapping_add(palslot) as usize) }
} }

View file

@ -9,9 +9,9 @@ use crate::{
sync::with_irqs_disabled, sync::with_irqs_disabled,
}; };
use core::cmp; use core::cmp;
use voladdress::VolAddress; use voladdress::*;
const PORT: VolAddress<u16> = unsafe { VolAddress::new(0x0DFFFF00) }; const PORT: VolAddress<u16, Safe, Safe> = unsafe { VolAddress::new(0x0DFFFF00) };
const SECTOR_SHIFT: usize = 3; const SECTOR_SHIFT: usize = 3;
const SECTOR_LEN: usize = 1 << SECTOR_SHIFT; const SECTOR_LEN: usize = 1 << SECTOR_SHIFT;
const SECTOR_MASK: usize = SECTOR_LEN - 1; const SECTOR_MASK: usize = SECTOR_LEN - 1;
@ -156,32 +156,30 @@ impl EepromProperties {
/// Writes a sector directly. /// Writes a sector directly.
fn write_sector_raw(&self, word: usize, block: &[u8]) -> Result<(), Error> { fn write_sector_raw(&self, word: usize, block: &[u8]) -> Result<(), Error> {
unsafe { // Write sector command. The command is a one bit, followed by a
// Write sector command. The command is a one bit, followed by a // zero bit, followed by the address, followed by 64 bits of data.
// 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 ...]
// 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 ...]
// 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();
let mut buf = BufferData::new(); buf.write_bit(1);
buf.write_bit(1); buf.write_bit(0);
buf.write_bit(0); buf.write_num(self.addr_bits, word as u32);
buf.write_num(self.addr_bits, word as u32); for i in 0..8 {
for i in 0..8 { buf.write_num(8, block[i] as u32);
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(())
} }
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 /// Writes a sector to the EEPROM, keeping any current contents outside the
@ -218,7 +216,7 @@ impl EepromProperties {
let start = offset & SECTOR_MASK; let start = offset & SECTOR_MASK;
let end_len = cmp::min(SECTOR_LEN - start, buf.len()); let end_len = cmp::min(SECTOR_LEN - start, buf.len());
let sector = self.read_sector(offset >> SECTOR_SHIFT); let sector = self.read_sector(offset >> SECTOR_SHIFT);
buf[..end_len].copy_from_slice(&sector[start..start+end_len]); buf[..end_len].copy_from_slice(&sector[start..start + end_len]);
buf = &mut buf[end_len..]; buf = &mut buf[end_len..];
offset += end_len; offset += end_len;
} }

View file

@ -9,14 +9,13 @@ use super::{
}; };
use crate::sync::{with_irqs_disabled, InitOnce, Static}; use crate::sync::{with_irqs_disabled, InitOnce, Static};
use core::cmp; use core::cmp;
use typenum::consts::U65536; use voladdress::*;
use voladdress::{VolAddress, VolBlock};
// Volatile address ports for flash // Volatile address ports for flash
const FLASH_PORT_BANK: VolAddress<u8> = unsafe { VolAddress::new(0x0E000000) }; const FLASH_PORT_BANK: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x0E000000) };
const FLASH_PORT_A: VolAddress<u8> = unsafe { VolAddress::new(0x0E005555) }; const FLASH_PORT_A: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x0E005555) };
const FLASH_PORT_B: VolAddress<u8> = unsafe { VolAddress::new(0x0E002AAA) }; const FLASH_PORT_B: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x0E002AAA) };
const FLASH_DATA: VolBlock<u8, U65536> = unsafe { VolBlock::new(0x0E000000) }; const FLASH_DATA: VolBlock<u8, Safe, Safe, 65536> = unsafe { VolBlock::new(0x0E000000) };
// Various constants related to sector sizes // Various constants related to sector sizes
const BANK_SHIFT: usize = 16; // 64 KiB const BANK_SHIFT: usize = 16; // 64 KiB
@ -133,7 +132,7 @@ struct ChipInfo {
/// The timeout in milliseconds for writes to this chip. /// The timeout in milliseconds for writes to this chip.
write_timeout: u16, 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, erase_sector_timeout: u16,
/// The timeout in milliseconds for erasing the entire chip. /// The timeout in milliseconds for erasing the entire chip.
erase_chip_timeout: u16, erase_chip_timeout: u16,

View file

@ -1,12 +1,12 @@
//! A package containing useful utilities for writing save accessors. This is //! 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 super::Error;
use crate::{ use crate::{
io::timers::*, io::timers::*,
sync::{RawMutex, RawMutexGuard, Static}, sync::{RawMutex, RawMutexGuard, Static},
}; };
use voladdress::VolAddress; use voladdress::*;
/// Internal representation for our active timer. /// Internal representation for our active timer.
#[derive(Copy, Clone, PartialEq)] #[derive(Copy, Clone, PartialEq)]
@ -44,8 +44,8 @@ pub fn disable_timeout() {
pub struct Timeout { pub struct Timeout {
_lock_guard: RawMutexGuard<'static>, _lock_guard: RawMutexGuard<'static>,
active: bool, active: bool,
timer_l: VolAddress<u16>, timer_l: VolAddress<u16, Safe, Safe>,
timer_h: VolAddress<TimerControlSetting>, timer_h: VolAddress<TimerControlSetting, Safe, Safe>,
} }
impl Timeout { impl Timeout {
/// Creates a new timeout from the timer passed to [`set_timer_for_timeout`]. /// Creates a new timeout from the timer passed to [`set_timer_for_timeout`].

View file

@ -29,13 +29,19 @@ pub fn memory_write_hint<T>(val: *mut T) {
} }
/// An internal function used as a temporary hack to get `compiler_fence` /// An internal function used as a temporary hack to get `compiler_fence`
/// working. While this call is not properly inlined, working is better than /// working. While this call is not properly inlined, working is better than not
/// not working at all. /// working at all.
/// ///
/// This seems to be a problem caused by Rust issue #62256: /// This seems to be a problem caused by Rust issue #62256:
/// <https://github.com/rust-lang/rust/issues/62256> /// <https://github.com/rust-lang/rust/issues/62256>
/// ///
/// Not public API, obviously. /// 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)] #[doc(hidden)]
#[deprecated] #[deprecated]
#[allow(dead_code)] #[allow(dead_code)]
@ -49,15 +55,15 @@ pub unsafe extern "C" fn __sync_synchronize() {}
/// for game functionality. /// for game functionality.
pub fn with_irqs_disabled<T>(mut func: impl FnOnce() -> T) -> T { pub fn with_irqs_disabled<T>(mut func: impl FnOnce() -> T) -> T {
let current_ime = IME.read(); 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. // prevents the contents of the function from being reordered before IME is disabled.
memory_write_hint(&mut func); memory_write_hint(&mut func);
let mut result = 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); memory_write_hint(&mut result);
IME.write(current_ime); unsafe { IME.write(current_ime) };
result result
} }

View file

@ -1,15 +1,19 @@
#![cfg_attr(not(target_arch = "arm"), allow(unused_variables))] #![cfg_attr(not(target_arch = "arm"), allow(unused_variables))]
use super::*; use crate::sync::with_irqs_disabled;
use core::{cell::UnsafeCell, mem, mem::MaybeUninit, ptr}; use core::{
cell::UnsafeCell,
mem::{align_of, size_of, MaybeUninit},
ptr,
};
/// The internal function for replacing a `Copy` (really `!Drop`) value in a /// The internal function for replacing a `Copy` (really `!Drop`) value in a
/// [`Static`]. This uses assembly to use an `stmia` instruction to ensure /// [`Static`]. This uses assembly to use an `stmia` instruction to ensure
/// an IRQ cannot occur during the write operation. /// an IRQ cannot occur during the write operation.
#[cfg(target_arch = "arm")] #[cfg(target_arch = "arm")]
unsafe fn transfer<T: Copy>(dst: *mut T, src: *const T) { unsafe fn transfer<T: Copy>(dst: *mut T, src: *const T) {
let align = mem::align_of::<T>(); let align = align_of::<T>();
let size = mem::size_of::<T>(); let size = size_of::<T>();
if size == 0 { if size == 0 {
// Do nothing with ZSTs. Obviously. // Do nothing with ZSTs. Obviously.
} else if size <= 16 && align % 4 == 0 { } else if size <= 16 && align % 4 == 0 {
@ -41,7 +45,7 @@ unsafe fn transfer<T: Copy>(dst: *mut T, src: *const T) {
#[cfg(target_arch = "arm")] #[cfg(target_arch = "arm")]
#[allow(unused_assignments)] #[allow(unused_assignments)]
unsafe fn transfer_align4_thumb<T: Copy>(mut dst: *mut T, mut src: *const T) { unsafe fn transfer_align4_thumb<T: Copy>(mut dst: *mut T, mut src: *const T) {
let size = mem::size_of::<T>(); let size = size_of::<T>();
if size <= 4 { if size <= 4 {
// We use assembly here regardless to just do the word aligned copy. This // We use assembly here regardless to just do the word aligned copy. This
// ensures it's done with a single ldr/str instruction. // ensures it's done with a single ldr/str instruction.
@ -82,7 +86,7 @@ unsafe fn transfer_align4_thumb<T: Copy>(mut dst: *mut T, mut src: *const T) {
#[instruction_set(arm::a32)] #[instruction_set(arm::a32)]
#[allow(unused_assignments)] #[allow(unused_assignments)]
unsafe fn transfer_align4_arm<T: Copy>(mut dst: *mut T, mut src: *const T) { unsafe fn transfer_align4_arm<T: Copy>(mut dst: *mut T, mut src: *const T) {
let size = mem::size_of::<T>(); let size = size_of::<T>();
if size <= 16 { if size <= 16 {
unimplemented!("This should be done via transfer_thumb."); unimplemented!("This should be done via transfer_thumb.");
} else if size <= 20 { } else if size <= 20 {
@ -134,8 +138,8 @@ unsafe fn transfer_align4_arm<T: Copy>(mut dst: *mut T, mut src: *const T) {
/// another value. /// another value.
#[cfg(target_arch = "arm")] #[cfg(target_arch = "arm")]
unsafe fn exchange<T>(dst: *mut T, src: *const T) -> T { unsafe fn exchange<T>(dst: *mut T, src: *const T) -> T {
let align = mem::align_of::<T>(); let align = align_of::<T>();
let size = mem::size_of::<T>(); let size = size_of::<T>();
if size == 0 { if size == 0 {
// Do nothing with ZSTs. // Do nothing with ZSTs.
ptr::read(dst) ptr::read(dst)

View file

@ -15,8 +15,6 @@
pub(crate) use super::*; pub(crate) use super::*;
use typenum::{U1024, consts::{U256, U32, U512, U6}};
pub mod affine; pub mod affine;
pub mod bitmap; pub mod bitmap;
pub mod text; pub mod text;
@ -34,10 +32,11 @@ pub const VRAM_BASE_USIZE: usize = 0x600_0000;
pub const PAGE1_OFFSET: usize = 0xA000; pub const PAGE1_OFFSET: usize = 0xA000;
/// The character base blocks. /// 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. /// 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) }; unsafe { VolBlock::new(VRAM_BASE_USIZE) };
newtype! { newtype! {
@ -53,15 +52,15 @@ newtype! {
} }
/// Gives the specified charblock in 4bpp view. /// Gives the specified charblock in 4bpp view.
pub fn get_4bpp_character_block(slot: usize) -> VolBlock<Tile4bpp, U512> { pub fn get_4bpp_character_block(slot: usize) -> VolBlock<Tile4bpp, Safe, Safe, 512> {
unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).to_usize()) } unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).as_usize()) }
} }
/// Gives the specified charblock in 8bpp view. /// Gives the specified charblock in 8bpp view.
pub fn get_8bpp_character_block(slot: usize) -> VolBlock<Tile8bpp, U256> { pub fn get_8bpp_character_block(slot: usize) -> VolBlock<Tile8bpp, Safe, Safe, 256> {
unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).to_usize()) } unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).as_usize()) }
} }
pub fn get_screen_block(slot: usize) -> VolBlock<TextScreenblockEntry, U1024> { pub fn get_screen_block(slot: usize) -> VolBlock<TextScreenblockEntry, Safe, Safe, 1024> {
unsafe { VolBlock::new(SCREEN_BASE_BLOCKS.index(slot).to_usize()) } unsafe { VolBlock::new(SCREEN_BASE_BLOCKS.index(slot).as_usize()) }
} }

View file

@ -1,8 +1,6 @@
//! Module for the Bitmap video modes. //! Module for the Bitmap video modes.
use super::*; 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. /// A bitmap video mode with full color and full resolution.
/// ///
@ -23,10 +21,10 @@ impl Mode3 {
/// The screen's height in this mode. /// The screen's height in this mode.
pub const HEIGHT: usize = 160; pub const HEIGHT: usize = 160;
const VRAM: VolBlock<Color, <U256 as Mul<U160>>::Output> = const VRAM: VolBlock<Color, Safe, Safe, { 256 * 160 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE) }; unsafe { VolBlock::new(VRAM_BASE_USIZE) };
const WORDS_BLOCK: VolBlock<u32, <<U256 as Mul<U160>>::Output as Div<U2>>::Output> = const WORDS_BLOCK: VolBlock<u32, Safe, Safe, { (256 * 160) / 2 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE) }; unsafe { VolBlock::new(VRAM_BASE_USIZE) };
/// Gets the address of the pixel specified. /// Gets the address of the pixel specified.
@ -34,7 +32,7 @@ impl Mode3 {
/// ## Failure /// ## Failure
/// ///
/// Gives `None` if out of bounds /// Gives `None` if out of bounds
fn get(col: usize, row: usize) -> Option<VolAddress<Color>> { fn get(col: usize, row: usize) -> Option<VolAddress<Color, Safe, Safe>> {
Self::VRAM.get(col + row * Self::WIDTH) Self::VRAM.get(col + row * Self::WIDTH)
} }
@ -44,7 +42,7 @@ impl Mode3 {
/// ///
/// Gives `None` if out of bounds /// Gives `None` if out of bounds
pub fn read(col: usize, row: usize) -> Option<Color> { pub fn read(col: usize, row: usize) -> Option<Color> {
Self::get(col, row).map(VolAddress::read) Self::get(col, row).map(VolAddress::<Color, Safe, Safe>::read)
} }
/// Writes a color to the pixel specified. /// Writes a color to the pixel specified.
@ -164,16 +162,16 @@ impl Mode4 {
/// The screen's height in this mode. /// The screen's height in this mode.
pub const HEIGHT: usize = 160; pub const HEIGHT: usize = 160;
const PAGE0_INDEXES: VolBlock<u8, <U256 as Mul<U160>>::Output> = const PAGE0_INDEXES: VolBlock<u8, Safe, Safe, { 256 * 160 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE) }; unsafe { VolBlock::new(VRAM_BASE_USIZE) };
const PAGE1_INDEXES: VolBlock<u8, <U256 as Mul<U160>>::Output> = const PAGE1_INDEXES: VolBlock<u8, Safe, Safe, { 256 * 160 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) };
const PAGE0_WORDS: VolBlock<u32, <<U256 as Mul<U160>>::Output as Div<U4>>::Output> = const PAGE0_WORDS: VolBlock<u32, Safe, Safe, { (256 * 160) / 4 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE) }; unsafe { VolBlock::new(VRAM_BASE_USIZE) };
const PAGE1_WORDS: VolBlock<u32, <<U256 as Mul<U160>>::Output as Div<U4>>::Output> = const PAGE1_WORDS: VolBlock<u32, Safe, Safe, { (256 * 160) / 4 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) };
/// Reads the color of the pixel specified. /// Reads the color of the pixel specified.
@ -187,7 +185,7 @@ impl Mode4 {
Page::One => Self::PAGE1_INDEXES, Page::One => Self::PAGE1_INDEXES,
} }
.get(col + row * Self::WIDTH) .get(col + row * Self::WIDTH)
.map(VolAddress::read) .map(VolAddress::<u8, Safe, Safe>::read)
} }
/// Writes a color to the pixel specified. /// Writes a color to the pixel specified.
@ -201,12 +199,12 @@ impl Mode4 {
if col < Self::WIDTH && row < Self::HEIGHT { if col < Self::WIDTH && row < Self::HEIGHT {
let real_index = col + row * Self::WIDTH; let real_index = col + row * Self::WIDTH;
let rounded_down_index = real_index & !1; let rounded_down_index = real_index & !1;
let address: VolAddress<u16> = unsafe { let address: VolAddress<u16, Safe, Safe> = unsafe {
match page { match page {
Page::Zero => Self::PAGE0_INDEXES, Page::Zero => Self::PAGE0_INDEXES,
Page::One => Self::PAGE1_INDEXES, Page::One => Self::PAGE1_INDEXES,
} }
.index_unchecked(rounded_down_index) .index(rounded_down_index)
.cast::<u16>() .cast::<u16>()
}; };
if real_index != rounded_down_index { if real_index != rounded_down_index {
@ -247,11 +245,9 @@ impl Mode4 {
let pal8bpp_32 = pal8bpp as u32; let pal8bpp_32 = pal8bpp as u32;
let bulk_color = (pal8bpp_32 << 24) | (pal8bpp_32 << 16) | (pal8bpp_32 << 8) | pal8bpp_32; let bulk_color = (pal8bpp_32 << 24) | (pal8bpp_32 << 16) | (pal8bpp_32 << 8) | pal8bpp_32;
let words_address = unsafe { let words_address = match page {
match page { Page::Zero => Self::PAGE0_WORDS.index(0).as_usize(),
Page::Zero => Self::PAGE0_WORDS.index_unchecked(0).to_usize(), Page::One => Self::PAGE1_WORDS.index(0).as_usize(),
Page::One => Self::PAGE1_WORDS.index_unchecked(0).to_usize(),
}
}; };
unsafe { DMA3::fill32(&bulk_color, words_address as *mut u32, Self::PAGE0_WORDS.len() as u16) }; 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. /// The screen's height in this mode.
pub const HEIGHT: usize = 128; pub const HEIGHT: usize = 128;
const PAGE0_PIXELS: VolBlock<Color, <U160 as Mul<U128>>::Output> = const PAGE0_PIXELS: VolBlock<Color, Safe, Safe, { 160 * 128 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE) }; unsafe { VolBlock::new(VRAM_BASE_USIZE) };
const PAGE1_PIXELS: VolBlock<Color, <U160 as Mul<U128>>::Output> = const PAGE1_PIXELS: VolBlock<Color, Safe, Safe, { 160 * 128 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) };
const PAGE0_WORDS: VolBlock<u32, <<U160 as Mul<U128>>::Output as Div<U2>>::Output> = const PAGE0_WORDS: VolBlock<u32, Safe, Safe, { (160 * 128) / 2 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE) }; unsafe { VolBlock::new(VRAM_BASE_USIZE) };
const PAGE1_WORDS: VolBlock<u32, <<U160 as Mul<U128>>::Output as Div<U2>>::Output> = const PAGE1_WORDS: VolBlock<u32, Safe, Safe, { (160 * 128) / 2 }> =
unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) }; unsafe { VolBlock::new(VRAM_BASE_USIZE + PAGE1_OFFSET) };
/// Reads the color of the pixel specified. /// Reads the color of the pixel specified.
@ -354,7 +350,7 @@ impl Mode5 {
Page::One => Self::PAGE1_PIXELS, Page::One => Self::PAGE1_PIXELS,
} }
.get(col + row * Self::WIDTH) .get(col + row * Self::WIDTH)
.map(VolAddress::read) .map(VolAddress::<Color, Safe, Safe>::read)
} }
/// Writes a color to the pixel specified. /// Writes a color to the pixel specified.
@ -394,11 +390,9 @@ impl Mode5 {
let color32 = color.0 as u32; let color32 = color.0 as u32;
let bulk_color = color32 << 16 | color32; let bulk_color = color32 << 16 | color32;
let words_address = unsafe { let words_address = match page {
match page { Page::Zero => Self::PAGE0_WORDS.index(0).as_usize(),
Page::Zero => Self::PAGE0_WORDS.index_unchecked(0).to_usize(), Page::One => Self::PAGE1_WORDS.index(0).as_usize(),
Page::One => Self::PAGE1_WORDS.index_unchecked(0).to_usize(),
}
}; };
unsafe { DMA3::fill32(&bulk_color, words_address as *mut u32, Self::PAGE0_WORDS.len() as u16) }; unsafe { DMA3::fill32(&bulk_color, words_address as *mut u32, Self::PAGE0_WORDS.len() as u16) };
} }