mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-22 15:16:40 +11:00
allow only one vblank handler
This commit is contained in:
parent
3978e64cff
commit
9527d32521
3 changed files with 57 additions and 18 deletions
|
@ -14,6 +14,7 @@ struct Vector2D {
|
|||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
let gba = gba::Gba::new();
|
||||
let bitmap = gba.display.bitmap3();
|
||||
let vblank = gba.display.get_vblank();
|
||||
|
||||
let mut input = gba::input::ButtonController::new();
|
||||
let mut pos = Vector2D {
|
||||
|
@ -21,12 +22,8 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
|||
y: display::HEIGHT / 2,
|
||||
};
|
||||
|
||||
gba::interrupt::enable(gba::interrupt::Interrupt::VBlank);
|
||||
gba::interrupt::enable_interrupts();
|
||||
gba::display::enable_VBlank_interrupt();
|
||||
|
||||
loop {
|
||||
gba::display::wait_for_VBlank();
|
||||
vblank.wait_for_VBlank();
|
||||
|
||||
input.update();
|
||||
pos.x += input.x_tri() as i32;
|
||||
|
|
|
@ -9,6 +9,7 @@ use gba::display;
|
|||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||
let gba = gba::Gba::new();
|
||||
let bitmap = gba.display.bitmap4();
|
||||
let vblank = gba.display.get_vblank();
|
||||
|
||||
bitmap.set_palette_entry(1, 0x001F);
|
||||
bitmap.set_palette_entry(2, 0x03E0);
|
||||
|
@ -17,23 +18,19 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
|||
display::WIDTH / 2,
|
||||
display::HEIGHT / 2,
|
||||
1,
|
||||
display::Page::Front,
|
||||
display::bitmap4::Page::Front,
|
||||
);
|
||||
bitmap.draw_point_page(
|
||||
display::WIDTH / 2 + 5,
|
||||
display::HEIGHT / 2,
|
||||
2,
|
||||
display::Page::Back,
|
||||
display::bitmap4::Page::Back,
|
||||
);
|
||||
|
||||
gba::interrupt::enable(gba::interrupt::Interrupt::VBlank);
|
||||
gba::interrupt::enable_interrupts();
|
||||
gba::display::enable_VBlank_interrupt();
|
||||
|
||||
let mut count = 0;
|
||||
|
||||
loop {
|
||||
gba::display::wait_for_VBlank();
|
||||
vblank.wait_for_VBlank();
|
||||
count += 1;
|
||||
if count % 6 == 0 {
|
||||
bitmap.flip_page();
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
use crate::{memory_mapped::MemoryMapped, single::Single};
|
||||
use crate::{
|
||||
memory_mapped::MemoryMapped,
|
||||
single::{Single, SingleToken},
|
||||
};
|
||||
use bitflags::bitflags;
|
||||
|
||||
use bitmap3::Bitmap3;
|
||||
use bitmap4::Bitmap4;
|
||||
|
||||
mod bitmap3;
|
||||
mod bitmap4;
|
||||
pub mod bitmap3;
|
||||
pub mod bitmap4;
|
||||
|
||||
const DISPLAY_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0000) };
|
||||
const DISPLAY_STATUS: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0004) };
|
||||
|
@ -42,12 +45,14 @@ pub enum DisplayMode {
|
|||
|
||||
pub struct Display {
|
||||
in_mode: Single,
|
||||
vblank: Single,
|
||||
}
|
||||
|
||||
impl Display {
|
||||
pub(crate) const unsafe fn new() -> Self {
|
||||
Display {
|
||||
in_mode: Single::new(),
|
||||
vblank: Single::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -65,6 +70,15 @@ impl Display {
|
|||
.expect("Cannot create new mode as mode already taken"),
|
||||
)
|
||||
}
|
||||
pub fn get_vblank(&self) -> VBlank {
|
||||
unsafe {
|
||||
VBlank::new(
|
||||
self.vblank
|
||||
.take()
|
||||
.expect("Cannot create another vblank handler"),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn set_graphics_mode(mode: DisplayMode) {
|
||||
|
@ -85,18 +99,49 @@ pub fn set_graphics_settings(settings: GraphicsSettings) {
|
|||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
/// Waits until vblank using a busy wait loop, this should almost never be used.
|
||||
/// I only say almost because whilst I don't believe there to be a reason to use
|
||||
/// this I can't rule it out.
|
||||
pub fn busy_wait_for_VBlank() {
|
||||
while VCOUNT.get() >= 160 {}
|
||||
while VCOUNT.get() < 160 {}
|
||||
}
|
||||
|
||||
pub struct VBlank<'a> {
|
||||
_got: SingleToken<'a>,
|
||||
}
|
||||
|
||||
impl<'a> VBlank<'a> {
|
||||
unsafe fn new(a: SingleToken<'a>) -> Self {
|
||||
crate::interrupt::enable_interrupts();
|
||||
crate::interrupt::enable(crate::interrupt::Interrupt::VBlank);
|
||||
enable_VBlank_interrupt();
|
||||
VBlank { _got: a }
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn enable_VBlank_interrupt() {
|
||||
pub fn wait_for_VBlank(&self) {
|
||||
crate::syscall::wait_for_VBlank();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for VBlank<'a> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
disable_VBlank_interrupt();
|
||||
crate::interrupt::disable(crate::interrupt::Interrupt::VBlank);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
unsafe fn enable_VBlank_interrupt() {
|
||||
let status = DISPLAY_STATUS.get() | (1 << 3);
|
||||
DISPLAY_STATUS.set(status);
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
pub fn wait_for_VBlank() {
|
||||
crate::syscall::wait_for_VBlank();
|
||||
unsafe fn disable_VBlank_interrupt() {
|
||||
let status = DISPLAY_STATUS.get() & !(1 << 3);
|
||||
DISPLAY_STATUS.set(status);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue