From 3b688b907cd8a59ffb4d77884c055b5f1da455c1 Mon Sep 17 00:00:00 2001 From: Lokathor Date: Thu, 14 Feb 2019 19:39:34 -0700 Subject: [PATCH] Get all the code lined up --- examples-bak/light_cycle.rs | 61 ------------------------------------- examples/hello_world.rs | 56 ++++++++++++++++++++++++++++++---- examples/irq.rs | 7 +++-- src/io/display.rs | 31 ------------------- src/io/keypad.rs | 14 +++++---- src/lib.rs | 7 ----- 6 files changed, 62 insertions(+), 114 deletions(-) delete mode 100644 examples-bak/light_cycle.rs diff --git a/examples-bak/light_cycle.rs b/examples-bak/light_cycle.rs deleted file mode 100644 index 58f2156..0000000 --- a/examples-bak/light_cycle.rs +++ /dev/null @@ -1,61 +0,0 @@ -#![no_std] -#![feature(start)] -#![forbid(unsafe_code)] - -use gba::{ - io::{ - display::{spin_until_vblank, spin_until_vdraw, DisplayControlSetting, DisplayMode, DISPCNT}, - keypad::read_key_input, - }, - vram::bitmap::Mode3, - Color, -}; - -#[panic_handler] -fn panic(_info: &core::panic::PanicInfo) -> ! { - loop {} -} - -#[start] -fn main(_argc: isize, _argv: *const *const u8) -> isize { - const SETTING: DisplayControlSetting = DisplayControlSetting::new().with_mode(DisplayMode::Mode3).with_bg2(true); - DISPCNT.write(SETTING); - - let mut px = Mode3::WIDTH / 2; - let mut py = Mode3::HEIGHT / 2; - let mut color = Color::from_rgb(31, 0, 0); - - loop { - // read the input for this frame - let this_frame_keys = read_key_input(); - - // adjust game state and wait for vblank - px = px.wrapping_add(2 * this_frame_keys.column_direction() as usize); - py = py.wrapping_add(2 * this_frame_keys.row_direction() as usize); - spin_until_vblank(); - - // draw the new game and wait until the next frame starts. - const BLACK: Color = Color::from_rgb(0, 0, 0); - if px >= Mode3::WIDTH || py >= Mode3::HEIGHT { - // out of bounds, reset the screen and position. - Mode3::clear_to(BLACK); - color = color.rotate_left(5); - px = Mode3::WIDTH / 2; - py = Mode3::HEIGHT / 2; - } else { - let color_here = Mode3::read(px, py); - if color_here != Some(BLACK) { - // crashed into our own line, reset the screen - Mode3::dma_clear_to(BLACK); - color = color.rotate_left(5); - } else { - // draw the new part of the line - Mode3::write(px, py, color); - Mode3::write(px, py + 1, color); - Mode3::write(px + 1, py, color); - Mode3::write(px + 1, py + 1, color); - } - } - spin_until_vdraw(); - } -} diff --git a/examples/hello_world.rs b/examples/hello_world.rs index b6263ec..54527f3 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -4,11 +4,13 @@ use gba::{ fatal, - io::display::{DisplayControlSetting, DisplayMode, DISPCNT}, + io::{ + display::{DisplayControlSetting, DisplayMode, DISPCNT, VBLANK_SCANLINE, VCOUNT}, + keypad::read_key_input, + }, vram::bitmap::Mode3, Color, }; -use gba::io::keypad::read_key_input; #[panic_handler] fn panic(info: &core::panic::PanicInfo) -> ! { @@ -33,9 +35,51 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { // read our keys for this frame let this_frame_keys = read_key_input(); - gba::io::display::spin_until_vblank(); - Mode5::dma_clear_to(Page::Zero, Color(111)); - Mode5::draw_line(Page::Zero, 5, 5, 100, 100, Color(0b0_11111_11111_11111)); - gba::io::display::spin_until_vdraw(); + // adjust game state and wait for vblank + px = px.wrapping_add(2 * this_frame_keys.x_tribool() as usize); + py = py.wrapping_add(2 * this_frame_keys.y_tribool() as usize); + if this_frame_keys.l() { + color = Color(color.0.rotate_left(5)); + } + if this_frame_keys.r() { + color = Color(color.0.rotate_right(5)); + } + + // now we wait + spin_until_vblank(); + + // draw the new game and wait until the next frame starts. + const BLACK: Color = Color::from_rgb(0, 0, 0); + if px >= Mode3::WIDTH || py >= Mode3::HEIGHT { + // out of bounds, reset the screen and position. + Mode3::dma_clear_to(BLACK); + px = Mode3::WIDTH / 2; + py = Mode3::HEIGHT / 2; + } else { + // draw the new part of the line + Mode3::write(px, py, color); + Mode3::write(px, py + 1, color); + Mode3::write(px + 1, py, color); + Mode3::write(px + 1, py + 1, color); + } + + // now we wait again + spin_until_vdraw(); } } + +/// Performs a busy loop until VBlank starts. +/// +/// This is very inefficient, and please keep following the lessons until we +/// cover how interrupts work! +pub fn spin_until_vblank() { + while VCOUNT.read() < VBLANK_SCANLINE {} +} + +/// Performs a busy loop until VDraw starts. +/// +/// This is very inefficient, and please keep following the lessons until we +/// cover how interrupts work! +pub fn spin_until_vdraw() { + while VCOUNT.read() >= VBLANK_SCANLINE {} +} diff --git a/examples/irq.rs b/examples/irq.rs index c38bc81..931ecc6 100644 --- a/examples/irq.rs +++ b/examples/irq.rs @@ -26,7 +26,8 @@ fn panic(_info: &core::panic::PanicInfo) -> ! { fn start_timers() { let init_val: u16 = u32::wrapping_sub(0x1_0000, 64) as u16; - const TIMER_SETTINGS: TimerControlSetting = TimerControlSetting::new().with_overflow_irq(true).with_enabled(true); + const TIMER_SETTINGS: TimerControlSetting = + TimerControlSetting::new().with_overflow_irq(true).with_enabled(true); TM0CNT_L.write(init_val); TM0CNT_H.write(TIMER_SETTINGS.with_tick_rate(TimerTickRate::CPU1024)); @@ -90,8 +91,8 @@ static mut PIXEL: usize = 0; fn write_pixel(color: Color) { unsafe { - Mode3::write_pixel(PIXEL, 0, color); - PIXEL = (PIXEL + 1) % Mode3::SCREEN_PIXEL_COUNT; + Mode3::write(PIXEL, 0, color); + PIXEL = (PIXEL + 1) % (Mode3::WIDTH * Mode3::HEIGHT); } } diff --git a/src/io/display.rs b/src/io/display.rs index e2e0e8f..553967c 100644 --- a/src/io/display.rs +++ b/src/io/display.rs @@ -127,37 +127,6 @@ pub const VCOUNT: ROVolAddress = unsafe { ROVolAddress::new(0x400_0006) }; /// If the `VCOUNT` register reads equal to or above this then you're in vblank. pub const VBLANK_SCANLINE: u16 = 160; -/// Obtains the current `VCOUNT` value. -pub fn vcount() -> u16 { - VCOUNT.read() -} - -/// Performs a busy loop until VBlank starts. -/// -/// NOTE: This method isn't very power efficient, since it is equivalent to -/// calling "halt" repeatedly. The recommended way to wait for a VBlank or VDraw -/// is to set an IRQ handler with -/// [`io::irq::set_irq_handler`](`io::irq::set_irq_handler`) and using -/// [`bios::vblank_intr_wait`](bios::vblank_interrupt_wait) to sleep the CPU -/// until a VBlank IRQ is generated. See the [`io::irq`](io::irq) module for -/// more details. -pub fn spin_until_vblank() { - while vcount() < VBLANK_SCANLINE {} -} - -/// Performs a busy loop until VDraw starts. -/// -/// NOTE: This method isn't very power efficient, since it is equivalent to -/// calling "halt" repeatedly. The recommended way to wait for a VBlank or VDraw -/// is to set an IRQ handler with -/// [`io::irq::set_irq_handler`](`io::irq::set_irq_handler`) and using -/// [`bios::vblank_intr_wait`](bios::vblank_interrupt_wait) to sleep the CPU -/// until a VBlank IRQ is generated. See the [`io::irq`](io::irq) module for -/// more details. -pub fn spin_until_vdraw() { - while vcount() >= VBLANK_SCANLINE {} -} - /// Global mosaic effect control. Write-only. pub const MOSAIC: VolAddress = unsafe { VolAddress::new(0x400_004C) }; diff --git a/src/io/keypad.rs b/src/io/keypad.rs index 2041dd4..5805e12 100644 --- a/src/io/keypad.rs +++ b/src/io/keypad.rs @@ -50,9 +50,10 @@ impl KeyInput { KeyInput(self.0 ^ other.0) } - /// Gives the arrow pad value as a tribool, with Plus being increased column - /// value (right). - pub fn column_direction(self) -> TriBool { + /// Right/left tribool. + /// + /// Right is Plus and Left is Minus + pub fn x_tribool(self) -> TriBool { if self.right() { TriBool::Plus } else if self.left() { @@ -62,9 +63,10 @@ impl KeyInput { } } - /// Gives the arrow pad value as a tribool, with Plus being increased row - /// value (down). - pub fn row_direction(self) -> TriBool { + /// Up/down tribool. + /// + /// Down is Plus and Up is Minus + pub fn y_tribool(self) -> TriBool { if self.down() { TriBool::Plus } else if self.up() { diff --git a/src/lib.rs b/src/lib.rs index 4825a21..ca17759 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -71,13 +71,6 @@ impl Color { pub const fn from_rgb(r: u16, g: u16, b: u16) -> Color { Color(b << 10 | g << 5 | r) } - - /// Does a left rotate of the bits. - /// - /// This has no particular meaning but is a wild way to cycle colors. - pub const fn rotate_left(self, n: u32) -> Color { - Color(self.0.rotate_left(n)) - } } //