Merge branch 'agbrs:master' into master

This commit is contained in:
Alex Janka 2023-04-10 09:54:07 +10:00 committed by GitHub
commit c7591a3e37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
63 changed files with 1343 additions and 631 deletions

View file

@ -10,10 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Made Vector2D::new a const function. - Made Vector2D::new a const function.
- The template now uses rust 2021 edition by default. - The template now uses rust 2021 edition by default.
- All objects which should only be created once now have the correct lifetimes to only allow one to exist. - All objects which should only be created once now have the correct lifetimes to only allow one to exist.
- Template now uses codegen-units=1 to workaround bug in nightly.
### Fixed ### Fixed
- Alpha channel is now considered by `include_gfx!()` even when `transparent_colour` is absent. - Alpha channel is now considered by `include_gfx!()` even when `transparent_colour` is absent.
- 256 colour backgrounds are now correctly rendered (breaking change). - 256 colour backgrounds are now correctly rendered (breaking change).
- The `#[agb::entry]` macro now reports errors better.
- Added the shstrtab section to the linker to ensure that agb builds with lld.
## [0.13.0] - 2023/01/19 ## [0.13.0] - 2023/01/19

View file

@ -1,4 +1,4 @@
# AGBRS # AGB
## Rust for the Game Boy Advance ## Rust for the Game Boy Advance
@ -10,17 +10,17 @@
![AGB logo](.github/logo.png) ![AGB logo](.github/logo.png)
This is a library for making games on the Game Boy Advance using the Rust This is a library for making games on the Game Boy Advance using the Rust
programming language. It attempts to be a high level abstraction over the programming language. The library's main focus is to provide an abstraction
internal workings of the Game Boy Advance whilst still being high performance that allows you to develop games which take advantage of the GBA's capabilities
and memory efficient. without needing to have extensive knowledge of its low-level implementation.
AGBRS provides the following features: agb provides the following features:
* Simple build process with minimal dependencies * Simple build process with minimal dependencies
* Built in importing of sprites, backgrounds, music and sound effects * Built in importing of sprites, backgrounds, music and sound effects
* High performance audio mixer * High performance audio mixer
* Simple sprite and tiled background usage * Easy to use sprite and tiled background usage
* Global allocator allowing for use of both `core` and `alloc` * A global allocator allowing for use of both `core` and `alloc`
The documentation for the latest release can be found on The documentation for the latest release can be found on
[docs.rs](https://docs.rs/agb/latest/agb/). [docs.rs](https://docs.rs/agb/latest/agb/).
@ -69,7 +69,7 @@ to just write games for the Game Boy Advance using this library:
* [gbafix](https://crates.io/crates/gbafix) * [gbafix](https://crates.io/crates/gbafix)
* Install with `cargo install gbafix` * Install with `cargo install gbafix`
With all of this installed, you should be able to run a full build of agbrs using by running With all of this installed, you should be able to run a full build of agb using by running
```sh ```sh
just ci just ci
``` ```
@ -103,15 +103,14 @@ for performant decimals.
## Stability ## Stability
While in 0.x releases, we are following a semi-semantic versioning. While agb is in the pre-1.0 phase, we follow a semi-semantic versioning scheme to ensure compatibility between minor releases.
So 0.x.y will be compatible with 0.x.z provided that y > z, but any changes Specifically, any 0.x.y release is guaranteed to be compatible with another 0.x.z release provided that y > z, but there may be breaking changes between minor releases (i.e., changes to the second digit, e.g., between 0.1 and 0.2).
to the minor version will be incompatible with one another.
Once we hit version 1.0, we will maintain stronger semantic versioning. Once agb reaches version 1.0, we will transition to stronger semantic versioning, meaning that any breaking changes will be indicated by an increment to the major version (i.e., the first digit, e.g., from 1.0 to 2.0).
## Acknowledgments ## Acknowledgments
AGBRS would not be possible without the help from the following (non-exhaustive) list of projects: agb would not be possible without the help from the following (non-exhaustive) list of projects:
* The amazing work of the [rust-console](https://github.com/rust-console) for making this all possible in the first place * The amazing work of the [rust-console](https://github.com/rust-console) for making this all possible in the first place
* The [asefile](https://crates.io/crates/asefile) crate for loading aseprite files * The [asefile](https://crates.io/crates/asefile) crate for loading aseprite files
@ -120,15 +119,15 @@ AGBRS would not be possible without the help from the following (non-exhaustive)
## Licence ## Licence
AGBRS and all its subcrates are released under MPL version 2.0. See full licence agb and all its subcrates are released under MPL version 2.0. See full licence
text in the `LICENSE` file. text in the `LICENSE` file.
AGBRS contains a subset of the code from [agbabi](https://github.com/felixjones/agbabi) which is released under a zlib style licence, agb contains a subset of the code from [agbabi](https://github.com/felixjones/agbabi) which is released under a zlib style licence,
details for which you can find under `agb/src/agbabi`. details for which you can find under `agb/src/agbabi`.
The template is released under [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/) to allow you to make whatever The template is released under [CC0](https://creativecommons.org/share-your-work/public-domain/cc0/) to allow you to make whatever
changes you wish. changes you wish.
The AGBRS logo is released under [Creative Commons Attribution-ShareAlike 4.0](http://creativecommons.org/licenses/by-sa/4.0/) The agb logo is released under [Creative Commons Attribution-ShareAlike 4.0](http://creativecommons.org/licenses/by-sa/4.0/)
The music used for the examples is by [Josh Woodward](https://www.joshwoodward.com) and released under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/) The music used for the examples is by [Josh Woodward](https://www.joshwoodward.com) and released under [Creative Commons Attribution 4.0](https://creativecommons.org/licenses/by/4.0/)

View file

@ -12,9 +12,9 @@ proc-macro = true
[dependencies] [dependencies]
image = { version = "0.23", default-features = false, features = [ "png", "bmp" ] } image = { version = "0.23", default-features = false, features = [ "png", "bmp" ] }
toml = "0.5" toml = "0.7"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
syn = { version = "1", features = ["full"] } syn = { version = "2", features = ["full"] }
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"
asefile = "0.3.5" asefile = "0.3.5"

View file

@ -28,9 +28,7 @@ impl FromStr for Colour {
fn from_str(colour: &str) -> Result<Self, Self::Err> { fn from_str(colour: &str) -> Result<Self, Self::Err> {
if colour.len() != 6 { if colour.len() != 6 {
return Err(format!( return Err(format!("Expected colour to be 6 characters, got {colour}"));
"Expected colour to be 6 characters, got {colour}"
));
} }
let r = u8::from_str_radix(&colour[0..2], 16).unwrap(); let r = u8::from_str_radix(&colour[0..2], 16).unwrap();

View file

@ -385,8 +385,7 @@ fn add_image_to_tile_data(
for j in inner_y * 8..inner_y * 8 + 8 { for j in inner_y * 8..inner_y * 8 + 8 {
for i in inner_x * 8..inner_x * 8 + 8 { for i in inner_x * 8..inner_x * 8 + 8 {
let colour = image.colour(x * tile_size + i, y * tile_size + j); let colour = image.colour(x * tile_size + i, y * tile_size + j);
tile_data tile_data.push(palette.colour_index(colour));
.push(palette.colour_index(colour));
} }
} }
} }

View file

@ -11,6 +11,6 @@ repository = "https://github.com/agbrs/agb"
proc-macro = true proc-macro = true
[dependencies] [dependencies]
syn = { version = "1", features = ["full", "extra-traits"] } syn = { version = "2", features = ["full", "extra-traits"] }
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"

View file

@ -8,13 +8,20 @@ use syn::{FnArg, Ident, ItemFn, Pat, ReturnType, Token, Type, Visibility};
use std::collections::hash_map::DefaultHasher; use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
fn token_stream_with_string_error(mut tokens: TokenStream, error_str: &str) -> TokenStream {
tokens.extend(TokenStream::from(quote! { compile_error!(#error_str); }));
tokens
}
#[proc_macro_attribute] #[proc_macro_attribute]
pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream { pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
let f: ItemFn = syn::parse(input).expect("#[agb::entry] must be applied to a function"); let f: ItemFn = match syn::parse(input.clone()) {
Ok(it) => it,
Err(_) => return input,
};
// Check that the function signature is correct // Check that the function signature is correct
assert!( if !(f.sig.constness.is_none()
f.sig.constness.is_none()
&& f.vis == Visibility::Inherited && f.vis == Visibility::Inherited
&& f.sig.abi.is_none() && f.sig.abi.is_none()
&& f.sig.generics.params.is_empty() && f.sig.generics.params.is_empty()
@ -22,42 +29,61 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
&& match f.sig.output { && match f.sig.output {
ReturnType::Type(_, ref ty) => matches!(**ty, Type::Never(_)), ReturnType::Type(_, ref ty) => matches!(**ty, Type::Never(_)),
_ => false, _ => false,
}, })
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !" {
return token_stream_with_string_error(
input,
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !",
); );
}
// Check that the function signature takes 1 argument, agb::Gba // Check that the function signature takes 1 argument, agb::Gba
let arguments: Vec<_> = f.sig.inputs.iter().collect(); let arguments: Vec<_> = f.sig.inputs.iter().collect();
assert_eq!( if arguments.len() != 1 {
arguments.len(), return token_stream_with_string_error(
1, input,
&format!(
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !, but got {} arguments", "#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !, but got {} arguments",
arguments.len(), arguments.len()
)
); );
}
let (argument_type, (argument_name, is_mutable)) = match arguments[0] { let (argument_type, (argument_name, is_mutable)) = match arguments[0] {
FnArg::Typed(pat_type) => ( FnArg::Typed(pat_type) => (
pat_type.ty.to_token_stream(), pat_type.ty.to_token_stream(),
match &*pat_type.pat { match &*pat_type.pat {
Pat::Ident(ident) => { Pat::Ident(ident) => {
assert!( if !(ident.attrs.is_empty() && ident.by_ref.is_none() && ident.subpat.is_none())
ident.attrs.is_empty() && ident.by_ref.is_none() && ident.subpat.is_none(), {
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !" return token_stream_with_string_error(
input,
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !",
); );
}
(ident.ident.clone(), ident.mutability.is_some()) (ident.ident.clone(), ident.mutability.is_some())
} }
_ => panic!("Expected first argument to #[agb::entry] to be a basic identifier"), _ => {
return token_stream_with_string_error(
input,
"Expected first argument to #[agb::entry] to be a basic identifier",
)
}
}, },
), ),
_ => panic!("Expected first argument to #[agb::entry] to not be self"), _ => {
return token_stream_with_string_error(
input,
"Expected first argument to #[agb::entry] to not be self",
)
}
}; };
assert!( if args.to_string() != "" {
args.to_string() == "", return token_stream_with_string_error(input, "Must pass no args to #[agb::entry] macro");
"Must pass no args to #[agb::entry] macro" }
);
let fn_name = hashed_ident(&f); let fn_name = hashed_ident(&f);
@ -70,10 +96,9 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
None None
}; };
assert!( if !argument_type.to_string().ends_with("Gba") {
argument_type.to_string().ends_with("Gba"), return token_stream_with_string_error(input, "Expected first argument to have type 'Gba'");
"Expected first argument to have type 'Gba'" }
);
quote!( quote!(
#[cfg(not(test))] #[cfg(not(test))]

View file

@ -20,6 +20,6 @@ proc-macro = true
[dependencies] [dependencies]
hound = "3.5" hound = "3.5"
syn = "1" syn = "2"
proc-macro2 = "1" proc-macro2 = "1"
quote = "1" quote = "1"

View file

@ -12,16 +12,17 @@ opt-level = 3
debug = true debug = true
[profile.release] [profile.release]
opt-level = "s" opt-level = 3
lto = "thin" lto = "fat"
debug = true debug = true
codegen-units = 1
[features] [features]
default = ["testing"] default = ["testing"]
testing = [] testing = []
[dependencies] [dependencies]
bitflags = "1" bitflags = "2"
agb_image_converter = { version = "0.13.0", path = "../agb-image-converter" } agb_image_converter = { version = "0.13.0", path = "../agb-image-converter" }
agb_sound_converter = { version = "0.13.0", path = "../agb-sound-converter" } agb_sound_converter = { version = "0.13.0", path = "../agb-sound-converter" }
agb_macros = { version = "0.13.0", path = "../agb-macros" } agb_macros = { version = "0.13.0", path = "../agb-macros" }

View file

@ -6,13 +6,10 @@ use agb::sync::Static;
#[agb::entry] #[agb::entry]
fn main(_gba: agb::Gba) -> ! { fn main(_gba: agb::Gba) -> ! {
let count = Static::new(0); let count = Static::new(0);
let _a = agb::interrupt::add_interrupt_handler( let _a = agb::interrupt::add_interrupt_handler(agb::interrupt::Interrupt::VBlank, |_| {
agb::interrupt::Interrupt::VBlank,
|_| {
let cur_count = count.read(); let cur_count = count.read();
agb::println!("Hello, world, frame = {}", cur_count); agb::println!("Hello, world, frame = {}", cur_count);
count.write(cur_count + 1); count.write(cur_count + 1);
}, });
);
loop {} loop {}
} }

View file

@ -74,6 +74,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -72,6 +72,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
components = ["rust-src", "clippy"] components = ["rust-src", "clippy", "rustfmt"]

View file

@ -10,9 +10,9 @@ use core::convert::TryInto;
use core::ptr::NonNull; use core::ptr::NonNull;
use crate::interrupt::free; use crate::interrupt::free;
use bare_metal::{CriticalSection, Mutex}; use bare_metal::Mutex;
use super::bump_allocator::{BumpAllocator, StartEnd}; use super::bump_allocator::{BumpAllocatorInner, StartEnd};
use super::SendNonNull; use super::SendNonNull;
struct Block { struct Block {
@ -37,57 +37,103 @@ impl Block {
.expect("too large allocation") .expect("too large allocation")
.pad_to_align() .pad_to_align()
} }
pub fn layout() -> Layout {
Layout::new::<Block>().align_to(8).unwrap().pad_to_align()
}
} }
struct BlockAllocatorState { struct BlockAllocatorState {
first_free_block: Option<SendNonNull<Block>>, first_free_block: Option<SendNonNull<Block>>,
} }
struct BlockAllocatorInner {
inner_allocator: BumpAllocatorInner,
state: BlockAllocatorState,
}
pub struct BlockAllocator { pub struct BlockAllocator {
inner_allocator: BumpAllocator, inner: Mutex<RefCell<BlockAllocatorInner>>,
state: Mutex<RefCell<BlockAllocatorState>>,
} }
impl BlockAllocator { impl BlockAllocator {
pub(crate) const unsafe fn new(start: StartEnd) -> Self { pub(crate) const unsafe fn new(start: StartEnd) -> Self {
Self { Self {
inner_allocator: BumpAllocator::new(start), inner: Mutex::new(RefCell::new(BlockAllocatorInner::new(start))),
state: Mutex::new(RefCell::new(BlockAllocatorState {
first_free_block: None,
})),
} }
} }
#[doc(hidden)] #[doc(hidden)]
#[cfg(any(test, feature = "testing"))] #[cfg(any(test, feature = "testing"))]
pub unsafe fn number_of_blocks(&self) -> u32 { pub unsafe fn number_of_blocks(&self) -> u32 {
free(|key| { free(|key| self.inner.borrow(key).borrow_mut().number_of_blocks())
let mut state = self.state.borrow(key).borrow_mut(); }
pub unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> {
free(|key| self.inner.borrow(key).borrow_mut().alloc(layout))
}
pub unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
free(|key| self.inner.borrow(key).borrow_mut().dealloc(ptr, layout));
}
pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) {
free(|key| {
self.inner
.borrow(key)
.borrow_mut()
.dealloc_no_normalise(ptr, layout);
});
}
pub unsafe fn grow(
&self,
ptr: *mut u8,
layout: Layout,
new_layout: Layout,
) -> Option<NonNull<u8>> {
free(|key| {
self.inner
.borrow(key)
.borrow_mut()
.grow(ptr, layout, new_layout)
})
}
}
impl BlockAllocatorInner {
pub(crate) const unsafe fn new(start: StartEnd) -> Self {
Self {
inner_allocator: BumpAllocatorInner::new(start),
state: BlockAllocatorState {
first_free_block: None,
},
}
}
#[doc(hidden)]
#[cfg(any(test, feature = "testing"))]
pub unsafe fn number_of_blocks(&mut self) -> u32 {
let mut count = 0; let mut count = 0;
let mut list_ptr = &mut state.first_free_block; let mut list_ptr = &mut self.state.first_free_block;
while let Some(mut current) = list_ptr { while let Some(mut current) = list_ptr {
count += 1; count += 1;
list_ptr = &mut current.as_mut().next; list_ptr = &mut current.as_mut().next;
} }
count count
})
} }
/// Requests a brand new block from the inner bump allocator /// Requests a brand new block from the inner bump allocator
fn new_block(&self, layout: Layout, cs: CriticalSection) -> Option<NonNull<u8>> { fn new_block(&mut self, layout: Layout) -> Option<NonNull<u8>> {
let overall_layout = Block::either_layout(layout); let overall_layout = Block::either_layout(layout);
self.inner_allocator.alloc_critical(overall_layout, cs) self.inner_allocator.alloc(overall_layout)
} }
/// Merges blocks together to create a normalised list /// Merges blocks together to create a normalised list
unsafe fn normalise(&self) { unsafe fn normalise(&mut self) {
free(|key| { let mut list_ptr = &mut self.state.first_free_block;
let mut state = self.state.borrow(key).borrow_mut();
let mut list_ptr = &mut state.first_free_block;
while let Some(mut current) = list_ptr { while let Some(mut current) = list_ptr {
if let Some(next_elem) = current.as_mut().next { if let Some(next_elem) = current.as_mut().next {
@ -110,65 +156,159 @@ impl BlockAllocator {
} }
list_ptr = &mut current.as_mut().next; list_ptr = &mut current.as_mut().next;
} }
});
} }
pub unsafe fn alloc(&self, layout: Layout) -> Option<NonNull<u8>> { pub unsafe fn alloc(&mut self, layout: Layout) -> Option<NonNull<u8>> {
// find a block that this current request fits in // find a block that this current request fits in
let full_layout = Block::either_layout(layout); let full_layout = Block::either_layout(layout);
let (block_after_layout, block_after_layout_offset) = full_layout let mut list_ptr = &mut self.state.first_free_block;
.extend(Layout::new::<Block>().align_to(8).unwrap().pad_to_align())
.unwrap();
free(|key| {
let mut state = self.state.borrow(key).borrow_mut();
let mut current_block = state.first_free_block;
let mut list_ptr = &mut state.first_free_block;
// This iterates the free list until it either finds a block that // This iterates the free list until it either finds a block that
// is the exact size requested or a block that can be split into // is the exact size requested or a block that can be split into
// one with the desired size and another block header. // one with the desired size and another block header.
while let Some(mut current) = current_block { loop {
let block_to_examine = current.as_mut(); match list_ptr {
if block_to_examine.size == full_layout.size() { Some(mut current_block) => {
*list_ptr = block_to_examine.next; if let Some(alloc) = Self::allocate_into_block(list_ptr, full_layout) {
return Some(current.cast()); return Some(alloc);
} else if block_to_examine.size >= block_after_layout.size() { }
// can split block list_ptr = &mut current_block.as_mut().next;
}
None => return self.new_block(layout),
}
}
}
/// splits a block in twain
unsafe fn allocate_into_block(
reference_to_block_pointer: &mut Option<SendNonNull<Block>>,
wanted_layout: Layout,
) -> Option<NonNull<u8>> {
let (extended_layout, offset) = wanted_layout.extend(Block::layout()).unwrap();
let mut examination_block_ptr = reference_to_block_pointer.unwrap().0;
let examination_block = examination_block_ptr.as_mut();
if examination_block.size == wanted_layout.size() {
*reference_to_block_pointer = examination_block.next;
Some(examination_block_ptr.cast())
} else if examination_block.size >= extended_layout.size() {
let split_block = Block { let split_block = Block {
size: block_to_examine.size - block_after_layout_offset, size: examination_block.size - offset,
next: block_to_examine.next, next: examination_block.next,
}; };
let split_ptr = current
let split_block_ptr = examination_block_ptr
.as_ptr() .as_ptr()
.cast::<u8>() .cast::<u8>()
.add(block_after_layout_offset) .add(offset)
.cast(); .cast();
*split_ptr = split_block; *split_block_ptr = split_block;
*list_ptr = NonNull::new(split_ptr).map(SendNonNull); *reference_to_block_pointer = NonNull::new(split_block_ptr).map(SendNonNull);
return Some(current.cast()); Some(examination_block_ptr.cast())
} else {
None
} }
current_block = block_to_examine.next;
list_ptr = &mut block_to_examine.next;
} }
self.new_block(layout, key) pub unsafe fn grow(
}) &mut self,
ptr: *mut u8,
initial_layout: Layout,
desired_layout: Layout,
) -> Option<NonNull<u8>> {
let either_layout_initial = Block::either_layout(initial_layout);
let either_layout_desired = Block::either_layout(desired_layout);
let difference = Layout::from_size_align(
either_layout_desired.size() - either_layout_initial.size(),
either_layout_initial.align(),
)
.expect("should be able to construct difference layout");
if self.is_block_at_end(ptr, either_layout_initial) {
let _additional_space = self.inner_allocator.alloc(difference);
return NonNull::new(ptr);
} }
pub unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { // cases
// * Our block has no free block after it.
// * Our block has a free block after that we fit in.
// * Our block has a free block after that is too small.
// * UNIMPLEMENTED Out block has a free block after that is too small but that is at the end so we can bump allocate some more space.
let next_block = self.find_first_block_after(ptr);
if let Some(list_to_block) = next_block {
let is_block_directly_after = {
if let Some(block) = list_to_block {
block.0.as_ptr() == ptr.add(either_layout_initial.size()).cast()
} else {
false
}
};
if is_block_directly_after {
if let Some(_split) = Self::allocate_into_block(list_to_block, difference) {
return NonNull::new(ptr);
}
}
}
self.grow_copy(ptr, either_layout_initial, either_layout_desired)
}
unsafe fn grow_copy(
&mut self,
ptr: *mut u8,
initial_layout: Layout,
desired_layout: Layout,
) -> Option<NonNull<u8>> {
let new_ptr = self.alloc(desired_layout)?;
core::ptr::copy_nonoverlapping(ptr, new_ptr.as_ptr(), initial_layout.size());
self.dealloc(ptr, initial_layout);
Some(new_ptr)
}
unsafe fn is_block_at_end(&self, ptr: *mut u8, total_layout: Layout) -> bool {
self.inner_allocator.tip() == NonNull::new(ptr.add(total_layout.size()))
}
pub unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
self.dealloc_no_normalise(ptr, layout); self.dealloc_no_normalise(ptr, layout);
self.normalise(); self.normalise();
} }
pub unsafe fn dealloc_no_normalise(&self, ptr: *mut u8, layout: Layout) { /// Returns a reference to the pointer to the next block
/// Useful because you can modify what points to the block and access the block
unsafe fn find_first_block_after(
&mut self,
ptr: *mut u8,
) -> Option<&mut Option<SendNonNull<Block>>> {
let mut list_ptr = &mut self.state.first_free_block;
loop {
match list_ptr {
Some(mut current_block) => {
if current_block.as_ptr().cast() > ptr {
return Some(list_ptr);
}
list_ptr = &mut current_block.as_mut().next;
}
None => return None,
}
}
}
pub unsafe fn dealloc_no_normalise(&mut self, ptr: *mut u8, layout: Layout) {
let new_layout = Block::either_layout(layout).pad_to_align(); let new_layout = Block::either_layout(layout).pad_to_align();
free(|key| {
let mut state = self.state.borrow(key).borrow_mut();
// note that this is a reference to a pointer // note that this is a reference to a pointer
let mut list_ptr = &mut state.first_free_block; let mut list_ptr = &mut self.state.first_free_block;
// This searches the free list until it finds a block further along // This searches the free list until it finds a block further along
// than the block that is being freed. The newly freed block is then // than the block that is being freed. The newly freed block is then
@ -200,7 +340,6 @@ impl BlockAllocator {
} }
} }
} }
});
} }
} }
@ -215,6 +354,24 @@ unsafe impl GlobalAlloc for BlockAllocator {
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
self.dealloc(ptr, layout); self.dealloc(ptr, layout);
} }
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
let new_layout = Layout::from_size_align_unchecked(new_size, layout.align());
if new_size > layout.size() {
return match self.grow(ptr, layout, new_layout) {
Some(p) => p.as_ptr(),
None => core::ptr::null_mut(),
};
}
let new_ptr = GlobalAlloc::alloc(self, new_layout);
if !new_ptr.is_null() {
core::ptr::copy_nonoverlapping(ptr, new_ptr, core::cmp::min(layout.size(), new_size));
self.dealloc(ptr, layout);
}
new_ptr
}
} }
unsafe impl Allocator for BlockAllocator { unsafe impl Allocator for BlockAllocator {
@ -230,6 +387,42 @@ unsafe impl Allocator for BlockAllocator {
} }
} }
unsafe fn grow(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
match self.grow(ptr.as_ptr(), old_layout, new_layout) {
Some(p) => Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
p.as_ptr(),
new_layout.size(),
))),
None => Err(core::alloc::AllocError),
}
}
unsafe fn grow_zeroed(
&self,
ptr: NonNull<u8>,
old_layout: Layout,
new_layout: Layout,
) -> Result<NonNull<[u8]>, core::alloc::AllocError> {
let new_ptr = self
.grow(ptr.as_ptr(), old_layout, new_layout)
.ok_or(core::alloc::AllocError)?;
new_ptr
.as_ptr()
.add(old_layout.size())
.write_bytes(0, new_layout.size() - old_layout.size());
Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut(
new_ptr.as_ptr(),
new_layout.size(),
)))
}
unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) { unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
self.dealloc(ptr.as_ptr(), layout); self.dealloc(ptr.as_ptr(), layout);
} }

View file

@ -4,35 +4,41 @@ use core::ptr::NonNull;
use super::SendNonNull; use super::SendNonNull;
use crate::interrupt::free; use crate::interrupt::free;
use bare_metal::{CriticalSection, Mutex}; use bare_metal::Mutex;
pub(crate) struct StartEnd { pub(crate) struct StartEnd {
pub start: fn() -> usize, pub start: fn() -> usize,
pub end: fn() -> usize, pub end: fn() -> usize,
} }
pub(crate) struct BumpAllocator { pub(crate) struct BumpAllocatorInner {
current_ptr: Mutex<RefCell<Option<SendNonNull<u8>>>>, current_ptr: Option<SendNonNull<u8>>,
start_end: Mutex<StartEnd>, start_end: StartEnd,
} }
impl BumpAllocator { pub(crate) struct BumpAllocator {
inner: Mutex<RefCell<BumpAllocatorInner>>,
}
impl BumpAllocatorInner {
pub const fn new(start_end: StartEnd) -> Self { pub const fn new(start_end: StartEnd) -> Self {
Self { Self {
current_ptr: Mutex::new(RefCell::new(None)), current_ptr: None,
start_end: Mutex::new(start_end), start_end,
} }
} }
}
impl BumpAllocator { pub fn tip(&self) -> Option<NonNull<u8>> {
pub fn alloc_critical(&self, layout: Layout, cs: CriticalSection) -> Option<NonNull<u8>> { self.current_ptr.map(|x| x.0)
let mut current_ptr = self.current_ptr.borrow(cs).borrow_mut(); }
pub fn alloc(&mut self, layout: Layout) -> Option<NonNull<u8>> {
let current_ptr = &mut self.current_ptr;
let ptr = if let Some(c) = *current_ptr { let ptr = if let Some(c) = *current_ptr {
c.as_ptr() as usize c.as_ptr() as usize
} else { } else {
(self.start_end.borrow(cs).start)() (self.start_end.start)()
}; };
let alignment_bitmask = layout.align() - 1; let alignment_bitmask = layout.align() - 1;
@ -43,7 +49,7 @@ impl BumpAllocator {
let resulting_ptr = ptr + amount_to_add; let resulting_ptr = ptr + amount_to_add;
let new_current_ptr = resulting_ptr + layout.size(); let new_current_ptr = resulting_ptr + layout.size();
if new_current_ptr >= (self.start_end.borrow(cs).end)() { if new_current_ptr >= (self.start_end.end)() {
return None; return None;
} }
@ -51,8 +57,11 @@ impl BumpAllocator {
NonNull::new(resulting_ptr as *mut _) NonNull::new(resulting_ptr as *mut _)
} }
pub fn alloc_safe(&self, layout: Layout) -> Option<NonNull<u8>> { }
free(|key| self.alloc_critical(layout, key))
impl BumpAllocator {
fn alloc_safe(&self, layout: Layout) -> Option<NonNull<u8>> {
free(|key| self.inner.borrow(key).borrow_mut().alloc(layout))
} }
} }

View file

@ -292,4 +292,18 @@ mod test {
} }
} }
} }
#[test_case]
fn growth_works(_gba: &mut crate::Gba) {
let mut growing_vector = Vec::with_capacity(1);
for i in 0..1000 {
growing_vector.push(i);
growing_vector.reserve_exact(i + 2);
for (idx, elem) in growing_vector.iter().enumerate() {
assert_eq!(idx, *elem);
}
}
}
} }

View file

@ -35,6 +35,7 @@ pub(crate) const DISPLAY_STATUS: MemoryMapped<u16> = unsafe { MemoryMapped::new(
const VCOUNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0006) }; const VCOUNT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0006) };
bitflags! { bitflags! {
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
struct GraphicsSettings: u16 { struct GraphicsSettings: u16 {
const PAGE_SELECT = 1 << 0x4; const PAGE_SELECT = 1 << 0x4;
const OAM_HBLANK = 1 << 0x5; const OAM_HBLANK = 1 << 0x5;

View file

@ -40,6 +40,7 @@ impl From<(bool, bool)> for Tri {
bitflags! { bitflags! {
/// Represents a button on the GBA /// Represents a button on the GBA
#[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
pub struct Button: u32 { pub struct Button: u32 {
/// The A button /// The A button
const A = 1 << 0; const A = 1 << 0;

View file

@ -3,8 +3,8 @@
//! EEPROM requires using DMA to issue commands for both reading and writing. //! EEPROM requires using DMA to issue commands for both reading and writing.
use crate::memory_mapped::MemoryMapped; use crate::memory_mapped::MemoryMapped;
use crate::save::{Error, MediaInfo, MediaType, RawSaveAccess};
use crate::save::utils::Timeout; use crate::save::utils::Timeout;
use crate::save::{Error, MediaInfo, MediaType, RawSaveAccess};
use core::cmp; use core::cmp;
const PORT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0DFFFF00) }; const PORT: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0DFFFF00) };
@ -41,7 +41,10 @@ union BufferContents {
} }
impl BufferData { impl BufferData {
fn new() -> Self { fn new() -> Self {
BufferData { idx: 0, data: BufferContents { uninit: () } } BufferData {
idx: 0,
data: BufferContents { uninit: () },
}
} }
/// Writes a bit to the output buffer. /// Writes a bit to the output buffer.
@ -120,7 +123,10 @@ impl EepromProperties {
/// Writes a sector directly. /// Writes a sector directly.
#[allow(clippy::needless_range_loop)] #[allow(clippy::needless_range_loop)]
fn write_sector_raw( fn write_sector_raw(
&self, word: usize, block: &[u8], timeout: &mut Timeout, &self,
word: usize,
block: &[u8],
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
// 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.
@ -150,7 +156,11 @@ impl EepromProperties {
/// Writes a sector to the EEPROM, keeping any current contents outside the /// Writes a sector to the EEPROM, keeping any current contents outside the
/// buffer's range. /// buffer's range.
fn write_sector_safe( fn write_sector_safe(
&self, word: usize, data: &[u8], start: usize, timeout: &mut Timeout, &self,
word: usize,
data: &[u8],
start: usize,
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut buf = self.read_sector(word); let mut buf = self.read_sector(word);
buf[start..start + data.len()].copy_from_slice(data); buf[start..start + data.len()].copy_from_slice(data);
@ -159,7 +169,11 @@ impl EepromProperties {
/// Writes a sector to the EEPROM. /// Writes a sector to the EEPROM.
fn write_sector( fn write_sector(
&self, word: usize, data: &[u8], start: usize, timeout: &mut Timeout, &self,
word: usize,
data: &[u8],
start: usize,
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
if data.len() == 8 && start == 0 { if data.len() == 8 && start == 0 {
self.write_sector_raw(word, data, timeout) self.write_sector_raw(word, data, timeout)
@ -219,8 +233,14 @@ impl EepromProperties {
Ok(()) Ok(())
} }
} }
const PROPS_512B: EepromProperties = EepromProperties { addr_bits: 6, byte_len: 512 }; const PROPS_512B: EepromProperties = EepromProperties {
const PROPS_8K: EepromProperties = EepromProperties { addr_bits: 14, byte_len: 8 * 1024 }; addr_bits: 6,
byte_len: 512,
};
const PROPS_8K: EepromProperties = EepromProperties {
addr_bits: 14,
byte_len: 8 * 1024,
};
/// The [`RawSaveAccess`] used for 512 byte EEPROM. /// The [`RawSaveAccess`] used for 512 byte EEPROM.
pub struct Eeprom512B; pub struct Eeprom512B;

View file

@ -6,11 +6,11 @@
// TODO: Setup cartridge read timings for faster Flash access. // TODO: Setup cartridge read timings for faster Flash access.
use crate::memory_mapped::{MemoryMapped, MemoryMapped1DArray}; use crate::memory_mapped::{MemoryMapped, MemoryMapped1DArray};
use crate::save::{Error, MediaInfo, MediaType, RawSaveAccess};
use crate::save::asm_utils::*; use crate::save::asm_utils::*;
use crate::save::utils::Timeout;
use crate::save::{Error, MediaInfo, MediaType, RawSaveAccess};
use crate::sync::{InitOnce, Static}; use crate::sync::{InitOnce, Static};
use core::cmp; use core::cmp;
use crate::save::utils::Timeout;
// Volatile address ports for flash // Volatile address ports for flash
const FLASH_PORT_BANK: MemoryMapped<u8> = unsafe { MemoryMapped::new(0x0E000000) }; const FLASH_PORT_BANK: MemoryMapped<u8> = unsafe { MemoryMapped::new(0x0E000000) };
@ -314,7 +314,11 @@ impl ChipInfo {
/// Waits for a timeout, or an operation to complete. /// Waits for a timeout, or an operation to complete.
fn wait_for_timeout( fn wait_for_timeout(
&self, offset: usize, val: u8, ms: u16, timeout: &mut Timeout, &self,
offset: usize,
val: u8,
ms: u16,
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
timeout.start(); timeout.start();
let offset = 0x0E000000 + offset; let offset = 0x0E000000 + offset;
@ -371,7 +375,10 @@ impl ChipInfo {
/// Erases and writes an entire 128b sector on Atmel devices. /// Erases and writes an entire 128b sector on Atmel devices.
#[allow(clippy::needless_range_loop)] #[allow(clippy::needless_range_loop)]
fn write_atmel_sector_raw( fn write_atmel_sector_raw(
&self, offset: usize, buf: &[u8], timeout: &mut Timeout, &self,
offset: usize,
buf: &[u8],
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
crate::interrupt::free(|_| { crate::interrupt::free(|_| {
issue_flash_command(CMD_WRITE); issue_flash_command(CMD_WRITE);
@ -387,12 +394,19 @@ impl ChipInfo {
/// case of non-sector aligned writes. /// case of non-sector aligned writes.
#[inline(never)] // avoid allocating the 128 byte buffer for no reason. #[inline(never)] // avoid allocating the 128 byte buffer for no reason.
fn write_atmel_sector_safe( fn write_atmel_sector_safe(
&self, offset: usize, buf: &[u8], start: usize, timeout: &mut Timeout, &self,
offset: usize,
buf: &[u8],
start: usize,
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut sector = [0u8; 128]; let mut sector = [0u8; 128];
self.read_buffer(offset, &mut sector[0..start])?; self.read_buffer(offset, &mut sector[0..start])?;
sector[start..start + buf.len()].copy_from_slice(buf); sector[start..start + buf.len()].copy_from_slice(buf);
self.read_buffer(offset + start + buf.len(), &mut sector[start + buf.len()..128])?; self.read_buffer(
offset + start + buf.len(),
&mut sector[start + buf.len()..128],
)?;
self.write_atmel_sector_raw(offset, &sector, timeout) self.write_atmel_sector_raw(offset, &sector, timeout)
} }
@ -401,7 +415,11 @@ impl ChipInfo {
/// ///
/// This avoids allocating stack if there is no need to. /// This avoids allocating stack if there is no need to.
fn write_atmel_sector( fn write_atmel_sector(
&self, offset: usize, buf: &[u8], start: usize, timeout: &mut Timeout, &self,
offset: usize,
buf: &[u8],
start: usize,
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
if start == 0 && buf.len() == 128 { if start == 0 && buf.len() == 128 {
self.write_atmel_sector_raw(offset, buf, timeout) self.write_atmel_sector_raw(offset, buf, timeout)
@ -433,7 +451,10 @@ impl RawSaveAccess for FlashAccess {
} }
fn prepare_write( fn prepare_write(
&self, sector: usize, count: usize, timeout: &mut Timeout, &self,
sector: usize,
count: usize,
timeout: &mut Timeout,
) -> Result<(), Error> { ) -> Result<(), Error> {
let chip = cached_chip_info()?; let chip = cached_chip_info()?;
chip.check_sector_len(sector, count)?; chip.check_sector_len(sector, count)?;

View file

@ -3,9 +3,9 @@
//! SRAM acts as ordinary memory mapped into the memory space, and as such //! SRAM acts as ordinary memory mapped into the memory space, and as such
//! is accessed using normal memory read/write commands. //! is accessed using normal memory read/write commands.
use crate::save::{Error, MediaInfo, MediaType, RawSaveAccess};
use crate::save::asm_utils::*; use crate::save::asm_utils::*;
use crate::save::utils::Timeout; use crate::save::utils::Timeout;
use crate::save::{Error, MediaInfo, MediaType, RawSaveAccess};
const SRAM_SIZE: usize = 32 * 1024; // 32 KiB const SRAM_SIZE: usize = 32 * 1024; // 32 KiB

View file

@ -2,7 +2,7 @@
use super::Error; use super::Error;
use crate::sync::{RawMutex, RawMutexGuard}; use crate::sync::{RawMutex, RawMutexGuard};
use crate::timer::{Timer, Divider}; use crate::timer::{Divider, Timer};
/// A timeout type used to prevent hardware errors in save media from hanging /// A timeout type used to prevent hardware errors in save media from hanging
/// the game. /// the game.

View file

@ -81,7 +81,10 @@ impl<T> Mutex<T> {
/// Creates a new lock containing a given value. /// Creates a new lock containing a given value.
#[must_use] #[must_use]
pub const fn new(t: T) -> Self { pub const fn new(t: T) -> Self {
Mutex { raw: RawMutex::new(), data: UnsafeCell::new(t) } Mutex {
raw: RawMutex::new(),
data: UnsafeCell::new(t),
}
} }
/// Returns a guard for this lock, or panics if there is another lock active. /// Returns a guard for this lock, or panics if there is another lock active.
@ -92,7 +95,10 @@ impl<T> Mutex<T> {
/// Returns a guard for this lock or `None` if there is another lock active. /// Returns a guard for this lock or `None` if there is another lock active.
pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> { pub fn try_lock(&self) -> Option<MutexGuard<'_, T>> {
if self.raw.raw_lock() { if self.raw.raw_lock() {
Some(MutexGuard { underlying: self, ptr: self.data.get() }) Some(MutexGuard {
underlying: self,
ptr: self.data.get(),
})
} else { } else {
None None
} }

View file

@ -1,6 +1,6 @@
use core::cmp;
use agb::save::{Error, MediaInfo}; use agb::save::{Error, MediaInfo};
use agb::sync::InitOnce; use agb::sync::InitOnce;
use core::cmp;
fn init_sram(gba: &mut agb::Gba) -> &'static MediaInfo { fn init_sram(gba: &mut agb::Gba) -> &'static MediaInfo {
static ONCE: InitOnce<MediaInfo> = InitOnce::new(); static ONCE: InitOnce<MediaInfo> = InitOnce::new();
@ -31,7 +31,11 @@ const MAX_BLOCK_SIZE: usize = 4 * 1024;
#[allow(clippy::needless_range_loop)] #[allow(clippy::needless_range_loop)]
fn do_test( fn do_test(
gba: &mut agb::Gba, seed: Rng, offset: usize, len: usize, block_size: usize, gba: &mut agb::Gba,
seed: Rng,
offset: usize,
len: usize,
block_size: usize,
) -> Result<(), Error> { ) -> Result<(), Error> {
let mut buffer = [0; MAX_BLOCK_SIZE]; let mut buffer = [0; MAX_BLOCK_SIZE];
@ -61,9 +65,12 @@ fn do_test(
for i in 0..cur_len { for i in 0..cur_len {
let cur_byte = rng.next_u8(); let cur_byte = rng.next_u8();
assert_eq!( assert_eq!(
buffer[i], cur_byte, buffer[i],
cur_byte,
"Read does not match earlier write: {} != {} @ 0x{:05x}", "Read does not match earlier write: {} != {} @ 0x{:05x}",
buffer[i], cur_byte, current + i, buffer[i],
cur_byte,
current + i,
); );
} }
current += cur_len; current += cur_len;

View file

@ -23,7 +23,7 @@ dependencies = [
"agb_macros", "agb_macros",
"agb_sound_converter", "agb_sound_converter",
"bare-metal", "bare-metal",
"bitflags", "bitflags 2.0.2",
"modular-bitfield", "modular-bitfield",
"rustc-hash", "rustc-hash",
] ]
@ -45,7 +45,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn", "syn 2.0.8",
"toml", "toml",
] ]
@ -55,7 +55,7 @@ version = "0.13.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -65,7 +65,7 @@ dependencies = [
"hound", "hound",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -85,7 +85,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891" checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"byteorder", "byteorder",
"flate2", "flate2",
"image", "image",
@ -112,10 +112,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bytemuck" name = "bitflags"
version = "1.13.0" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
[[package]]
name = "bytemuck"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -217,9 +223,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.139" version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "log" name = "log"
@ -266,7 +272,7 @@ checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
] ]
[[package]] [[package]]
@ -318,9 +324,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "png" name = "png"
@ -328,7 +334,7 @@ version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"crc32fast", "crc32fast",
"deflate", "deflate",
"miniz_oxide 0.3.7", "miniz_oxide 0.3.7",
@ -343,18 +349,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.50" version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -367,22 +373,22 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -393,9 +399,20 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.107" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -419,9 +436,9 @@ checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "version_check" name = "version_check"

View file

@ -74,6 +74,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -72,6 +72,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
components = ["rust-src", "clippy"] components = ["rust-src", "clippy", "rustfmt"]

View file

@ -1,21 +1,20 @@
# The Game Boy Advance hardware # The Game Boy Advance hardware
The Game Boy Advance was released by Nintendo in Japan in March 2001 and in North America in the following June. The Game Boy Advance is a handheld gaming console released by Nintendo in March 2001 in Japan and in North America in June of the same year.
It has a 2.9 inch screen with a 240x144 pixel resolution, and contains a 32-bit 16.8MHz ARM CPU. It features a 2.9 inch screen with a 240x144 pixel resolution and is powered by a 32-bit 16.8MHz ARM CPU.
It was developed to be the successor to the Game Boy Color and internally codenamed the 'Advanced Game Boy' (agb) which is where this crate gets its name. The console was developed as a successor to the Game Boy Color and was internally codenamed the 'Advanced Game Boy' (agb), which is where this crate gets its name.
# What makes the GBA unique? # What makes the GBA unique?
The Game Boy Advance is (fairly) unique amongst retro handheld consoles. The Game Boy Advance is a (fairly) unique console among retro handheld consoles.
It was developed at a time where processors weren't powerful enough to be able to push an entire screen of pixels to the screen every frame. It was developed at a time when processors were not powerful enough to push an entire screen of pixels to the screen every frame.
Therefore, it has a special Pixel Processing Unit (PPU) which is sort of similar to a modern day graphics card, except it is very games focused. As a result, it features a special Pixel Processing Unit (PPU) that is similar to a modern-day graphics card, but is optimized for gaming.
For example, the GBA has a concept of 'hardware sprites' and 'hardware backgrounds' which we'll go in to more detail in the next section. The console has a concept of "hardware sprites" and "hardware backgrounds," which we will explain in more detail in the next section.
This hardware 2d capabilities gives the GBA the unique characteristics with the games developed for it. These hardware 2D capabilities give the GBA its unique characteristics.
However, despite this, it is possible to write code for it using modern tools and programming languages thanks to the ARM CPU it contains. Despite being a retro console, the GBA is still compatible with modern tools and programming languages thanks to the ARM CPU it contains.
The CPU is modern enough to be supported by LLVM and rust to give a reasonably trouble free experience. The CPU is modern enough to be supported by LLVM and Rust, which provide a reasonably trouble-free experience.
This allows developers to take advantage of modern tooling while experiencing what it was like to program for retro consoles at the time.
So the GBA lets you take advantage of modern tooling while also giving you the ability to see what programming for retro consoles was like at the time!
# Capabilities of the hardware # Capabilities of the hardware
@ -25,9 +24,8 @@ The relevant features for this book are:
* 256 sprites which can be from 8x8 to 64x64 pixels in size * 256 sprites which can be from 8x8 to 64x64 pixels in size
* 4 background layers which are enabled / disabled depending on the graphics mode * 4 background layers which are enabled / disabled depending on the graphics mode
* Background tiles, 8x8 pixel tiles are used in the background layers if they are in tile mode. * Background tiles, 8x8 pixel tiles are used in the background layers if they are in tile mode.
* 8-bit sound. You have the ability to send 8-bit raw audio data to the speakers (optionally stereo). * 8-bit sound. You have the ability to send 8-bit raw audio data to the speakers, optionally stereo.
You can read more about the specifics of the GBA on [gbatek](https://rust-console.github.io/gbatek-gbaonly/). You can read more about the specifics of the GBA on [gbatek](https://rust-console.github.io/gbatek-gbaonly/).
To simplify the development process, agb abstracts some of the GBA's hardware away from the developer, which reduces the number of things to remember and lessens the chance of something going wrong.
agb tries to abstract some of this away from you to give you less to remember and less that can go wrong. If you wish to experiment with the hardware directly, the best place to look is [tonc](https://www.coranac.com/tonc/text/).
If you want to try playing around directly with the hardware, the best place to look is [tonc](https://www.coranac.com/tonc/text/).

View file

@ -1,30 +1,52 @@
# Introduction # Introduction
**agb** is a library for writing games for the Game Boy Advance (GBA) in rust. **agb** is a powerful and easy-to-use library for writing games for the Game Boy Advance (GBA) in rust.
It is intended to make the process of producing games for the Game Boy Advance as easy as possible by giving you access to the hardware in an abstracted format, which allows you to take advantage of all that it has to offer, without needing to know the specifics of how it is implemented. It provides an abstracted interface to the hardware, allowing you to take full advantage of its capabilities without needing to know the low-level details of its implementation.
## A little bit about agb
`agb` is a library for making games on the Game Boy Advance using the Rust
programming language. The library's main focus is to provide an abstraction
that allows you to develop games which take advantage of the GBA's capabilities
without needing to have extensive knowledge of its low-level implementation.
agb provides the following features:
* Simple build process with minimal dependencies
* Built in importing of sprites, backgrounds, music and sound effects
* High performance audio mixer
* Easy to use sprite and tiled background usage
* A global allocator allowing for use of both `core` and `alloc`
## Why rust?
Rust is an excellent choice of language for developing games on low-level embedded hardware like the GBA.
Its strong type system, memory safety, and performance optimizations make it well-suited for building reliable and efficient code in this context.
Agb leverages rust's unique features by using the type system to model the GBA's hardware.
This approach helps prevent common programming errors and allows developers to quickly build games that function correctly on the GBA platform.
In addition to safety and correctness, rust's performance optimizations are crucial for developing games on the GBA's slow processor.
With a limited amount of time per frame, every optimization counts, and rust's speed and efficiency help ensure that games built with agb run smoothly on the GBA hardware.
# What is in this book? # What is in this book?
This book is intended as an introduction to what **agb** has to offer, and should set you up nicely to start writing games of your own. This book serves as an introduction to agb, showcasing its capabilities and providing guidance on how to use it to build your own GBA games.
This book will not give a thorough overview of the specifics of the hardware implementation of the GBA unless it is needed as part of an explanation. It assumes that you have some experience with rust and game development, and provides detailed explanations of the unique challenges of writing games for the GBA.
An overview of the hardware can be found in chapter 2.
# Who is this book for? # Who is this book for?
This book is for: This book is ideal for anyone interested in writing games for the GBA using rust.
* **People who want to make games for the GBA.** First and foremost, games written using agb cannot run on any other platform except the GBA and emulators. If you don't want to write a game for the GBA, you should probably use a different library. If you're new to either rust or game development, you may want to start with some introductory resources before diving into this book.
* **People who have experience in rust.** Unless the rust specific syntax or semantics are important, we will not discuss details here and instead recommend reading the rust book before coming back. This book assumes a basic understanding of rust syntax and semantics, as well as game development concepts.
* **People with experience in writing games.** Game programming is hard, and harder still in rust on a GBA. We recommend writing a game for a more user friendly platform before coming back here.
If you fit into all of those categories, welcome!
It is super rewarding being able to play a game you made yourself on a piece of 20+ year old hardware.
# Helpful links # Helpful links
* [agb's GitHub](https://github.com/agbrs/agb) all development happens here * [agb's GitHub](https://github.com/agbrs/agb) is the primary development hub for the library.
* [agb's Discussion Page](https://github.com/agbrs/agb/discussions) a forum where you can ask for help on the usage of agb * [agb's Discussion Page](https://github.com/agbrs/agb/discussions) is a helpful forum where you can ask for help on using agb or share your projects with the community.
* [agb's crates.io page](https://crates.io/crates/agb) * [agb's crates.io page](https://crates.io/crates/agb) the latest version of the library on crates.io.
* [agb's documentation](https://docs.rs/agb) which is useful if you need a quick reference * [agb's documentation](https://docs.rs/agb) is a useful reference for the library's API and features.
* [Awesome Game Boy Advance development](https://github.com/gbdev/awesome-gbadev) contains links to popular libraries, emulators and the super friendly gbadev discord * [Awesome Game Boy Advance development](https://github.com/gbdev/awesome-gbadev) is a comprehensive resource for GBA development, with links to popular libraries, emulators, and the friendly gbadev Discord server.
* [Example game](https://lostimmortal.itch.io/the-hat-chooses-the-wizard) written using agb as part of the 2021 GMTK game jam. * [Example games](https://github.com/agbrs/agb/releases/latest) built using agb can be found in the `examples.zip` file attached to the latest release. Additionally, you can also check out [The Hat Chooses the Wizard](https://lostimmortal.itch.io/the-hat-chooses-the-wizard), a game written using agb as part of the GMTK 2021 game jam.
* [More example games](https://github.com/agbrs/agb/releases/latest) built using agb. See them in `examples.zip` attached to the latest release.
In addition to these resources, this book provides step-by-step instructions for getting started with agb.

View file

@ -1,25 +1,23 @@
# Learn agb part I - pong # Learn agb part I: Pong
In this section, we'll make a simple pong style game for the Game Boy Advance using `agb`. In this section, you'll learn how to make a simple pong-style game for the Game Boy Advance using agb.
You will learn: By following the steps in this section below, you'll gain an understanding of:
* How to use tiled graphics modes. * How to use tiled graphics modes.
* How to import graphics using `agb`. * How to import graphics using `agb`.
* What Game Boy Advance sprites are and how to put them on the screen. * What Game Boy Advance sprites are, how to create them, and how to display them on the screen.
* How to detect button input and react to it. * How to detect button input and use it to control game objects.
* How to add a static background. * How to add a static background to your game.
* How to make a dynamic background for a score display. * How to make a dynamic background to display scores.
* How to add music to your game. * How to add music and sound effects to your game.
* How to add sound effects to your game.
With this knowledge, you'll be well equipped to start making your own games! With this knowledge, you'll be well equipped to start making your own games for the GBA!
## Getting started ## Getting started
To start, create a new repository based on the [agb template](https://github.com/agbrs/template). To get started, create a new repository based on the [agb template](https://github.com/agbrs/template) and name it `pong`.
We'll call this `pong`.
Then replace the `name` field in `Cargo.toml` with `pong`, to end up with something similar to: Next, update the `name` field in `Cargo.toml` to `pong` like so:
```toml ```toml
[package] [package]
@ -31,4 +29,4 @@ edition = "2021"
# ... # ...
``` ```
You are now ready to get started learning about how `agb` works. Now, you're ready to dive and and start learning about `agb`!

View file

@ -4,14 +4,17 @@ In this section, we'll cover the importance of the Gba struct and how it gets cr
# The importance of the Gba struct # The importance of the Gba struct
Almost all interaction with the Game Boy Advance's hardware goes through the [Gba singleton struct](https://docs.rs/agb/latest/agb/struct.Gba.html). The [Gba singleton struct](https://docs.rs/agb/latest/agb/struct.Gba.html) is a crucial part of agb game development.
You should not create the Gba struct yourself, instead having it be passed into your main function. It is used for almost all interactions with the Game Boy Advance's hardware, such as graphics rendering, timer access and audio playback.
The Gba struct is used to take advantage of rust's borrow checker, and lean on it to ensure that access to the Game Boy Advance hardware is done 'sensibly'. You should not create the Gba struct yourself. Instead, it is passed to your main function as an owned reference.
You won't have to worry about 2 bits of your code modifying data in the wrong way! This allows rust's borrow checker to ensure that access to the Game Boy Advance hardware is done in a safe and sensible manner, preventing two bits of your code from modifying data in the wrong way.
# How all agb games start # How all agb games start
To use the Gba struct in your agb game, you'll need to create a function (normally called `main`) which takes an owned reference to the Gba instance.
The recommended way to do this is by using the `#[agb::entry]` attribute macro provided by the `agb` crate.
Replace the content of the `main` function with the following: Replace the content of the `main` function with the following:
```rust,ignore ```rust,ignore
@ -23,15 +26,14 @@ loop {} // infinite loop for now
# } # }
``` ```
and ignore warnings for now. This creates an infinite loop and allows you to start building your game.
# Running your pong game # Running your pong game
Although there isn't much to see at the moment (just a black screen), you can start the game by using `cargo run` or whatever worked for you in the introduction. At this point, your game won't do much except display a black screen. To run your game, use the `cargo run` command as before.
# What we did # What we covered
This was a very simple but incredibly important part of any game using `agb`. In this section, we covered the importance of the Gba struct in agb game development.
All interactions with the hardware are gated via the Gba struct, which you never create yourself. By using the Gba struct as a gatekeeper for all hardware interactions, you can ensure that your code is safe and efficient.
You are now ready to learn about sprites and start getting things onto the screen!
You are now ready to learn about display modes and how to start getting things onto the screen!

View file

@ -1,56 +1,44 @@
# Sprites # Sprites
In this section, we'll put the sprites needed for our pong game onto the screen. In this section, we'll cover what sprites are in the Game Boy Advance and how to put them on the screen in our pong game.
We'll cover what sprites are in the Game Boy Advance, and how to get them to show up on screen. We'll briefly cover vblank, and by the end of this section, you'll have a ball bouncing around the screen!
We'll briefly cover vblank and by the end of this section, you'll have a ball bouncing around the screen!
# Why do we need sprites in the first place? # Why do we need sprites?
The Game Boy Advance has a 240x160px screen, with 15-bit RGB colour support. The Game Boy Advance has a 240x160px screen with 15-bit RGB color support. Setting the color for each pixel manually would require updating 38,400 pixels per frame, or 2,304,000 pixels per second at 60 fps.
In order to manually set the colour for each pixel in the screen, you would need to update a total of 38,400 pixels per frame, or 2,304,000 pixels per second at 60 fps. With a 16 MHz processor, this means calculating 1 pixel every 8 clock cycles, which is pretty much impossible.
With a 16MHz processor, that means you would need to be able to calculate 1 pixel every 8 clock cycles, which is pretty much impossible. he Game Boy Advance provides two ways to easily put pixels on the screen: tiles and sprites.
You could get clever with how you update these pixels, but using the tools provided by the Game Boy Advance to put pixels on the screen, you'll have a much easier time.
So there are 2 ways that the Game Boy Advance allows you to get these pixels on screen much more easily.
Tiles and sprites.
Tiles are 8x8 pixels in size and can be placed in a grid on the screen. Tiles are 8x8 pixels in size and can be placed in a grid on the screen.
You can also scroll the whole tile layer to arbitrary positions, but the tiles will remain in this 8x8 pixel grid. You can also scroll the whole tile layer to arbitrary positions, but the tiles will remain in this 8x8 pixel grid.
We'll cover tiles in more detail later.
The other way you can draw things on screen is using sprites, which we'll cover in more detail in this section. Sprites are the other way to draw things on the screen, which we'll cover in this section.
The Game Boy Advance supports 256 hardware sprites, with different sizes ranging from square 8x8 to more exotic sizes like 8x32 pixels.
In our pong game, all the sprites will be 16x16 pixels to make things simpler.
# Sprites on the Game Boy Advance Sprites are stored in a special area of video memory called the 'Object Attribute Memory' (OAM).
OAM has space for the 'attributes' of the sprites, such as their location, whether or not they are visible, and which tile to use, but it does not store the actual pixel data.
The pixel data is stored in video RAM (VRAM).
This split allows multiple sprites to refer to the same tiles in VRAM, which saves space and allows for more objects on screen than would be possible by repeating them.
The Game Boy Advance supports 256 hardware sprites. Since RAM is in short supply and expensive, the tile data is stored as indexed palette data.
These can be in one of many sizes, ranging from square 8x8 to more exotic sizes like 8x32 pixels. Instead of storing the full color data for each pixel in the tile, the Game Boy Advance stores a 'palette' of colors, and the tiles that make up the sprites are stored as indexes to the palette.
For our pong game, all the sprites will be 16x16 pixels to make things a bit simpler. Each sprite can use a maximum of 16 colors out of the total sprite palette of 256 colors.
Sprites are stored in the Game Boy Advance in a special area of video memory called the 'Object Attribute Memory' (OAM). There are technically two types of sprites: regular and affine sprites.
This has space for the 'attributes' of the sprites (things like whether or not they are visible, the location, which tile to use etc) but it does not store the actual pixel data.
The pixel data is stored in a video RAM (VRAM).
Because of this split, it is possible to have multiple sprites refer to the same tiles in video RAM which saves space and allows for more objects on screen at once then repeating them would otherwise allow.
Since RAM is in short supply, and at the time was quite expensive, the tile data is stored as indexed palette data.
So rather than storing the full colour data for each pixel in the tile, the Game Boy Advance instead stores a 'palette' of colours and the tiles which make up the sprites are stored as indexes to the palette.
You don't need to worry about this though, because `agb` handles it for you, but it is important to keep in mind that each sprite can use a maximum of 16 colours out of the total sprite palette of 256 colours.
There are technically 2 types of sprite, regular and affine sprites.
For now, we will only be dealing with regular sprites. For now, we will only be dealing with regular sprites.
# Import the sprite # Import the sprite
Firstly, you're going to need to import the sprites into your project. Firstly, you're going to need to import the sprites into your project.
`agb` has great support for the [aseprite](https://www.aseprite.org/) sprite editor which can be bought for $20 or you can compile it yourself for free. `agb` has excellent support for the [aseprite](https://www.aseprite.org/) sprite editor which can be bought for $20 or you can compile it yourself for free.
Aseprite files can be natively imported by `agb` for use on the Game Boy Advance. Aseprite files can be natively imported by `agb` for use on the Game Boy Advance.
Here is the sprite sheet we will use as a png, but you should [download the aseprite file](sprites.aseprite) and place it in `gfx/sprites.aseprite`. Here is the sprite sheet we will use as a png, but you should [download the aseprite file](sprites.aseprite) and place it in `gfx/sprites.aseprite`.
![pong sprites](sprites.png) ![pong sprites](sprites.png)
This contains 5 `16x16px` sprites. This contains 5 `16x16px` sprites: the end cap for the paddle, the center part of the paddle, which could potentially be repeated a few times, and the ball with various squashed states.
The first is the end cap for the paddle. The aseprite file defines tags for these sprites: "Paddle End," "Paddle Mid," and "Ball."
The second is the centre part of the paddle, which could potentially be repeated a few times.
The third until the fifth is the ball, with various squashed states.
The aseprite file defines tags for these sprites, being "Paddle End", "Paddle Mid", and "Ball".
```rust ```rust
use agb::{ use agb::{

View file

@ -1,31 +1,71 @@
# Building the template # Building and running the agb template
By the end of this section, you should be able to build and run the **agb** template. In this section, you will learn how to build and run the agb template.
By the end of this section, you will have a working GBA game that you can run on your emulator of choice.
# 1. Get the source code ## 1. Clone the repository
The source code can be fetched using `git clone https://github.com/agbrs/template.git`. The first step is to clone the agb template repository using Git.
Open a terminal or command prompt and run the following command:
# 2. Build the template ```sh
git clone https://github.com/agbrs/template.git
```
Build a copy of the template using `cargo build --release`. This will create a copy of the agb template repository on your local machine.
This could take quite a while, but eventually you'll end up with a copy of the template in `target/thumbv4t-none-eabi/release/template` or `target/thumbv4t-none-eabi/release/template.elf` depending on platform.
This can be run directly by some emulators, but we need to run an extra step in order to convert the elf file into a '.gba' file. ## 2. Build the template
Next, navigate to the `template` directory in the repository and build the template using the following command:
```sh
cd template
cargo build --release
```
This command will compile the agb template in release mode.
The resulting binary file can be found in the `target/thumbv4t-none-eabi/release` directory.
Depending on your platform, the file will have either a `.elf` extension or no extension.
## 3. Convert the binary to a GBA file
In order to run the game on an emulator, we need to convert the binary file to a GBA file.
To do this, we'll use two tools: `arm-none-eabi-objcopy` and `gbafix`.
Run the following command to convert the binary file to a GBA file:
```sh ```sh
arm-none-eabi-objcopy -O binary target/thumbv4t-none-eabi/release/template template.gba arm-none-eabi-objcopy -O binary target/thumbv4t-none-eabi/release/template template.gba
gbafix template.gba
``` ```
or or
```sh ```sh
arm-none-eabi-objcopy -O binary target/thumbv4t-none-eabi/release/template.elf template.gba arm-none-eabi-objcopy -O binary target/thumbv4t-none-eabi/release/template.elf template.gba
```
Depending on whether your file has the .elf extension.
This command will create a template.gba file in the template directory.
Next, run the following command to fix the GBA header:
```sh
gbafix template.gba gbafix template.gba
``` ```
And then load the resulting file in your emulator of choice. This command will add the correct GBA header to the template.gba file.
That's all there is to it!
If you have `mgba-qt` in your path, then you can launch the template directly using `cargo run --release`. ## 4. Run the game
Finally, you can run the game on your emulator of choice.
Load the template.gba file in your emulator, and you should see the agb template running.
If you have mgba-qt installed on your machine, you can run the game directly from the command line using the following command:
```sh
cargo run --release
```
This will build and run the agb template in a single step.
That's it! You now have a working agb template that you can use as a starting point for your own GBA game.

View file

@ -1,6 +1,6 @@
# Running an example # Running an example
In this section, we will get to the point where you can build and run the game built for the GMTK game jam using agb known as 'The Hat Chooses the Wizard'. In this section, we will get to the point where you can build and run the agb template repository.
This will prove that your development environment is ready for the future tutorials and later building. This will prove that your development environment is ready for the future tutorials and later building.
You can run the game using real hardware and a flash card. You can run the game using real hardware and a flash card.

View file

@ -4,31 +4,31 @@ This guide has been tested on Ubuntu, Arch Linux and Raspberry Pi OS running on
# 1. Install a recent version of rust # 1. Install a recent version of rust
agb unfortunately relies on a few nightly rust features, so you need to ensure you have that installed. To use agb, you'll need to use nightly rust since it requires a few nightly features.
Firstly, ensure that you have **rustup** installed which you can do by following the instructions on the [rust website](https://www.rust-lang.org/tools/install) Firstly, ensure that you have **rustup** installed which you can do by following the instructions on the [rust website](https://www.rust-lang.org/tools/install)
You can update rustup with `rustup update` if you have already installed it. If you have already installed rustup, you can update it with `rustup update`.
# 2. arm-none-eabi # 2. arm-none-eabi
We need this installed in order to be able to assemble the small amount of assembly in agb, and to do the final linking. To assemble the small amount of assembly in agb and to do the final linking, you'll need to install the `arm-none-eabi` binutils.
* On Debian and derivatives (like Ubuntu): `sudo apt install binutils-arm-none-eabi` * On Debian and derivatives (like Ubuntu): `sudo apt install binutils-arm-none-eabi`
* On Arch Linux and derivatives: `pacman -S arm-none-eabi-binutils` * On Arch Linux and derivatives: `pacman -S arm-none-eabi-binutils`
# 3. git # 3. git
The source code for the game is hosted on github, so you will need git installed. The source code for the game is hosted on github, so you will need to install git.
* On Debian and derivatives (like Ubuntu): `sudo apt install git` * On Debian and derivatives (like Ubuntu): `sudo apt install git`
* On Arch Linux and derivatives: `pacman -S git` * On Arch Linux and derivatives: `pacman -S git`
# 4. gbafix # 4. gbafix
In order to be able to play on real hardware or on some emulators, you may need to install 'gbafix'. In order to be able to play games made with agb on real hardware or on some emulators, you will need to install 'gbafix'.
The rust implementation can be installed very easily using `cargo install gbafix`. The rust implementation can be installed very easily using `cargo install gbafix`.
Make sure that the Cargo bin directory is in your `PATH` as we'll need to use it later. Make sure that the Cargo bin directory is in your `PATH` as we'll need to use it later.
That is all you need to get started. That is all you need to get started!
You can now move on to 'building the game'. You can now move on to 'building the game'.

View file

@ -4,14 +4,14 @@ This guide has been tested on MacOS 13.0.1 on an M1 chip.
# 1. Install a recent version of rust # 1. Install a recent version of rust
agb unfortunately relies on a few nightly rust features, so you need to ensure you have that installed. To use agb, you'll need to use nightly rust since it requires a few nightly features.
Firstly, ensure that you have **rustup** installed which you can do by following the instructions on the [rust website](https://www.rust-lang.org/tools/install) Firstly, ensure that you have **rustup** installed which you can do by following the instructions on the [rust website](https://www.rust-lang.org/tools/install)
You can update rustup with `rustup update` if you have already installed it. If you have already installed rustup, you can update it with `rustup update`.
# 2. Install arm-none-eabi # 2. Install arm-none-eabi
We need this installed in order to be able to assemble the small amount of assembly in agb, and to do the final linking. To assemble the small amount of assembly in agb and to do the final linking, you'll need to install the `arm-none-eabi` binutils.
## Install from ARM ## Install from ARM
@ -43,10 +43,10 @@ After installing to your `/Applications` folder you can add the binary to your p
# 5. Real hardware - gbafix # 5. Real hardware - gbafix
In order to be able to play on real hardware or on some emulators, you may need to install 'gbafix'. In order to be able to play games made with agb on real hardware or on some emulators, you will need to install 'gbafix'.
The rust implementation can be installed very easily using `cargo install gbafix`. The rust implementation can be installed very easily using `cargo install gbafix`.
Make sure that the Cargo bin directory is in your `PATH` as we'll need to use it later. Make sure that the Cargo bin directory is in your `PATH` as we'll need to use it later.
That is all you need to get started. That is all you need to get started!
You can now move on to 'building the game'. You can now move on to 'building the game'.

View file

@ -23,7 +23,7 @@ dependencies = [
"agb_macros", "agb_macros",
"agb_sound_converter", "agb_sound_converter",
"bare-metal", "bare-metal",
"bitflags", "bitflags 2.0.2",
"modular-bitfield", "modular-bitfield",
"rustc-hash", "rustc-hash",
] ]
@ -45,7 +45,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn", "syn 2.0.8",
"toml", "toml",
] ]
@ -55,7 +55,7 @@ version = "0.13.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -65,7 +65,7 @@ dependencies = [
"hound", "hound",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -85,7 +85,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891" checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"byteorder", "byteorder",
"flate2", "flate2",
"image", "image",
@ -121,10 +121,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bytemuck" name = "bitflags"
version = "1.13.0" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
[[package]]
name = "bytemuck"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -259,15 +265,15 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.5" version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.139" version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "libflate" name = "libflate"
@ -326,7 +332,7 @@ checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
] ]
[[package]] [[package]]
@ -378,9 +384,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "png" name = "png"
@ -388,7 +394,7 @@ version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"crc32fast", "crc32fast",
"deflate", "deflate",
"miniz_oxide 0.3.7", "miniz_oxide 0.3.7",
@ -396,18 +402,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.50" version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -426,35 +432,35 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.12" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.91" version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -469,9 +475,20 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.107" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -531,9 +548,9 @@ checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "version_check" name = "version_check"

View file

@ -20,3 +20,4 @@ debug = true
panic = "abort" panic = "abort"
lto = true lto = true
debug = true debug = true
codegen-units = 1

View file

@ -74,6 +74,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -72,6 +72,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
components = ["rust-src", "clippy"] components = ["rust-src", "clippy", "rustfmt"]

View file

@ -23,7 +23,7 @@ dependencies = [
"agb_macros", "agb_macros",
"agb_sound_converter", "agb_sound_converter",
"bare-metal", "bare-metal",
"bitflags", "bitflags 2.0.2",
"modular-bitfield", "modular-bitfield",
"rustc-hash", "rustc-hash",
] ]
@ -45,7 +45,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn", "syn 2.0.8",
"toml", "toml",
] ]
@ -55,7 +55,7 @@ version = "0.13.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -65,7 +65,7 @@ dependencies = [
"hound", "hound",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -85,7 +85,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891" checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"byteorder", "byteorder",
"flate2", "flate2",
"image", "image",
@ -112,10 +112,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bytemuck" name = "bitflags"
version = "1.13.0" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
[[package]]
name = "bytemuck"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -170,7 +176,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253" checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
dependencies = [ dependencies = [
"hashbrown", "hashbrown 0.11.2",
"ttf-parser", "ttf-parser",
] ]
@ -194,6 +200,12 @@ dependencies = [
"ahash", "ahash",
] ]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hound" name = "hound"
version = "3.5.0" version = "3.5.0"
@ -205,7 +217,6 @@ name = "hyperspace-roll"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"agb", "agb",
"bare-metal",
] ]
[[package]] [[package]]
@ -224,10 +235,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "libc" name = "indexmap"
version = "0.2.139" version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "libc"
version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "log" name = "log"
@ -238,6 +259,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.3.7" version = "0.3.7"
@ -274,7 +301,7 @@ checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
] ]
[[package]] [[package]]
@ -326,9 +353,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "png" name = "png"
@ -336,7 +363,7 @@ version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"crc32fast", "crc32fast",
"deflate", "deflate",
"miniz_oxide 0.3.7", "miniz_oxide 0.3.7",
@ -344,18 +371,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.50" version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -368,22 +395,31 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
]
[[package]]
name = "serde_spanned"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
dependencies = [
"serde",
] ]
[[package]] [[package]]
@ -394,9 +430,20 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.107" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -405,11 +452,36 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.19.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
] ]
[[package]] [[package]]
@ -420,9 +492,9 @@ checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "version_check" name = "version_check"
@ -435,3 +507,12 @@ name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winnow"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
dependencies = [
"memchr",
]

View file

@ -8,14 +8,13 @@ edition = "2021"
[dependencies] [dependencies]
agb = { version = "0.13.0", path = "../../agb" } agb = { version = "0.13.0", path = "../../agb" }
bare-metal = "1"
[profile.dev] [profile.dev]
opt-level = 2 opt-level = 2
debug = true debug = true
[profile.release] [profile.release]
panic = "abort" panic = "abort"
lto = true lto = true
debug = true debug = true
codegen-units = 1

View file

@ -74,6 +74,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -72,6 +72,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
components = ["rust-src", "clippy"] components = ["rust-src", "clippy", "rustfmt"]

View file

@ -23,7 +23,7 @@ dependencies = [
"agb_macros", "agb_macros",
"agb_sound_converter", "agb_sound_converter",
"bare-metal", "bare-metal",
"bitflags", "bitflags 2.0.2",
"modular-bitfield", "modular-bitfield",
"rustc-hash", "rustc-hash",
] ]
@ -45,7 +45,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn", "syn 2.0.8",
"toml", "toml",
] ]
@ -55,7 +55,7 @@ version = "0.13.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -65,7 +65,7 @@ dependencies = [
"hound", "hound",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -85,7 +85,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891" checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"byteorder", "byteorder",
"flate2", "flate2",
"image", "image",
@ -112,10 +112,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bytemuck" name = "bitflags"
version = "1.13.0" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
[[package]]
name = "bytemuck"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -170,7 +176,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253" checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
dependencies = [ dependencies = [
"hashbrown", "hashbrown 0.11.2",
"ttf-parser", "ttf-parser",
] ]
@ -194,6 +200,12 @@ dependencies = [
"ahash", "ahash",
] ]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hound" name = "hound"
version = "3.5.0" version = "3.5.0"
@ -216,16 +228,26 @@ dependencies = [
] ]
[[package]] [[package]]
name = "itoa" name = "indexmap"
version = "1.0.5" version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.139" version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "log" name = "log"
@ -236,6 +258,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.3.7" version = "0.3.7"
@ -272,7 +300,7 @@ checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
] ]
[[package]] [[package]]
@ -324,9 +352,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "png" name = "png"
@ -334,7 +362,7 @@ version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"crc32fast", "crc32fast",
"deflate", "deflate",
"miniz_oxide 0.3.7", "miniz_oxide 0.3.7",
@ -342,18 +370,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.50" version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -366,41 +394,50 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.12" version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.91" version = "1.0.94"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
"serde", "serde",
] ]
[[package]]
name = "serde_spanned"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "static_assertions" name = "static_assertions"
version = "1.1.0" version = "1.1.0"
@ -409,9 +446,20 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.107" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -429,11 +477,36 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.19.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
] ]
[[package]] [[package]]
@ -444,9 +517,9 @@ checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "version_check" name = "version_check"
@ -459,3 +532,12 @@ name = "wasi"
version = "0.11.0+wasi-snapshot-preview1" version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winnow"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
dependencies = [
"memchr",
]

View file

@ -74,6 +74,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
components = ["rust-src", "clippy"] components = ["rust-src", "clippy", "rustfmt"]

View file

@ -23,7 +23,7 @@ dependencies = [
"agb_macros", "agb_macros",
"agb_sound_converter", "agb_sound_converter",
"bare-metal", "bare-metal",
"bitflags", "bitflags 2.0.2",
"modular-bitfield", "modular-bitfield",
"rustc-hash", "rustc-hash",
] ]
@ -45,7 +45,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"serde", "serde",
"syn", "syn 2.0.8",
"toml", "toml",
] ]
@ -55,7 +55,7 @@ version = "0.13.0"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -65,7 +65,7 @@ dependencies = [
"hound", "hound",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -85,7 +85,7 @@ version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891" checksum = "10a71de7aecd2d0a76ec90fde2c443d12667c737d92de76bd187f101eca37891"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"byteorder", "byteorder",
"flate2", "flate2",
"image", "image",
@ -121,10 +121,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bytemuck" name = "bitflags"
version = "1.13.0" version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
[[package]]
name = "bytemuck"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -185,7 +191,7 @@ version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253" checksum = "6a62391ecb864cf12ed06b2af4eda2e609b97657950d6a8f06841b17726ab253"
dependencies = [ dependencies = [
"hashbrown", "hashbrown 0.11.2",
"ttf-parser", "ttf-parser",
] ]
@ -218,6 +224,12 @@ dependencies = [
"ahash", "ahash",
] ]
[[package]]
name = "hashbrown"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hound" name = "hound"
version = "3.5.0" version = "3.5.0"
@ -240,10 +252,20 @@ dependencies = [
] ]
[[package]] [[package]]
name = "libc" name = "indexmap"
version = "0.2.139" version = "1.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [
"autocfg",
"hashbrown 0.12.3",
]
[[package]]
name = "libc"
version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "libflate" name = "libflate"
@ -266,6 +288,12 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
] ]
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.3.7" version = "0.3.7"
@ -302,7 +330,7 @@ checksum = "5a7d5f7076603ebc68de2dc6a650ec331a062a13abaa346975be747bbfa4b789"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
] ]
[[package]] [[package]]
@ -354,9 +382,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "png" name = "png"
@ -364,7 +392,7 @@ version = "0.16.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
dependencies = [ dependencies = [
"bitflags", "bitflags 1.3.2",
"crc32fast", "crc32fast",
"deflate", "deflate",
"miniz_oxide 0.3.7", "miniz_oxide 0.3.7",
@ -372,18 +400,18 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.50" version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@ -402,22 +430,31 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.152" version = "1.0.158"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
]
[[package]]
name = "serde_spanned"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
dependencies = [
"serde",
] ]
[[package]] [[package]]
@ -428,9 +465,20 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.107" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -466,11 +514,36 @@ dependencies = [
[[package]] [[package]]
name = "toml" name = "toml"
version = "0.5.11" version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
dependencies = [ dependencies = [
"serde", "serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.19.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
dependencies = [
"indexmap",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
] ]
[[package]] [[package]]
@ -481,9 +554,9 @@ checksum = "7b3e06c9b9d80ed6b745c7159c40b311ad2916abb34a49e9be2653b90db0d8dd"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "version_check" name = "version_check"
@ -497,6 +570,15 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winnow"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "xml-rs" name = "xml-rs"
version = "0.8.4" version = "0.8.4"

View file

@ -74,6 +74,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -72,6 +72,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
components = ["rust-src", "clippy"] components = ["rust-src", "clippy", "rustfmt"]

View file

@ -34,6 +34,13 @@ _build_docs crate:
clean: clean:
just _all-crates _clean just _all-crates _clean
fmt:
just _all-crates _fmt
just _fmt tools
fmt-check:
just _all-crates _fmt-check
just _fmt-check tools
run-example example: run-example example:
just _build-example "{{example}}" just _build-example "{{example}}"
mgba-qt "$CARGO_TARGET_DIR/thumbv4t-none-eabi/debug/examples/{{example}}" mgba-qt "$CARGO_TARGET_DIR/thumbv4t-none-eabi/debug/examples/{{example}}"
@ -52,7 +59,7 @@ check-linker-script-consistency:
find -type f -name gba.ld -print0 | xargs -0 -n1 cmp -- agb/gba.ld find -type f -name gba.ld -print0 | xargs -0 -n1 cmp -- agb/gba.ld
find -type f -name gba_mb.ld -print0 | xargs -0 -n1 cmp -- agb/gba_mb.ld find -type f -name gba_mb.ld -print0 | xargs -0 -n1 cmp -- agb/gba_mb.ld
ci: check-linker-script-consistency build-debug clippy test build-release test-release doctest-agb build-roms build-book check-docs ci: check-linker-script-consistency build-debug clippy fmt-check test build-release test-release doctest-agb build-roms build-book check-docs
build-roms: build-roms:
just _build-rom "examples/the-purple-night" "PURPLENIGHT" just _build-rom "examples/the-purple-night" "PURPLENIGHT"
@ -94,7 +101,7 @@ _build-rom folder name:
TARGET_FOLDER="${CARGO_TARGET_DIR:-$GAME_FOLDER/target}" TARGET_FOLDER="${CARGO_TARGET_DIR:-$GAME_FOLDER/target}"
GBA_FILE="$TARGET_FOLDER/$GAME_NAME.gba" GBA_FILE="$TARGET_FOLDER/$GAME_NAME.gba"
(cd "$GAME_FOLDER" && cargo build --release --target thumbv4t-none-eabi && cargo clippy --release --target thumbv4t-none-eabi -- {{CLIPPY_ARGUMENTS}}) (cd "$GAME_FOLDER" && cargo build --release --target thumbv4t-none-eabi && cargo clippy --release --target thumbv4t-none-eabi -- {{CLIPPY_ARGUMENTS}} && cargo fmt --all -- --check)
mkdir -p examples/target/examples mkdir -p examples/target/examples
@ -127,6 +134,10 @@ _clippy crate:
(cd "{{crate}}" && cargo clippy --examples --tests -- {{CLIPPY_ARGUMENTS}}) (cd "{{crate}}" && cargo clippy --examples --tests -- {{CLIPPY_ARGUMENTS}})
_clean crate: _clean crate:
(cd "{{crate}}" && cargo clean) (cd "{{crate}}" && cargo clean)
_fmt crate:
(cd "{{crate}}" && cargo fmt --all)
_fmt-check crate:
(cd "{{crate}}" && cargo fmt --all -- --check)
_build-example example: _build-example example:
(cd agb && cargo build "--example={{example}}") (cd agb && cargo build "--example={{example}}")

View file

@ -19,9 +19,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.68" version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]] [[package]]
name = "autocfg" name = "autocfg"
@ -37,9 +37,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "bytemuck" name = "bytemuck"
version = "1.13.0" version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c041d3eab048880cb0b86b256447da3f18859a163c3b8d8893f4e6368abe6393" checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@ -49,9 +49,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.78" version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
dependencies = [ dependencies = [
"jobserver", "jobserver",
] ]
@ -103,18 +103,18 @@ dependencies = [
[[package]] [[package]]
name = "jobserver" name = "jobserver"
version = "0.1.25" version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" checksum = "936cfd212a0155903bcbc060e316fb6cc7cbf2e1907329391ebadc1fe0ce77c2"
dependencies = [ dependencies = [
"libc", "libc",
] ]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.139" version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "memchr" name = "memchr"
@ -185,9 +185,9 @@ dependencies = [
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.7.1" version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
dependencies = [ dependencies = [
"aho-corasick", "aho-corasick",
"memchr", "memchr",
@ -196,6 +196,6 @@ dependencies = [
[[package]] [[package]]
name = "regex-syntax" name = "regex-syntax"
version = "0.6.28" version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"

View file

@ -17,3 +17,4 @@ debug = true
panic = "abort" panic = "abort"
lto = true lto = true
debug = true debug = true
codegen-units = 1

View file

@ -74,6 +74,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -72,6 +72,10 @@ SECTIONS {
__ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start; __ewram_rom_length_bytes = __ewram_data_end - __ewram_data_start;
__ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2; __ewram_rom_length_halfwords = (__ewram_rom_length_bytes + 1) / 2;
.shstrtab : {
*(.shstrtab)
}
/* debugging sections */ /* debugging sections */
/* Stabs */ /* Stabs */
.stab 0 : { *(.stab) } .stab 0 : { *(.stab) }

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly" channel = "nightly"
components = ["rust-src", "clippy"] components = ["rust-src", "clippy", "rustfmt"]

213
tools/Cargo.lock generated
View file

@ -31,9 +31,9 @@ checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.78" version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -43,9 +43,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "chrono" name = "chrono"
version = "0.4.23" version = "0.4.24"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f" checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
dependencies = [ dependencies = [
"iana-time-zone", "iana-time-zone",
"js-sys", "js-sys",
@ -58,9 +58,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.1.2" version = "4.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e638668a62aced2c9fb72b5135a33b4a500485ccf2a0e402e09aa04ab2fc115" checksum = "3c911b090850d79fc64fe9ea01e28e465f65e821e08813ced95bced72f7a8a9b"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"clap_lex", "clap_lex",
@ -71,9 +71,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_lex" name = "clap_lex"
version = "0.3.1" version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade" checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646"
dependencies = [ dependencies = [
"os_str_bytes", "os_str_bytes",
] ]
@ -96,9 +96,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]] [[package]]
name = "cxx" name = "cxx"
version = "1.0.87" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b61a7545f753a88bcbe0a70de1fcc0221e10bfc752f576754fa91e663db1622e" checksum = "a9c00419335c41018365ddf7e4d5f1c12ee3659ddcf3e01974650ba1de73d038"
dependencies = [ dependencies = [
"cc", "cc",
"cxxbridge-flags", "cxxbridge-flags",
@ -108,9 +108,9 @@ dependencies = [
[[package]] [[package]]
name = "cxx-build" name = "cxx-build"
version = "1.0.87" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f464457d494b5ed6905c63b0c4704842aba319084a0a3561cdc1359536b53200" checksum = "fb8307ad413a98fff033c8545ecf133e3257747b3bae935e7602aab8aa92d4ca"
dependencies = [ dependencies = [
"cc", "cc",
"codespan-reporting", "codespan-reporting",
@ -118,24 +118,24 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"scratch", "scratch",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
name = "cxxbridge-flags" name = "cxxbridge-flags"
version = "1.0.87" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43c7119ce3a3701ed81aca8410b9acf6fc399d2629d057b87e2efa4e63a3aaea" checksum = "edc52e2eb08915cb12596d29d55f0b5384f00d697a646dbd269b6ecb0fbd9d31"
[[package]] [[package]]
name = "cxxbridge-macro" name = "cxxbridge-macro"
version = "1.0.87" version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "65e07508b90551e610910fa648a1878991d367064997a596135b86df30daf07e" checksum = "631569015d0d8d54e6c241733f944042623ab6df7bc3be7466874b05fcdb1c5f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 2.0.8",
] ]
[[package]] [[package]]
@ -173,25 +173,22 @@ checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.2.6" version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "iana-time-zone" name = "iana-time-zone"
version = "0.1.53" version = "0.1.54"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64c122667b287044802d6ce17ee2ddf13207ed924c712de9a66a5814d5b64765" checksum = "0c17cc76786e99f8d2f055c11159e7f0091c42474dcc3189fbab96072e873e6d"
dependencies = [ dependencies = [
"android_system_properties", "android_system_properties",
"core-foundation-sys", "core-foundation-sys",
"iana-time-zone-haiku", "iana-time-zone-haiku",
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",
"winapi", "windows",
] ]
[[package]] [[package]]
@ -216,19 +213,20 @@ dependencies = [
[[package]] [[package]]
name = "io-lifetimes" name = "io-lifetimes"
version = "1.0.4" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e" checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
dependencies = [ dependencies = [
"hermit-abi",
"libc", "libc",
"windows-sys", "windows-sys",
] ]
[[package]] [[package]]
name = "is-terminal" name = "is-terminal"
version = "0.4.2" version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e"
dependencies = [ dependencies = [
"hermit-abi", "hermit-abi",
"io-lifetimes", "io-lifetimes",
@ -238,18 +236,18 @@ dependencies = [
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.60" version = "0.3.61"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.139" version = "0.2.140"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
[[package]] [[package]]
name = "link-cplusplus" name = "link-cplusplus"
@ -281,15 +279,6 @@ version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "nom8"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.45" version = "0.1.45"
@ -311,39 +300,39 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.17.0" version = "1.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
[[package]] [[package]]
name = "os_str_bytes" name = "os_str_bytes"
version = "6.4.1" version = "6.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.50" version = "1.0.53"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.23" version = "1.0.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]] [[package]]
name = "rustix" name = "rustix"
version = "0.36.7" version = "0.36.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03" checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"errno", "errno",
@ -355,9 +344,9 @@ dependencies = [
[[package]] [[package]]
name = "scratch" name = "scratch"
version = "1.0.3" version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddccb15bcce173023b3fedd9436f882a0739b8dfb45e4f6b6002bee5929f61b2" checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
[[package]] [[package]]
name = "strsim" name = "strsim"
@ -367,9 +356,20 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.107" version = "1.0.109"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -398,19 +398,19 @@ dependencies = [
[[package]] [[package]]
name = "toml_datetime" name = "toml_datetime"
version = "0.5.1" version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4553f467ac8e3d374bc9a177a26801e5d0f9b211aa1673fb137a403afd1c9cf5" checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.18.0" version = "0.19.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "729bfd096e40da9c001f778f5cdecbd2957929a24e10e5883d9392220a751581" checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"nom8",
"toml_datetime", "toml_datetime",
"winnow",
] ]
[[package]] [[package]]
@ -425,9 +425,9 @@ dependencies = [
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
@ -443,9 +443,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.83" version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@ -453,24 +453,24 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.83" version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.83" version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -478,22 +478,22 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.83" version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn 1.0.109",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.83" version = "0.2.84"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
[[package]] [[package]]
name = "winapi" name = "winapi"
@ -527,10 +527,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "windows-sys" name = "windows"
version = "0.42.0" version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" checksum = "cdacb41e6a96a052c6cb63a144f24900236121c6f63f4f8219fef5977ecb0c25"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm",
"windows_aarch64_msvc", "windows_aarch64_msvc",
@ -543,42 +561,51 @@ dependencies = [
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.42.1" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.42.1" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.42.1" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.42.1" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.42.1" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.42.1" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.42.1" version = "0.42.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "winnow"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "deac0939bd6e4f24ab5919fbf751c97a8cfc8543bb083a305ed5c0c10bb241d1"
dependencies = [
"memchr",
]

View file

@ -7,6 +7,6 @@ edition = "2021"
[dependencies] [dependencies]
clap = "4" clap = "4"
toml_edit = "0.18" toml_edit = "0.19"
glob = "0.3" glob = "0.3"
chrono = "0.4" chrono = "0.4"