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"]
[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 }

View file

@ -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)) };
}

View file

@ -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 {}
}

View file

@ -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::<bool, u8>(ignore_current_flags),
in("r1") mem::transmute::<IrqFlags, u16>(target_flags),
in("r0") ignore_current_flags as u8,
in("r1") target_flags.0,
);
}
}

View file

@ -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 {}
}

View file

@ -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<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_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;
// 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() {

View file

@ -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<u8> = unsafe { VolAddress::new(0x04FFFA1C) };
const SIGNATURE_ADDR: VolBlock<u8, U16> = unsafe { VolBlock::new(0x04FFFA00) };
const CHAR_OUT: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x04FFFA1C) };
const SIGNATURE_ADDR: VolBlock<u8, Safe, Safe, 16> = unsafe { VolBlock::new(0x04FFFA00) };
const SIGNATURE: [u8; 7] = *b"no$gba ";
static NO_CASH_DEBUGGING: InitOnce<bool> = InitOnce::new();

View file

@ -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.

View file

@ -3,13 +3,17 @@
use super::*;
/// 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.
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.
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.
pub const BG3CNT: VolAddress<BackgroundControlSetting> = unsafe { VolAddress::new(0x400_000E) };
pub const BG3CNT: VolAddress<BackgroundControlSetting, Safe, Safe> =
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<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.
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.
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.
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.
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.
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.
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.
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
// BG2X_L

View file

@ -3,7 +3,8 @@
use super::*;
/// 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! {
/// TODO: docs
@ -43,7 +44,8 @@ newtype_enum! {
}
/// 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! {
/// TODO: docs
@ -59,7 +61,7 @@ impl AlphaBlendingSetting {
}
/// 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! {
/// TODO: docs

View file

@ -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<DisplayControlSetting> = unsafe { VolAddress::new(0x400_0000) };
pub const DISPCNT: VolAddress<DisplayControlSetting, Safe, Safe> =
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<DisplayStatusSetting> = unsafe { VolAddress::new(0x400_0004) };
pub const DISPSTAT: VolAddress<DisplayStatusSetting, Safe, Safe> =
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<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.
pub const VBLANK_SCANLINE: u16 = 160;
/// 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! {
/// Allows control of the Mosaic effect.

View file

@ -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<u16> = unsafe { VolAddress::new(0x400_00B8) };
const DMA0CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00B8) };
/// 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.
///
@ -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<u16> = unsafe { VolAddress::new(0x400_00C4) };
const DMA1CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00C4) };
/// 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.
///
@ -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<u16> = unsafe { VolAddress::new(0x400_00D0) };
const DMA2CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00D0) };
/// 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.
///
@ -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<u16> = unsafe { VolAddress::new(0x400_00DC) };
const DMA3CNT_L: VolAddress<u16, Safe, Unsafe> = unsafe { VolAddress::new(0x400_00DC) };
/// 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.
///

View file

@ -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<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.
///
@ -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
/// handler must write a `1` bit to all bits that are enabled on this register
/// 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! {
/// Setting to control whether interrupts are enabled.
@ -161,7 +161,7 @@ impl IrqEnableSetting {
}
/// 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.
///
@ -169,7 +169,7 @@ pub const IME: VolAddress<IrqEnableSetting> = 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<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.
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
/// 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<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.
#[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<KeyInterruptSetting> = unsafe { VolAddress::new(0x400_0132) };
pub const KEYCNT: VolAddress<KeyInterruptSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0132) };
newtype! {
/// Allows configuration of when a keypad interrupt fires.

View file

@ -3,13 +3,14 @@
use super::*;
/// 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.
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.
pub const RCNT: VolAddress<IoControlSetting> = unsafe { VolAddress::new(0x400_0134) };
pub const RCNT: VolAddress<IoControlSetting, Safe, Safe> = 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;

View file

@ -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<SweepRegisterSetting> = unsafe { VolAddress::new(0x400_0060) };
pub const SOUND1CNT_L: VolAddress<SweepRegisterSetting, Safe, Safe> =
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<DutyLenEnvelopeSetting> = unsafe { VolAddress::new(0x400_0062) };
pub const SOUND1CNT_H: VolAddress<DutyLenEnvelopeSetting, Safe, Safe> =
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<FrequencyControlSetting> = unsafe { VolAddress::new(0x400_0064) };
pub const SOUND1CNT_X: VolAddress<FrequencyControlSetting, Safe, Safe> =
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<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.
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.
pub const SOUND3CNT_L: VolAddress<StopWaveRAMSelectSetting> =
pub const SOUND3CNT_L: VolAddress<StopWaveRAMSelectSetting, Safe, Safe> =
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<LengthVolumeSetting> = unsafe { VolAddress::new(0x400_0072) };
pub const SOUND3CNT_H: VolAddress<LengthVolumeSetting, Safe, Safe> =
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<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)
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)
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)
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)
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)
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)
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)
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)
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.
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! {
/// TODO: docs
@ -137,7 +145,8 @@ impl LengthEnvelopeSetting {
}
/// 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! {
/// 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<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)
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)
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)
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.
pub const SOUNDCNT_L: VolAddress<NonWaveVolumeEnableSetting> =
pub const SOUNDCNT_L: VolAddress<NonWaveVolumeEnableSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0080) };
newtype! {
@ -186,7 +195,8 @@ impl NonWaveVolumeEnableSetting {
}
/// 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! {
/// TODO: docs
@ -222,7 +232,8 @@ newtype_enum! {
}
/// 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! {
/// TODO: docs
@ -241,7 +252,8 @@ impl SoundMasterSetting {
}
/// 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! {
/// TODO: docs

View file

@ -28,28 +28,32 @@ use super::*;
// TODO: striding blocks?
/// 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).
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).
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).
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.
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.
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.
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.
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! {
/// Allows control of a timer unit.

View file

@ -3,10 +3,12 @@
use super::*;
/// 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)
pub const WIN1H: VolAddress<HorizontalWindowSetting> = unsafe { VolAddress::new(0x400_0042) };
pub const WIN1H: VolAddress<HorizontalWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_0042) };
newtype! {
/// TODO: docs
@ -22,10 +24,12 @@ impl HorizontalWindowSetting {
}
/// 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)
pub const WIN1V: VolAddress<VerticalWindowSetting> = unsafe { VolAddress::new(0x400_0046) };
pub const WIN1V: VolAddress<VerticalWindowSetting, Safe, Safe> =
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<InsideWindowSetting> = unsafe { VolAddress::new(0x400_0048) };
pub const WININ: VolAddress<InsideWindowSetting, Safe, Safe> =
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<OutsideWindowSetting> = unsafe { VolAddress::new(0x400_004A) };
pub const WINOUT: VolAddress<OutsideWindowSetting, Safe, Safe> =
unsafe { VolAddress::new(0x400_004A) };
newtype! {
/// TODO: docs

View file

@ -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;

View file

@ -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<()> {

View file

@ -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<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.
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.
pub const fn index_palram_bg_8bpp(slot: u8) -> VolAddress<Color> {
// 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<Color, Safe, Safe> {
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<Color> {
// 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<Color, Safe, Safe> {
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<Color> {
// 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<Color, Safe, Safe> {
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<Color> {
// 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<Color, Safe, Safe> {
PALRAM_OBJ.index(palbank.wrapping_mul(16).wrapping_add(palslot) as usize)
}

View file

@ -9,9 +9,9 @@ use crate::{
sync::with_irqs_disabled,
};
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_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(&sector[start..start+end_len]);
buf[..end_len].copy_from_slice(&sector[start..start + end_len]);
buf = &mut buf[end_len..];
offset += end_len;
}

View file

@ -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<u8> = unsafe { VolAddress::new(0x0E000000) };
const FLASH_PORT_A: VolAddress<u8> = unsafe { VolAddress::new(0x0E005555) };
const FLASH_PORT_B: VolAddress<u8> = unsafe { VolAddress::new(0x0E002AAA) };
const FLASH_DATA: VolBlock<u8, U65536> = unsafe { VolBlock::new(0x0E000000) };
const FLASH_PORT_BANK: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x0E000000) };
const FLASH_PORT_A: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x0E005555) };
const FLASH_PORT_B: VolAddress<u8, Safe, Safe> = unsafe { VolAddress::new(0x0E002AAA) };
const FLASH_DATA: VolBlock<u8, Safe, Safe, 65536> = 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,

View file

@ -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<u16>,
timer_h: VolAddress<TimerControlSetting>,
timer_l: VolAddress<u16, Safe, Safe>,
timer_h: VolAddress<TimerControlSetting, Safe, Safe>,
}
impl 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`
/// 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:
/// <https://github.com/rust-lang/rust/issues/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<T>(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
}

View file

@ -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<T: Copy>(dst: *mut T, src: *const T) {
let align = mem::align_of::<T>();
let size = mem::size_of::<T>();
let align = align_of::<T>();
let size = size_of::<T>();
if size == 0 {
// Do nothing with ZSTs. Obviously.
} 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")]
#[allow(unused_assignments)]
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 {
// 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<T: Copy>(mut dst: *mut T, mut src: *const T) {
#[instruction_set(arm::a32)]
#[allow(unused_assignments)]
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 {
unimplemented!("This should be done via transfer_thumb.");
} 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.
#[cfg(target_arch = "arm")]
unsafe fn exchange<T>(dst: *mut T, src: *const T) -> T {
let align = mem::align_of::<T>();
let size = mem::size_of::<T>();
let align = align_of::<T>();
let size = size_of::<T>();
if size == 0 {
// Do nothing with ZSTs.
ptr::read(dst)

View file

@ -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<Tile4bpp, U512> {
unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).to_usize()) }
pub fn get_4bpp_character_block(slot: usize) -> VolBlock<Tile4bpp, Safe, Safe, 512> {
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<Tile8bpp, U256> {
unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).to_usize()) }
pub fn get_8bpp_character_block(slot: usize) -> VolBlock<Tile8bpp, Safe, Safe, 256> {
unsafe { VolBlock::new(CHAR_BASE_BLOCKS.index(slot).as_usize()) }
}
pub fn get_screen_block(slot: usize) -> VolBlock<TextScreenblockEntry, U1024> {
unsafe { VolBlock::new(SCREEN_BASE_BLOCKS.index(slot).to_usize()) }
}
pub fn get_screen_block(slot: usize) -> VolBlock<TextScreenblockEntry, Safe, Safe, 1024> {
unsafe { VolBlock::new(SCREEN_BASE_BLOCKS.index(slot).as_usize()) }
}

View file

@ -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<Color, <U256 as Mul<U160>>::Output> =
const VRAM: VolBlock<Color, Safe, Safe, { 256 * 160 }> =
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) };
/// 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<VolAddress<Color>> {
fn get(col: usize, row: usize) -> Option<VolAddress<Color, Safe, Safe>> {
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<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.
@ -164,16 +162,16 @@ impl Mode4 {
/// The screen's height in this mode.
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) };
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) };
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) };
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) };
/// 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::<u8, Safe, Safe>::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<u16> = unsafe {
let address: VolAddress<u16, Safe, Safe> = unsafe {
match page {
Page::Zero => Self::PAGE0_INDEXES,
Page::One => Self::PAGE1_INDEXES,
}
.index_unchecked(rounded_down_index)
.index(rounded_down_index)
.cast::<u16>()
};
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<Color, <U160 as Mul<U128>>::Output> =
const PAGE0_PIXELS: VolBlock<Color, Safe, Safe, { 160 * 128 }> =
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) };
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) };
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) };
/// 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::<Color, Safe, Safe>::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) };
}