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 {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
let gba = gba::Gba::new();
|
let gba = gba::Gba::new();
|
||||||
let bitmap = gba.display.bitmap3();
|
let bitmap = gba.display.bitmap3();
|
||||||
|
let vblank = gba.display.get_vblank();
|
||||||
|
|
||||||
let mut input = gba::input::ButtonController::new();
|
let mut input = gba::input::ButtonController::new();
|
||||||
let mut pos = Vector2D {
|
let mut pos = Vector2D {
|
||||||
|
@ -21,12 +22,8 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
y: display::HEIGHT / 2,
|
y: display::HEIGHT / 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
gba::interrupt::enable(gba::interrupt::Interrupt::VBlank);
|
|
||||||
gba::interrupt::enable_interrupts();
|
|
||||||
gba::display::enable_VBlank_interrupt();
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
gba::display::wait_for_VBlank();
|
vblank.wait_for_VBlank();
|
||||||
|
|
||||||
input.update();
|
input.update();
|
||||||
pos.x += input.x_tri() as i32;
|
pos.x += input.x_tri() as i32;
|
||||||
|
|
|
@ -9,6 +9,7 @@ use gba::display;
|
||||||
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
let gba = gba::Gba::new();
|
let gba = gba::Gba::new();
|
||||||
let bitmap = gba.display.bitmap4();
|
let bitmap = gba.display.bitmap4();
|
||||||
|
let vblank = gba.display.get_vblank();
|
||||||
|
|
||||||
bitmap.set_palette_entry(1, 0x001F);
|
bitmap.set_palette_entry(1, 0x001F);
|
||||||
bitmap.set_palette_entry(2, 0x03E0);
|
bitmap.set_palette_entry(2, 0x03E0);
|
||||||
|
@ -17,23 +18,19 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
|
||||||
display::WIDTH / 2,
|
display::WIDTH / 2,
|
||||||
display::HEIGHT / 2,
|
display::HEIGHT / 2,
|
||||||
1,
|
1,
|
||||||
display::Page::Front,
|
display::bitmap4::Page::Front,
|
||||||
);
|
);
|
||||||
bitmap.draw_point_page(
|
bitmap.draw_point_page(
|
||||||
display::WIDTH / 2 + 5,
|
display::WIDTH / 2 + 5,
|
||||||
display::HEIGHT / 2,
|
display::HEIGHT / 2,
|
||||||
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;
|
let mut count = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
gba::display::wait_for_VBlank();
|
vblank.wait_for_VBlank();
|
||||||
count += 1;
|
count += 1;
|
||||||
if count % 6 == 0 {
|
if count % 6 == 0 {
|
||||||
bitmap.flip_page();
|
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 bitflags::bitflags;
|
||||||
|
|
||||||
use bitmap3::Bitmap3;
|
use bitmap3::Bitmap3;
|
||||||
use bitmap4::Bitmap4;
|
use bitmap4::Bitmap4;
|
||||||
|
|
||||||
mod bitmap3;
|
pub mod bitmap3;
|
||||||
mod bitmap4;
|
pub mod bitmap4;
|
||||||
|
|
||||||
const DISPLAY_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0000) };
|
const DISPLAY_CONTROL: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0000) };
|
||||||
const DISPLAY_STATUS: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0004) };
|
const DISPLAY_STATUS: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x0400_0004) };
|
||||||
|
@ -42,12 +45,14 @@ pub enum DisplayMode {
|
||||||
|
|
||||||
pub struct Display {
|
pub struct Display {
|
||||||
in_mode: Single,
|
in_mode: Single,
|
||||||
|
vblank: Single,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display {
|
impl Display {
|
||||||
pub(crate) const unsafe fn new() -> Self {
|
pub(crate) const unsafe fn new() -> Self {
|
||||||
Display {
|
Display {
|
||||||
in_mode: Single::new(),
|
in_mode: Single::new(),
|
||||||
|
vblank: Single::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +70,15 @@ impl Display {
|
||||||
.expect("Cannot create new mode as mode already taken"),
|
.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) {
|
fn set_graphics_mode(mode: DisplayMode) {
|
||||||
|
@ -85,18 +99,49 @@ pub fn set_graphics_settings(settings: GraphicsSettings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[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() {
|
pub fn busy_wait_for_VBlank() {
|
||||||
while VCOUNT.get() >= 160 {}
|
while VCOUNT.get() >= 160 {}
|
||||||
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 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)]
|
#[allow(non_snake_case)]
|
||||||
pub fn enable_VBlank_interrupt() {
|
unsafe fn enable_VBlank_interrupt() {
|
||||||
let status = DISPLAY_STATUS.get() | (1 << 3);
|
let status = DISPLAY_STATUS.get() | (1 << 3);
|
||||||
DISPLAY_STATUS.set(status);
|
DISPLAY_STATUS.set(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn wait_for_VBlank() {
|
unsafe fn disable_VBlank_interrupt() {
|
||||||
crate::syscall::wait_for_VBlank();
|
let status = DISPLAY_STATUS.get() & !(1 << 3);
|
||||||
|
DISPLAY_STATUS.set(status);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue