mirror of
https://github.com/italicsjenga/gba.git
synced 2024-12-23 19:01:30 +11:00
io register groundwork
the current goal is to get enough done that we can write a sensical looking hello world game, and then put a writeup of that into the book.
This commit is contained in:
parent
c99a85bf39
commit
e9b26f838b
40
src/core_extras.rs
Normal file
40
src/core_extras.rs
Normal file
|
@ -0,0 +1,40 @@
|
|||
//! Things that I wish were in core, but aren't.
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[repr(transparent)]
|
||||
/// A simple wrapper to any `*mut T` so that the basic "read" and "write"
|
||||
/// operations are volatile.
|
||||
///
|
||||
/// Accessing the GBA's IO registers and video ram and specific other places on
|
||||
/// **must** be done with volatile operations. Having this wrapper makes that
|
||||
/// more clear for all the global const values into IO registers.
|
||||
pub struct VolatilePtr<T>(pub *mut T);
|
||||
|
||||
impl<T> core::fmt::Pointer for VolatilePtr<T> {
|
||||
/// Formats exactly like the inner `*mut T`.
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||
write!(f, "{:p}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> VolatilePtr<T> {
|
||||
/// Performs a volatile read.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This method adds absolutely no additional safety, so all safety concerns
|
||||
/// for a normal raw pointer volatile read apply.
|
||||
pub unsafe fn read(&self) -> T {
|
||||
core::ptr::read_volatile(self.0)
|
||||
}
|
||||
|
||||
/// Performs a volatile write.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This method adds absolutely no additional safety, so all safety concerns
|
||||
/// for a normal raw pointer volatile write apply.
|
||||
pub unsafe fn write(&self, data: T) {
|
||||
core::ptr::write_volatile(self.0, data);
|
||||
}
|
||||
}
|
341
src/io_registers.rs
Normal file
341
src/io_registers.rs
Normal file
|
@ -0,0 +1,341 @@
|
|||
//! The module for all things relating to the IO Register portion of the GBA's
|
||||
//! memory map.
|
||||
//!
|
||||
//! Here we define many constants for the volatile pointers to the various IO
|
||||
//! registers. Each raw register constant is named according to the name given
|
||||
//! to it in GBATEK's [GBA I/O
|
||||
//! Map](http://problemkaputt.de/gbatek.htm#gbaiomap). They program in C, and so
|
||||
//! of course all the names terrible and missing as many vowels as possible.
|
||||
//! However, being able to look it up online is the most important thing here,
|
||||
//! so oh well.
|
||||
//!
|
||||
//! In addition to the const `VolatilePtr` values, we will over time be adding
|
||||
//! safe wrappers around each register, including newtypes and such so that you
|
||||
//! can easily work with whatever each specific register is doing.
|
||||
|
||||
// TODO(lokathor): IO Register newtypes.
|
||||
|
||||
use super::*;
|
||||
|
||||
/// LCD Control. Read/Write.
|
||||
///
|
||||
/// * [gbatek entry](http://problemkaputt.de/gbatek.htm#lcdiodisplaycontrol)
|
||||
pub const DISPCNT: VolatilePtr<u16> = VolatilePtr(0x4000000 as *mut u16);
|
||||
|
||||
/// Undocumented - Green Swap
|
||||
pub const GREEN_SWAP: VolatilePtr<u16> = VolatilePtr(0x4000002 as *mut u16);
|
||||
|
||||
/// General LCD Status (STAT,LYC)
|
||||
pub const DISPSTAT: VolatilePtr<u16> = VolatilePtr(0x4000004 as *mut u16);
|
||||
|
||||
/// Vertical Counter (LY)
|
||||
pub const VCOUNT: VolatilePtr<u16> = VolatilePtr(0x4000006 as *mut u16);
|
||||
|
||||
/// BG0 Control
|
||||
pub const BG0CNT: VolatilePtr<u16> = VolatilePtr(0x4000008 as *mut u16);
|
||||
|
||||
/// BG1 Control
|
||||
pub const BG1CNT: VolatilePtr<u16> = VolatilePtr(0x400000A as *mut u16);
|
||||
|
||||
/// BG2 Control
|
||||
pub const BG2CNT: VolatilePtr<u16> = VolatilePtr(0x400000C as *mut u16);
|
||||
|
||||
/// BG3 Control
|
||||
pub const BG3CNT: VolatilePtr<u16> = VolatilePtr(0x400000E as *mut u16);
|
||||
|
||||
/// BG0 X-Offset
|
||||
pub const BG0HOFS: VolatilePtr<u16> = VolatilePtr(0x4000010 as *mut u16);
|
||||
|
||||
/// BG0 Y-Offset
|
||||
pub const BG0VOFS: VolatilePtr<u16> = VolatilePtr(0x4000012 as *mut u16);
|
||||
|
||||
/// BG1 X-Offset
|
||||
pub const BG1HOFS: VolatilePtr<u16> = VolatilePtr(0x4000014 as *mut u16);
|
||||
|
||||
/// BG1 Y-Offset
|
||||
pub const BG1VOFS: VolatilePtr<u16> = VolatilePtr(0x4000016 as *mut u16);
|
||||
|
||||
/// BG2 X-Offset
|
||||
pub const BG2HOFS: VolatilePtr<u16> = VolatilePtr(0x4000018 as *mut u16);
|
||||
|
||||
/// BG2 Y-Offset
|
||||
pub const BG2VOFS: VolatilePtr<u16> = VolatilePtr(0x400001A as *mut u16);
|
||||
|
||||
/// BG3 X-Offset
|
||||
pub const BG3HOFS: VolatilePtr<u16> = VolatilePtr(0x400001C as *mut u16);
|
||||
|
||||
/// BG3 Y-Offset
|
||||
pub const BG3VOFS: VolatilePtr<u16> = VolatilePtr(0x400001E as *mut u16);
|
||||
|
||||
/// BG2 Rotation/Scaling Parameter A (dx)
|
||||
pub const BG2PA: VolatilePtr<u16> = VolatilePtr(0x4000020 as *mut u16);
|
||||
|
||||
/// BG2 Rotation/Scaling Parameter B (dmx)
|
||||
pub const BG2PB: VolatilePtr<u16> = VolatilePtr(0x4000022 as *mut u16);
|
||||
|
||||
/// BG2 Rotation/Scaling Parameter C (dy)
|
||||
pub const BG2PC: VolatilePtr<u16> = VolatilePtr(0x4000024 as *mut u16);
|
||||
|
||||
/// BG2 Rotation/Scaling Parameter D (dmy)
|
||||
pub const BG2PD: VolatilePtr<u16> = VolatilePtr(0x4000026 as *mut u16);
|
||||
|
||||
/// BG2 Reference Point X-Coordinate
|
||||
pub const BG2X: VolatilePtr<u32> = VolatilePtr(0x4000028 as *mut u32);
|
||||
|
||||
/// BG2 Reference Point Y-Coordinate
|
||||
pub const BG2Y: VolatilePtr<u32> = VolatilePtr(0x400002C as *mut u32);
|
||||
|
||||
/// BG3 Rotation/Scaling Parameter A (dx)
|
||||
pub const BG3PA: VolatilePtr<u16> = VolatilePtr(0x4000030 as *mut u16);
|
||||
|
||||
/// BG3 Rotation/Scaling Parameter B (dmx)
|
||||
pub const BG3PB: VolatilePtr<u16> = VolatilePtr(0x4000032 as *mut u16);
|
||||
|
||||
/// BG3 Rotation/Scaling Parameter C (dy)
|
||||
pub const BG3PC: VolatilePtr<u16> = VolatilePtr(0x4000034 as *mut u16);
|
||||
|
||||
/// BG3 Rotation/Scaling Parameter D (dmy)
|
||||
pub const BG3PD: VolatilePtr<u16> = VolatilePtr(0x4000036 as *mut u16);
|
||||
|
||||
/// BG3 Reference Point X-Coordinate
|
||||
pub const BG3X: VolatilePtr<u32> = VolatilePtr(0x4000038 as *mut u32);
|
||||
|
||||
/// BG3 Reference Point Y-Coordinate
|
||||
pub const BG3Y: VolatilePtr<u32> = VolatilePtr(0x400003C as *mut u32);
|
||||
|
||||
/// Window 0 Horizontal Dimensions
|
||||
pub const WIN0H: VolatilePtr<u16> = VolatilePtr(0x4000040 as *mut u16);
|
||||
|
||||
/// Window 1 Horizontal Dimensions
|
||||
pub const WIN1H: VolatilePtr<u16> = VolatilePtr(0x4000042 as *mut u16);
|
||||
|
||||
/// Window 0 Vertical Dimensions
|
||||
pub const WIN0V: VolatilePtr<u16> = VolatilePtr(0x4000044 as *mut u16);
|
||||
|
||||
/// Window 1 Vertical Dimensions
|
||||
pub const WIN1V: VolatilePtr<u16> = VolatilePtr(0x4000046 as *mut u16);
|
||||
|
||||
/// Inside of Window 0 and 1
|
||||
pub const WININ: VolatilePtr<u16> = VolatilePtr(0x4000048 as *mut u16);
|
||||
|
||||
/// Inside of OBJ Window & Outside of Windows
|
||||
pub const WINOUT: VolatilePtr<u16> = VolatilePtr(0x400004A as *mut u16);
|
||||
|
||||
/// Mosaic Size
|
||||
pub const MOSAIC: VolatilePtr<u16> = VolatilePtr(0x400004C as *mut u16);
|
||||
|
||||
/// Color Special Effects Selection
|
||||
pub const BLDCNT: VolatilePtr<u16> = VolatilePtr(0x4000050 as *mut u16);
|
||||
|
||||
/// Alpha Blending Coefficients
|
||||
pub const BLDALPHA: VolatilePtr<u16> = VolatilePtr(0x4000052 as *mut u16);
|
||||
|
||||
/// Brightness (Fade-In/Out) Coefficient
|
||||
pub const BLDY: VolatilePtr<u16> = VolatilePtr(0x4000054 as *mut u16);
|
||||
|
||||
/// Channel 1 Sweep register (NR10)
|
||||
pub const UND1CNT_L: VolatilePtr<u16> = VolatilePtr(0x4000060 as *mut u16);
|
||||
|
||||
/// Channel 1 Duty/Length/Envelope (NR11, NR12)
|
||||
pub const UND1CNT_H: VolatilePtr<u16> = VolatilePtr(0x4000062 as *mut u16);
|
||||
|
||||
/// Channel 1 Frequency/Control (NR13, NR14)
|
||||
pub const UND1CNT_X: VolatilePtr<u16> = VolatilePtr(0x4000064 as *mut u16);
|
||||
|
||||
/// Channel 2 Duty/Length/Envelope (NR21, NR22)
|
||||
pub const UND2CNT_L: VolatilePtr<u16> = VolatilePtr(0x4000068 as *mut u16);
|
||||
|
||||
/// Channel 2 Frequency/Control (NR23, NR24)
|
||||
pub const UND2CNT_H: VolatilePtr<u16> = VolatilePtr(0x400006C as *mut u16);
|
||||
|
||||
/// Channel 3 Stop/Wave RAM select (NR30)
|
||||
pub const UND3CNT_L: VolatilePtr<u16> = VolatilePtr(0x4000070 as *mut u16);
|
||||
|
||||
/// Channel 3 Length/Volume (NR31, NR32)
|
||||
pub const UND3CNT_H: VolatilePtr<u16> = VolatilePtr(0x4000072 as *mut u16);
|
||||
|
||||
/// Channel 3 Frequency/Control (NR33, NR34)
|
||||
pub const UND3CNT_X: VolatilePtr<u16> = VolatilePtr(0x4000074 as *mut u16);
|
||||
|
||||
/// Channel 4 Length/Envelope (NR41, NR42)
|
||||
pub const UND4CNT_L: VolatilePtr<u16> = VolatilePtr(0x4000078 as *mut u16);
|
||||
|
||||
/// Channel 4 Frequency/Control (NR43, NR44)
|
||||
pub const UND4CNT_H: VolatilePtr<u16> = VolatilePtr(0x400007C as *mut u16);
|
||||
|
||||
/// Control Stereo/Volume/Enable (NR50, NR51)
|
||||
pub const UNDCNT_L: VolatilePtr<u16> = VolatilePtr(0x4000080 as *mut u16);
|
||||
|
||||
/// Control Mixing/DMA Control
|
||||
pub const UNDCNT_H: VolatilePtr<u16> = VolatilePtr(0x4000082 as *mut u16);
|
||||
|
||||
/// Control Sound on/off (NR52)
|
||||
pub const UNDCNT_X: VolatilePtr<u16> = VolatilePtr(0x4000084 as *mut u16);
|
||||
|
||||
/// Sound PWM Control
|
||||
pub const UNDBIAS: VolatilePtr<u16> = VolatilePtr(0x4000088 as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM0_L: VolatilePtr<u16> = VolatilePtr(0x4000090 as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM0_H: VolatilePtr<u16> = VolatilePtr(0x4000092 as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM1_L: VolatilePtr<u16> = VolatilePtr(0x4000094 as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM1_H: VolatilePtr<u16> = VolatilePtr(0x4000096 as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM2_L: VolatilePtr<u16> = VolatilePtr(0x4000098 as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM2_H: VolatilePtr<u16> = VolatilePtr(0x400009A as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM3_L: VolatilePtr<u16> = VolatilePtr(0x400009C as *mut u16);
|
||||
|
||||
/// Channel 3 Wave Pattern RAM (W/R)
|
||||
pub const WAVE_RAM3_H: VolatilePtr<u16> = VolatilePtr(0x400009E as *mut u16);
|
||||
|
||||
/// Channel A FIFO, Data 0-3
|
||||
pub const FIFO_A: VolatilePtr<u32> = VolatilePtr(0x40000A0 as *mut u32);
|
||||
|
||||
/// Channel B FIFO, Data 0-3
|
||||
pub const FIFO_B: VolatilePtr<u32> = VolatilePtr(0x40000A4 as *mut u32);
|
||||
|
||||
/// DMA 0 Source Address
|
||||
pub const DMA0SAD: VolatilePtr<u32> = VolatilePtr(0x40000B0 as *mut u32);
|
||||
|
||||
/// DMA 0 Destination Address
|
||||
pub const DMA0DAD: VolatilePtr<u32> = VolatilePtr(0x40000B4 as *mut u32);
|
||||
|
||||
/// DMA 0 Word Count
|
||||
pub const DMA0CNT_L: VolatilePtr<u16> = VolatilePtr(0x40000B8 as *mut u16);
|
||||
|
||||
/// DMA 0 Control
|
||||
pub const DMA0CNT_H: VolatilePtr<u16> = VolatilePtr(0x40000BA as *mut u16);
|
||||
|
||||
/// DMA 1 Source Address
|
||||
pub const DMA1SAD: VolatilePtr<u32> = VolatilePtr(0x40000BC as *mut u32);
|
||||
|
||||
/// DMA 1 Destination Address
|
||||
pub const DMA1DAD: VolatilePtr<u32> = VolatilePtr(0x40000C0 as *mut u32);
|
||||
|
||||
/// DMA 1 Word Count
|
||||
pub const DMA1CNT_L: VolatilePtr<u16> = VolatilePtr(0x40000C4 as *mut u16);
|
||||
|
||||
/// DMA 1 Control
|
||||
pub const DMA1CNT_H: VolatilePtr<u16> = VolatilePtr(0x40000C6 as *mut u16);
|
||||
|
||||
/// DMA 2 Source Address
|
||||
pub const DMA2SAD: VolatilePtr<u32> = VolatilePtr(0x40000C8 as *mut u32);
|
||||
|
||||
/// DMA 2 Destination Address
|
||||
pub const DMA2DAD: VolatilePtr<u32> = VolatilePtr(0x40000CC as *mut u32);
|
||||
|
||||
/// DMA 2 Word Count
|
||||
pub const DMA2CNT_L: VolatilePtr<u16> = VolatilePtr(0x40000D0 as *mut u16);
|
||||
|
||||
/// DMA 2 Control
|
||||
pub const DMA2CNT_H: VolatilePtr<u16> = VolatilePtr(0x40000D2 as *mut u16);
|
||||
|
||||
/// DMA 3 Source Address
|
||||
pub const DMA3SAD: VolatilePtr<u32> = VolatilePtr(0x40000D4 as *mut u32);
|
||||
|
||||
/// DMA 3 Destination Address
|
||||
pub const DMA3DAD: VolatilePtr<u32> = VolatilePtr(0x40000D8 as *mut u32);
|
||||
|
||||
/// DMA 3 Word Count
|
||||
pub const DMA3CNT_L: VolatilePtr<u16> = VolatilePtr(0x40000DC as *mut u16);
|
||||
|
||||
/// DMA 3 Control
|
||||
pub const DMA3CNT_H: VolatilePtr<u16> = VolatilePtr(0x40000DE as *mut u16);
|
||||
|
||||
/// Timer 0 Counter/Reload
|
||||
pub const TM0CNT_L: VolatilePtr<u16> = VolatilePtr(0x4000100 as *mut u16);
|
||||
|
||||
/// Timer 0 Control
|
||||
pub const TM0CNT_H: VolatilePtr<u16> = VolatilePtr(0x4000102 as *mut u16);
|
||||
|
||||
/// Timer 1 Counter/Reload
|
||||
pub const TM1CNT_L: VolatilePtr<u16> = VolatilePtr(0x4000104 as *mut u16);
|
||||
|
||||
/// Timer 1 Control
|
||||
pub const TM1CNT_H: VolatilePtr<u16> = VolatilePtr(0x4000106 as *mut u16);
|
||||
|
||||
/// Timer 2 Counter/Reload
|
||||
pub const TM2CNT_L: VolatilePtr<u16> = VolatilePtr(0x4000108 as *mut u16);
|
||||
|
||||
/// Timer 2 Control
|
||||
pub const TM2CNT_H: VolatilePtr<u16> = VolatilePtr(0x400010A as *mut u16);
|
||||
|
||||
/// Timer 3 Counter/Reload
|
||||
pub const TM3CNT_L: VolatilePtr<u16> = VolatilePtr(0x400010C as *mut u16);
|
||||
|
||||
/// Timer 3 Control
|
||||
pub const TM3CNT_H: VolatilePtr<u16> = VolatilePtr(0x400010E as *mut u16);
|
||||
|
||||
/// SIO Data (Normal-32bit Mode; shared with below)
|
||||
pub const SIODATA32: VolatilePtr<u32> = VolatilePtr(0x4000120 as *mut u32);
|
||||
|
||||
/// SIO Data 0 (Parent) (Multi-Player Mode)
|
||||
pub const SIOMULTI0: VolatilePtr<u16> = VolatilePtr(0x4000120 as *mut u16);
|
||||
|
||||
/// SIO Data 1 (1st Child) (Multi-Player Mode)
|
||||
pub const SIOMULTI1: VolatilePtr<u16> = VolatilePtr(0x4000122 as *mut u16);
|
||||
|
||||
/// SIO Data 2 (2nd Child) (Multi-Player Mode)
|
||||
pub const SIOMULTI2: VolatilePtr<u16> = VolatilePtr(0x4000124 as *mut u16);
|
||||
|
||||
/// SIO Data 3 (3rd Child) (Multi-Player Mode)
|
||||
pub const SIOMULTI3: VolatilePtr<u16> = VolatilePtr(0x4000126 as *mut u16);
|
||||
|
||||
/// SIO Control Register
|
||||
pub const SIOCNT: VolatilePtr<u16> = VolatilePtr(0x4000128 as *mut u16);
|
||||
|
||||
/// D SIO Data (Local of MultiPlayer; shared below)
|
||||
pub const SIOMLT_SEN: VolatilePtr<u16> = VolatilePtr(0x400012A as *mut u16);
|
||||
|
||||
/// SIO Data (Normal-8bit and UART Mode)
|
||||
pub const SIODATA8: VolatilePtr<u16> = VolatilePtr(0x400012A as *mut u16);
|
||||
|
||||
/// Key Status
|
||||
pub const KEYINPUT: VolatilePtr<u16> = VolatilePtr(0x4000130 as *mut u16);
|
||||
|
||||
/// Key Interrupt Control
|
||||
pub const KEYCNT: VolatilePtr<u16> = VolatilePtr(0x4000132 as *mut u16);
|
||||
|
||||
/// SIO Mode Select/General Purpose Data
|
||||
pub const RCNT: VolatilePtr<u16> = VolatilePtr(0x4000134 as *mut u16);
|
||||
|
||||
/// SIO JOY Bus Control
|
||||
pub const JOYCNT: VolatilePtr<u16> = VolatilePtr(0x4000140 as *mut u16);
|
||||
|
||||
/// SIO JOY Bus Receive Data
|
||||
pub const JOY_RECV: VolatilePtr<u32> = VolatilePtr(0x4000150 as *mut u32);
|
||||
|
||||
/// SIO JOY Bus Transmit Data
|
||||
pub const JOY_TRANS: VolatilePtr<u32> = VolatilePtr(0x4000154 as *mut u32);
|
||||
|
||||
/// SIO JOY Bus Receive Status
|
||||
pub const JOYSTAT: VolatilePtr<u16> = VolatilePtr(0x4000158 as *mut u16);
|
||||
|
||||
/// Interrupt Enable Register
|
||||
pub const IE: VolatilePtr<u16> = VolatilePtr(0x4000200 as *mut u16);
|
||||
|
||||
/// Interrupt Request Flags / IRQ Acknowledge
|
||||
pub const IF: VolatilePtr<u16> = VolatilePtr(0x4000202 as *mut u16);
|
||||
|
||||
/// Game Pak Waitstate Control
|
||||
pub const WAITCNT: VolatilePtr<u16> = VolatilePtr(0x4000204 as *mut u16);
|
||||
|
||||
/// Interrupt Master Enable Register
|
||||
pub const IME: VolatilePtr<u16> = VolatilePtr(0x4000208 as *mut u16);
|
||||
|
||||
/// Undocumented - Post Boot Flag
|
||||
pub const POSTFLG: VolatilePtr<u8> = VolatilePtr(0x4000300 as *mut u8);
|
||||
|
||||
/// Undocumented - Power Down Control
|
||||
pub const HALTCNT: VolatilePtr<u8> = VolatilePtr(0x4000301 as *mut u8);
|
22
src/lib.rs
22
src/lib.rs
|
@ -1 +1,23 @@
|
|||
#![no_std]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
//! This crate helps you write GBA ROMs.
|
||||
//!
|
||||
//! # SAFETY POLICY
|
||||
//!
|
||||
//! Some parts of this crate are safe wrappers around unsafe operations. This is
|
||||
//! good, and what you'd expect from a Rust crate.
|
||||
//!
|
||||
//! However, the safe wrappers all assume that you will _only_ attempt to
|
||||
//! execute this crate on a GBA or in a GBA Emulator.
|
||||
//!
|
||||
//! **Do not** use this crate in programs that aren't running on the GBA. If you
|
||||
//! do, it's a giant bag of Undefined Behavior.
|
||||
|
||||
//pub mod macros; // un-comment once we get some
|
||||
|
||||
pub mod core_extras;
|
||||
pub(crate) use crate::core_extras::*;
|
||||
|
||||
pub mod io_registers;
|
||||
//pub(crate) use crate::io_registers::*;
|
||||
|
|
6
src/macros.rs
Normal file
6
src/macros.rs
Normal file
|
@ -0,0 +1,6 @@
|
|||
//! Module for all macros.
|
||||
//!
|
||||
//! Macros are the only thing in rust where declaration order matters, so we
|
||||
//! place all of them here regardless of what they do.
|
||||
|
||||
// no macros yet!
|
Loading…
Reference in a new issue