mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-23 16:21:33 +11:00
Merge pull request #160 from gwilymk/make-agb-entry-create-gba-struct
Make agb entry create gba struct
This commit is contained in:
commit
a9e728a037
|
@ -2,9 +2,9 @@
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
|
|
||||||
use proc_macro2::Span;
|
use proc_macro2::Span;
|
||||||
use quote::quote;
|
use quote::{quote, ToTokens};
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use syn::{Ident, ItemFn, ReturnType, Type, Visibility};
|
use syn::{FnArg, Ident, ItemFn, Pat, ReturnType, Token, Type, Visibility};
|
||||||
|
|
||||||
#[proc_macro_attribute]
|
#[proc_macro_attribute]
|
||||||
pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
|
@ -15,16 +15,43 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
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.inputs.is_empty()
|
|
||||||
&& f.sig.generics.params.is_empty()
|
&& f.sig.generics.params.is_empty()
|
||||||
&& f.sig.generics.where_clause.is_none()
|
&& f.sig.generics.where_clause.is_none()
|
||||||
&& 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 () -> !"
|
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Check that the function signature takes 1 argument, agb::Gba
|
||||||
|
let arguments: Vec<_> = f.sig.inputs.iter().collect();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
arguments.len(),
|
||||||
|
1,
|
||||||
|
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !, but got {} arguments",
|
||||||
|
arguments.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let (argument_type, (argument_name, is_mutable)) = match arguments[0] {
|
||||||
|
FnArg::Typed(pat_type) => (
|
||||||
|
pat_type.ty.to_token_stream(),
|
||||||
|
match &*pat_type.pat {
|
||||||
|
Pat::Ident(ident) => {
|
||||||
|
assert!(
|
||||||
|
ident.attrs.is_empty() && ident.by_ref.is_none() && ident.subpat.is_none(),
|
||||||
|
"#[agb::entry] must have signature [unsafe] fn (mut agb::Gba) -> !"
|
||||||
|
);
|
||||||
|
|
||||||
|
(ident.ident.clone(), ident.mutability.is_some())
|
||||||
|
}
|
||||||
|
_ => panic!("Expected first argument to #[agb::entry] to be a basic identifier"),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_ => panic!("Expected first argument to #[agb::entry] to not be self"),
|
||||||
|
};
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
args.to_string() == "",
|
args.to_string() == "",
|
||||||
"Must pass no args to #[agb::entry] macro"
|
"Must pass no args to #[agb::entry] macro"
|
||||||
|
@ -35,10 +62,23 @@ pub fn entry(args: TokenStream, input: TokenStream) -> TokenStream {
|
||||||
let attrs = f.attrs;
|
let attrs = f.attrs;
|
||||||
let stmts = f.block.stmts;
|
let stmts = f.block.stmts;
|
||||||
|
|
||||||
|
let mutable = if is_mutable {
|
||||||
|
Some(Token![mut](Span::call_site()))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
argument_type.to_string().ends_with("Gba"),
|
||||||
|
"Expected first argument to have type 'Gba'"
|
||||||
|
);
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
#[export_name = "main"]
|
#[export_name = "main"]
|
||||||
#(#attrs)*
|
#(#attrs)*
|
||||||
pub fn #fn_name() -> ! {
|
pub fn #fn_name() -> ! {
|
||||||
|
let #mutable #argument_name = unsafe { #argument_type ::new_in_entry() };
|
||||||
|
|
||||||
#(#stmts)*
|
#(#stmts)*
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
|
@ -6,7 +6,7 @@ extern crate alloc;
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(_gba: agb::Gba) -> ! {
|
||||||
loop {
|
loop {
|
||||||
let b = Box::new(1);
|
let b = Box::new(1);
|
||||||
agb::println!("dynamic allocation made to {:?}", &*b as *const _);
|
agb::println!("dynamic allocation made to {:?}", &*b as *const _);
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
use agb::sound;
|
use agb::sound;
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(gba: agb::Gba) -> ! {
|
||||||
let gba = agb::Gba::new();
|
|
||||||
|
|
||||||
gba.sound.enable();
|
gba.sound.enable();
|
||||||
|
|
||||||
let sweep_settings = sound::dmg::SweepSettings::default();
|
let sweep_settings = sound::dmg::SweepSettings::default();
|
||||||
|
|
|
@ -9,8 +9,7 @@ struct Vector2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let mut bitmap = gba.display.video.bitmap3();
|
let mut bitmap = gba.display.video.bitmap3();
|
||||||
let vblank = agb::interrupt::VBlank::get();
|
let vblank = agb::interrupt::VBlank::get();
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
use agb::display;
|
use agb::display;
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let mut bitmap = gba.display.video.bitmap4();
|
let mut bitmap = gba.display.video.bitmap4();
|
||||||
let vblank = agb::interrupt::VBlank::get();
|
let vblank = agb::interrupt::VBlank::get();
|
||||||
|
|
||||||
|
|
|
@ -35,14 +35,13 @@ fn frame_ranger(count: u32, start: u32, end: u32, delay: u32) -> u16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let map_as_grid: &[[u16; 32]; 32] = unsafe {
|
let map_as_grid: &[[u16; 32]; 32] = unsafe {
|
||||||
(&MAP_MAP as *const [u16; 1024] as *const [[u16; 32]; 32])
|
(&MAP_MAP as *const [u16; 1024] as *const [[u16; 32]; 32])
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let mut gfx = gba.display.video.tiled0();
|
let mut gfx = gba.display.video.tiled0();
|
||||||
let vblank = agb::interrupt::VBlank::get();
|
let vblank = agb::interrupt::VBlank::get();
|
||||||
let mut input = agb::input::ButtonController::new();
|
let mut input = agb::input::ButtonController::new();
|
||||||
|
|
|
@ -10,8 +10,7 @@ use agb::{include_wav, Gba};
|
||||||
const DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav");
|
const DEAD_CODE: &[u8] = include_wav!("examples/JoshWoodward-DeadCode.wav");
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: Gba) -> ! {
|
||||||
let mut gba = Gba::new();
|
|
||||||
let mut input = ButtonController::new();
|
let mut input = ButtonController::new();
|
||||||
let vblank_provider = agb::interrupt::VBlank::get();
|
let vblank_provider = agb::interrupt::VBlank::get();
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,7 @@ struct Vector2D {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let vblank = agb::interrupt::VBlank::get();
|
let vblank = agb::interrupt::VBlank::get();
|
||||||
let mut input = agb::input::ButtonController::new();
|
let mut input = agb::input::ButtonController::new();
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(_gba: agb::Gba) -> ! {
|
||||||
let count = agb::interrupt::Mutex::new(0);
|
let count = agb::interrupt::Mutex::new(0);
|
||||||
agb::add_interrupt_handler!(agb::interrupt::Interrupt::VBlank, |key| {
|
agb::add_interrupt_handler!(agb::interrupt::Interrupt::VBlank, |key| {
|
||||||
let mut count = count.lock_with_key(&key);
|
let mut count = count.lock_with_key(&key);
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
use agb::display;
|
use agb::display;
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
|
|
||||||
let mut bitmap = gba.display.video.bitmap3();
|
let mut bitmap = gba.display.video.bitmap3();
|
||||||
let mut input = agb::input::ButtonController::new();
|
let mut input = agb::input::ButtonController::new();
|
||||||
|
|
||||||
|
|
|
@ -8,8 +8,7 @@ use agb::{include_wav, Gba};
|
||||||
const LET_IT_IN: &[u8] = include_wav!("examples/JoshWoodward-LetItIn.wav");
|
const LET_IT_IN: &[u8] = include_wav!("examples/JoshWoodward-LetItIn.wav");
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: Gba) -> ! {
|
||||||
let mut gba = Gba::new();
|
|
||||||
let vblank_provider = agb::interrupt::VBlank::get();
|
let vblank_provider = agb::interrupt::VBlank::get();
|
||||||
|
|
||||||
let mut timer_controller = gba.timers.timers();
|
let mut timer_controller = gba.timers.timers();
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
use agb::{display, syscall};
|
use agb::{display, syscall};
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let mut bitmap = gba.display.video.bitmap3();
|
let mut bitmap = gba.display.video.bitmap3();
|
||||||
|
|
||||||
for x in 0..display::WIDTH {
|
for x in 0..display::WIDTH {
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
use agb::display::example_logo;
|
use agb::display::example_logo;
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let mut gfx = gba.display.video.tiled0();
|
let mut gfx = gba.display.video.tiled0();
|
||||||
|
|
||||||
example_logo::display_logo(&mut gfx);
|
example_logo::display_logo(&mut gfx);
|
||||||
|
|
|
@ -13,8 +13,7 @@ struct BackCosines {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let mut gfx = gba.display.video.tiled0();
|
let mut gfx = gba.display.video.tiled0();
|
||||||
|
|
||||||
example_logo::display_logo(&mut gfx);
|
example_logo::display_logo(&mut gfx);
|
||||||
|
|
|
@ -114,7 +114,7 @@ pub use agb_image_converter::include_gfx;
|
||||||
|
|
||||||
/// This macro declares the entry point to your game written using `agb`.
|
/// This macro declares the entry point to your game written using `agb`.
|
||||||
///
|
///
|
||||||
/// It is already included in the template, but your `main` function must be annotated with `#[agb::entry]`, take no arguments and never return.
|
/// It is already included in the template, but your `main` function must be annotated with `#[agb::entry]`, takes 1 argument and never returns.
|
||||||
/// Doing this will ensure that `agb` can correctly set up the environment to call your rust function on start up.
|
/// Doing this will ensure that `agb` can correctly set up the environment to call your rust function on start up.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
@ -125,9 +125,7 @@ pub use agb_image_converter::include_gfx;
|
||||||
/// use agb::Gba;
|
/// use agb::Gba;
|
||||||
///
|
///
|
||||||
/// #[agb::entry]
|
/// #[agb::entry]
|
||||||
/// fn main() -> ! {
|
/// fn main(mut gba: Gba) -> ! {
|
||||||
/// let mut gba = Gba::new();
|
|
||||||
///
|
|
||||||
/// loop {}
|
/// loop {}
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
@ -180,13 +178,7 @@ static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::new(unsafe { G
|
||||||
/// The Gba struct is used to control access to the Game Boy Advance's hardware in a way which makes it the
|
/// The Gba struct is used to control access to the Game Boy Advance's hardware in a way which makes it the
|
||||||
/// borrow checker's responsibility to ensure no clashes of global resources.
|
/// borrow checker's responsibility to ensure no clashes of global resources.
|
||||||
///
|
///
|
||||||
/// This is typically created once at the start of the main function and then the various fields are used
|
/// This is will be created for you via the #[agb::entry] attribute.
|
||||||
/// to ensure mutually exclusive use of the various hardware registers. It provides a gateway into the main
|
|
||||||
/// usage of `agb` library.
|
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Calling this twice will panic.
|
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
|
@ -197,9 +189,7 @@ static mut GBASINGLE: single::Singleton<Gba> = single::Singleton::new(unsafe { G
|
||||||
/// use agb::Gba;
|
/// use agb::Gba;
|
||||||
///
|
///
|
||||||
/// #[agb::entry]
|
/// #[agb::entry]
|
||||||
/// fn main() -> ! {
|
/// fn main(mut gba: Gba) -> !
|
||||||
/// let mut gba = Gba::new();
|
|
||||||
///
|
|
||||||
/// // Do whatever you need to do with gba
|
/// // Do whatever you need to do with gba
|
||||||
///
|
///
|
||||||
/// loop {}
|
/// loop {}
|
||||||
|
@ -219,15 +209,9 @@ pub struct Gba {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Gba {
|
impl Gba {
|
||||||
/// Creates a new instance of the Gba struct.
|
#[doc(hidden)]
|
||||||
///
|
pub unsafe fn new_in_entry() -> Self {
|
||||||
/// Note that you can only create 1 instance, and trying to create a second will panic.
|
GBASINGLE.take()
|
||||||
///
|
|
||||||
/// # Panics
|
|
||||||
///
|
|
||||||
/// Panics if you try to create the second instance.
|
|
||||||
pub fn new() -> Self {
|
|
||||||
unsafe { GBASINGLE.take() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsafe fn single_new() -> Self {
|
const unsafe fn single_new() -> Self {
|
||||||
|
@ -240,12 +224,6 @@ impl Gba {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Gba {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub trait Testable {
|
pub trait Testable {
|
||||||
fn run(&self, gba: &mut Gba);
|
fn run(&self, gba: &mut Gba);
|
||||||
|
@ -283,7 +261,11 @@ fn panic_implementation(info: &core::panic::PanicInfo) -> ! {
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
static mut TEST_GBA: Option<Gba> = None;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[cfg(test)]
|
||||||
pub fn test_runner(tests: &[&dyn Testable]) {
|
pub fn test_runner(tests: &[&dyn Testable]) {
|
||||||
let mut mgba = mgba::Mgba::new().unwrap();
|
let mut mgba = mgba::Mgba::new().unwrap();
|
||||||
mgba.print(
|
mgba.print(
|
||||||
|
@ -292,7 +274,7 @@ pub fn test_runner(tests: &[&dyn Testable]) {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let mut gba = Gba::new();
|
let mut gba = unsafe { TEST_GBA.as_mut() }.unwrap();
|
||||||
|
|
||||||
for test in tests {
|
for test in tests {
|
||||||
test.run(&mut gba);
|
test.run(&mut gba);
|
||||||
|
@ -307,7 +289,8 @@ pub fn test_runner(tests: &[&dyn Testable]) {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[entry]
|
#[entry]
|
||||||
fn agb_test_main() -> ! {
|
fn agb_test_main(gba: Gba) -> ! {
|
||||||
|
unsafe { TEST_GBA = Some(gba) };
|
||||||
test_main();
|
test_main();
|
||||||
#[allow(clippy::empty_loop)]
|
#[allow(clippy::empty_loop)]
|
||||||
loop {}
|
loop {}
|
||||||
|
|
|
@ -33,9 +33,7 @@ mod gfx {
|
||||||
// ensures that everything is in order. `agb` will call this after setting up the stack
|
// ensures that everything is in order. `agb` will call this after setting up the stack
|
||||||
// and interrupt handlers correctly.
|
// and interrupt handlers correctly.
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: Gba) -> ! {
|
||||||
let mut gba = Gba::new();
|
|
||||||
|
|
||||||
let _tiled = gba.display.video.tiled0();
|
let _tiled = gba.display.video.tiled0();
|
||||||
let mut object = gba.display.object.get();
|
let mut object = gba.display.object.get();
|
||||||
gfx::load_sprite_data(&mut object);
|
gfx::load_sprite_data(&mut object);
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
# The Gba struct
|
# The Gba struct
|
||||||
|
|
||||||
In this section, we'll cover the importance of the Gba struct and how to create it.
|
In this section, we'll cover the importance of the Gba struct and how it gets created for you.
|
||||||
|
|
||||||
# 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).
|
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).
|
||||||
Your games using `agb` will typically create this in the `main` function and then handle the abstractions in there.
|
You should not create the Gba struct yourself, instead having it be passed into your main function.
|
||||||
|
|
||||||
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'.
|
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 won't have to worry about 2 bits of your code modifying data in the wrong way!
|
You won't have to worry about 2 bits of your code modifying data in the wrong way!
|
||||||
This struct is a 'singleton', so you cannot create 2 instances of it at once.
|
This struct is a 'singleton', so you cannot create another instance of it.
|
||||||
Attempting to do so will result in a panic which by default crashes the game.
|
Attempting to do so will result in a panic which by default crashes the game.
|
||||||
|
|
||||||
# How all agb games start
|
# How all agb games start
|
||||||
|
@ -21,8 +21,6 @@ Replace the content of the `main` function with the following:
|
||||||
# #![no_main]
|
# #![no_main]
|
||||||
# #[agb::entry]
|
# #[agb::entry]
|
||||||
# fn main() -> ! {
|
# fn main() -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
|
|
||||||
loop {} // infinite loop for now
|
loop {} // infinite loop for now
|
||||||
# }
|
# }
|
||||||
```
|
```
|
||||||
|
@ -36,6 +34,6 @@ Although there isn't much to see at the moment (just a black screen), you can st
|
||||||
# What we did
|
# What we did
|
||||||
|
|
||||||
This was a very simple but incredibly important part of any game using `agb`.
|
This was a very simple but incredibly important part of any game using `agb`.
|
||||||
All interactions with the hardware are gated via the Gba struct, so it must be created at the start of your `main` function and never again.
|
All interactions with the hardware are gated via the Gba struct, which you never create yourself.
|
||||||
|
|
||||||
You are now ready to learn about display modes and how to start getting things onto the screen!
|
You are now ready to learn about display modes and how to start getting things onto the screen!
|
|
@ -772,10 +772,8 @@ impl<'a, 'b, 'c> PlayingLevel<'a, 'b> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[agb::entry]
|
||||||
pub fn main() -> ! {
|
fn main(mut agb: agb::Gba) -> ! {
|
||||||
let mut agb = agb::Gba::new();
|
|
||||||
|
|
||||||
splash_screen::show_splash_screen(&mut agb, splash_screen::SplashScreen::Start, None, None);
|
splash_screen::show_splash_screen(&mut agb, splash_screen::SplashScreen::Start, None, None);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -2207,9 +2207,7 @@ mod tilemap {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
game_with_level(&mut gba);
|
game_with_level(&mut gba);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,11 @@
|
||||||
|
|
||||||
use agb::{display, syscall};
|
use agb::{display, syscall};
|
||||||
|
|
||||||
// The main function must take 0 arguments and never return. The agb::entry decorator
|
// The main function must take 1 arguments and never return. The agb::entry decorator
|
||||||
// ensures that everything is in order. `agb` will call this after setting up the stack
|
// ensures that everything is in order. `agb` will call this after setting up the stack
|
||||||
// and interrupt handlers correctly.
|
// and interrupt handlers correctly. It will also handle creating the `Gba` struct for you.
|
||||||
#[agb::entry]
|
#[agb::entry]
|
||||||
fn main() -> ! {
|
fn main(mut gba: agb::Gba) -> ! {
|
||||||
let mut gba = agb::Gba::new();
|
|
||||||
let mut bitmap = gba.display.video.bitmap3();
|
let mut bitmap = gba.display.video.bitmap3();
|
||||||
|
|
||||||
for x in 0..display::WIDTH {
|
for x in 0..display::WIDTH {
|
||||||
|
|
Loading…
Reference in a new issue