#[non_exhaustive]pub struct VBlank { /* private fields */ }
Implementations§
source§impl VBlank
impl VBlank
sourcepub fn get() -> Self
pub fn get() -> Self
Handles setting up everything required to be able to use the wait for interrupt syscall.
Examples found in repository?
examples/sprites.rs (line 45)
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
fn all_sprites(gfx: &OamManaged, rotation_speed: Num<i32, 16>) {
let mut input = agb::input::ButtonController::new();
let mut objs = Vec::new();
let mut rotation: Num<i32, 16> = num!(0.);
let rotation_matrix = AffineMatrix::from_rotation(rotation);
let matrix = object::AffineMatrixInstance::new(rotation_matrix.to_object_wrapping());
for y in 0..9 {
for x in 0..14 {
let mut obj = gfx.object_sprite(&SPRITES[0]);
obj.set_affine_matrix(matrix.clone());
obj.show_affine(object::AffineMode::Affine);
obj.set_position((x * 16 + 8, y * 16 + 8));
objs.push(obj);
}
}
let mut count = 0;
let mut image = 0;
let vblank = agb::interrupt::VBlank::get();
loop {
vblank.wait_for_vblank();
input.update();
if input.is_just_pressed(agb::input::Button::A) {
break;
}
rotation += rotation_speed;
let rotation_matrix = AffineMatrix::from_rotation(rotation);
let matrix = object::AffineMatrixInstance::new(rotation_matrix.to_object_wrapping());
for obj in objs.iter_mut() {
obj.set_affine_matrix(matrix.clone());
}
count += 1;
if count % 5 == 0 {
image += 1;
image %= SPRITES.len();
for (i, obj) in objs.iter_mut().enumerate() {
let this_image = (image + i) % SPRITES.len();
obj.set_sprite(gfx.sprite(&SPRITES[this_image]));
}
}
gfx.commit();
}
}
fn all_tags(gfx: &OamManaged) {
let mut input = agb::input::ButtonController::new();
let mut objs = Vec::new();
for (i, v) in TAG_MAP.values().enumerate() {
let x = (i % 7) as i32;
let y = (i / 7) as i32;
let sprite = v.sprite(0);
let (size_x, size_y) = sprite.size().to_width_height();
let (size_x, size_y) = (size_x as i32, size_y as i32);
let mut obj = gfx.object_sprite(sprite);
obj.show();
obj.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2));
objs.push((obj, v));
}
let mut count = 0;
let mut image = 0;
let vblank = agb::interrupt::VBlank::get();
loop {
vblank.wait_for_vblank();
input.update();
if input.is_just_pressed(agb::input::Button::A) {
break;
}
count += 1;
if count % 5 == 0 {
image += 1;
for (obj, tag) in objs.iter_mut() {
obj.set_sprite(gfx.sprite(tag.animation_sprite(image)));
}
gfx.commit();
}
}
}
More examples
examples/windows.rs (line 54)
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
);
let mut window = gba.display.window.get();
window
.win_in(WinIn::Win0)
.set_background_enable(map.background(), true)
.set_position(&Rect::new((10, 10).into(), (64, 64).into()))
.enable();
window
.win_out()
.enable()
.set_background_enable(map.background(), true)
.set_blend_enable(true);
example_logo::display_logo(&mut map, &mut vram);
let mut blend = gba.display.blend.get();
blend
.set_background_enable(Layer::Top, map.background(), true)
.set_backdrop_enable(Layer::Bottom, true)
.set_blend_mode(BlendMode::Normal);
let mut pos: Vector2D<FNum> = (10, 10).into();
let mut velocity: Vector2D<FNum> = Vector2D::new(1.into(), 1.into());
let mut blend_amount: Num<i32, 8> = num!(0.5);
let mut blend_velocity: Num<i32, 8> = Num::new(1) / 128;
let vblank = VBlank::get();
loop {
pos += velocity;
if pos.x.floor() > WIDTH - 64 || pos.x.floor() < 0 {
velocity.x *= -1;
}
if pos.y.floor() > HEIGHT - 64 || pos.y.floor() < 0 {
velocity.y *= -1;
}
blend_amount += blend_velocity;
if blend_amount > num!(0.75) || blend_amount < num!(0.25) {
blend_velocity *= -1;
}
blend_amount = blend_amount.clamp(0.into(), 1.into());
blend.set_blend_weight(Layer::Top, blend_amount.try_change_base().unwrap());
window
.win_in(WinIn::Win0)
.set_position(&Rect::new(pos.floor(), (64, 64).into()));
vblank.wait_for_vblank();
window.commit();
blend.commit();
}
}
examples/dma_effect_circular_window.rs (line 48)
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
);
let mut window = gba.display.window.get();
window
.win_in(WinIn::Win0)
.set_background_enable(map.background(), true)
.set_position(&Rect::new((10, 10).into(), (64, 64).into()))
.enable();
let dmas = gba.dma.dma();
example_logo::display_logo(&mut map, &mut vram);
let mut pos: Vector2D<FNum> = (10, 10).into();
let mut velocity: Vector2D<FNum> = Vector2D::new(1.into(), 1.into());
let vblank = VBlank::get();
let circle: Box<[_]> = (1..64i32)
.map(|i| {
let y = 32 - i;
let x = (32 * 32 - y * y).isqrt();
let x1 = 32 - x;
let x2 = 32 + x;
((x1 as u16) << 8) | (x2 as u16)
})
.collect();
let mut circle_poses = vec![0; 160];
loop {
pos += velocity;
if pos.x.floor() > WIDTH - 64 || pos.x.floor() < 0 {
velocity.x *= -1;
}
if pos.y.floor() > HEIGHT - 64 || pos.y.floor() < 0 {
velocity.y *= -1;
}
let x_pos = pos.x.floor().max(0) as u16;
let y_pos = pos.y.floor().max(0);
let x_adjustment = x_pos << 8 | x_pos;
for (i, value) in circle_poses.iter_mut().enumerate() {
let i = i as i32;
if i <= y_pos || i >= y_pos + 64 {
*value = 0;
continue;
}
*value = circle[(i - y_pos) as usize - 1] + x_adjustment;
}
window
.win_in(WinIn::Win0)
.set_position(&Rect::new(pos.floor(), (64, 65).into()));
window.commit();
let dma_controllable = window.win_in(WinIn::Win0).horizontal_position_dma();
let _transfer = unsafe { dmas.dma0.hblank_transfer(&dma_controllable, &circle_poses) };
vblank.wait_for_vblank();
}
}
examples/object_text_render.rs (line 56)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
fn main(mut gba: agb::Gba) -> ! {
let (mut unmanaged, _sprites) = gba.display.object.get_unmanaged();
let mut palette = [0x0; 16];
palette[1] = 0xFF_FF;
palette[2] = 0x00_FF;
let palette = Palette16::new(palette);
let palette = PaletteVram::new(&palette).unwrap();
let timer = gba.timers.timers();
let mut timer: agb::timer::Timer = timer.timer2;
timer.set_enabled(true);
timer.set_divider(agb::timer::Divider::Divider256);
let mut wr = ObjectTextRender::new(&FONT, Size::S16x16, palette);
let start = timer.value();
let player_name = "You";
let _ = writeln!(
wr,
"Woah!{change2} {player_name}! {change1}Hey there! I have a bunch of text I want to show you. However, you will find that the amount of text I can display is limited. Who'd have thought! Good thing that my text system supports scrolling! It only took around 20 jank versions to get here!",
change2 = ChangeColour::new(2),
change1 = ChangeColour::new(1),
);
let end = timer.value();
agb::println!(
"Write took {} cycles",
256 * (end.wrapping_sub(start) as u32)
);
let vblank = agb::interrupt::VBlank::get();
let mut input = agb::input::ButtonController::new();
let start = timer.value();
wr.layout((WIDTH, 40), TextAlignment::Justify, 2);
let end = timer.value();
agb::println!(
"Layout took {} cycles",
256 * (end.wrapping_sub(start) as u32)
);
let mut line_done = false;
let mut frame = 0;
loop {
vblank.wait_for_vblank();
input.update();
let oam = &mut unmanaged.iter();
wr.commit(oam);
let start = timer.value();
if frame % 4 == 0 {
line_done = !wr.next_letter_group();
}
if line_done && input.is_just_pressed(Button::A) {
line_done = false;
wr.pop_line();
}
wr.update((0, HEIGHT - 40));
let end = timer.value();
frame += 1;
agb::println!(
"Took {} cycles, line done {}",
256 * (end.wrapping_sub(start) as u32),
line_done
);
}
}
sourcepub fn wait_for_vblank(&self)
pub fn wait_for_vblank(&self)
Pauses CPU until vblank interrupt is triggered where code execution is resumed.
Examples found in repository?
examples/multiple_video.rs (line 33)
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
fn bitmap3_mode(
bitmap: &mut display::bitmap3::Bitmap3,
vblank: &agb::interrupt::VBlank,
input: &mut agb::input::ButtonController,
) {
let mut pos = Vector2D {
x: display::WIDTH / 2,
y: display::HEIGHT / 2,
};
loop {
vblank.wait_for_vblank();
input.update();
if input.is_just_pressed(agb::input::Button::B) {
break;
}
pos.x += input.x_tri() as i32;
pos.y += input.y_tri() as i32;
pos.x = pos.x.clamp(0, display::WIDTH - 1);
pos.y = pos.y.clamp(0, display::HEIGHT - 1);
bitmap.draw_point(pos.x, pos.y, 0x001F);
}
}
fn bitmap4_mode(
bitmap: &mut display::bitmap4::Bitmap4,
vblank: &agb::interrupt::VBlank,
input: &mut agb::input::ButtonController,
) {
bitmap.set_palette_entry(1, 0x001F);
bitmap.set_palette_entry(2, 0x03E0);
bitmap.draw_point_page(
display::WIDTH / 2,
display::HEIGHT / 2,
1,
display::bitmap4::Page::Front,
);
bitmap.draw_point_page(
display::WIDTH / 2 + 5,
display::HEIGHT / 2,
2,
display::bitmap4::Page::Back,
);
let mut count = 0;
loop {
vblank.wait_for_vblank();
input.update();
if input.is_just_pressed(agb::input::Button::B) {
break;
}
count += 1;
if count % 6 == 0 {
bitmap.flip_page();
}
}
}
More examples
examples/sprites.rs (line 48)
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
fn all_sprites(gfx: &OamManaged, rotation_speed: Num<i32, 16>) {
let mut input = agb::input::ButtonController::new();
let mut objs = Vec::new();
let mut rotation: Num<i32, 16> = num!(0.);
let rotation_matrix = AffineMatrix::from_rotation(rotation);
let matrix = object::AffineMatrixInstance::new(rotation_matrix.to_object_wrapping());
for y in 0..9 {
for x in 0..14 {
let mut obj = gfx.object_sprite(&SPRITES[0]);
obj.set_affine_matrix(matrix.clone());
obj.show_affine(object::AffineMode::Affine);
obj.set_position((x * 16 + 8, y * 16 + 8));
objs.push(obj);
}
}
let mut count = 0;
let mut image = 0;
let vblank = agb::interrupt::VBlank::get();
loop {
vblank.wait_for_vblank();
input.update();
if input.is_just_pressed(agb::input::Button::A) {
break;
}
rotation += rotation_speed;
let rotation_matrix = AffineMatrix::from_rotation(rotation);
let matrix = object::AffineMatrixInstance::new(rotation_matrix.to_object_wrapping());
for obj in objs.iter_mut() {
obj.set_affine_matrix(matrix.clone());
}
count += 1;
if count % 5 == 0 {
image += 1;
image %= SPRITES.len();
for (i, obj) in objs.iter_mut().enumerate() {
let this_image = (image + i) % SPRITES.len();
obj.set_sprite(gfx.sprite(&SPRITES[this_image]));
}
}
gfx.commit();
}
}
fn all_tags(gfx: &OamManaged) {
let mut input = agb::input::ButtonController::new();
let mut objs = Vec::new();
for (i, v) in TAG_MAP.values().enumerate() {
let x = (i % 7) as i32;
let y = (i / 7) as i32;
let sprite = v.sprite(0);
let (size_x, size_y) = sprite.size().to_width_height();
let (size_x, size_y) = (size_x as i32, size_y as i32);
let mut obj = gfx.object_sprite(sprite);
obj.show();
obj.set_position((x * 32 + 16 - size_x / 2, y * 32 + 16 - size_y / 2));
objs.push((obj, v));
}
let mut count = 0;
let mut image = 0;
let vblank = agb::interrupt::VBlank::get();
loop {
vblank.wait_for_vblank();
input.update();
if input.is_just_pressed(agb::input::Button::A) {
break;
}
count += 1;
if count % 5 == 0 {
image += 1;
for (obj, tag) in objs.iter_mut() {
obj.set_sprite(gfx.sprite(tag.animation_sprite(image)));
}
gfx.commit();
}
}
}
examples/windows.rs (line 80)
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
);
let mut window = gba.display.window.get();
window
.win_in(WinIn::Win0)
.set_background_enable(map.background(), true)
.set_position(&Rect::new((10, 10).into(), (64, 64).into()))
.enable();
window
.win_out()
.enable()
.set_background_enable(map.background(), true)
.set_blend_enable(true);
example_logo::display_logo(&mut map, &mut vram);
let mut blend = gba.display.blend.get();
blend
.set_background_enable(Layer::Top, map.background(), true)
.set_backdrop_enable(Layer::Bottom, true)
.set_blend_mode(BlendMode::Normal);
let mut pos: Vector2D<FNum> = (10, 10).into();
let mut velocity: Vector2D<FNum> = Vector2D::new(1.into(), 1.into());
let mut blend_amount: Num<i32, 8> = num!(0.5);
let mut blend_velocity: Num<i32, 8> = Num::new(1) / 128;
let vblank = VBlank::get();
loop {
pos += velocity;
if pos.x.floor() > WIDTH - 64 || pos.x.floor() < 0 {
velocity.x *= -1;
}
if pos.y.floor() > HEIGHT - 64 || pos.y.floor() < 0 {
velocity.y *= -1;
}
blend_amount += blend_velocity;
if blend_amount > num!(0.75) || blend_amount < num!(0.25) {
blend_velocity *= -1;
}
blend_amount = blend_amount.clamp(0.into(), 1.into());
blend.set_blend_weight(Layer::Top, blend_amount.try_change_base().unwrap());
window
.win_in(WinIn::Win0)
.set_position(&Rect::new(pos.floor(), (64, 64).into()));
vblank.wait_for_vblank();
window.commit();
blend.commit();
}
}
examples/dma_effect_circular_window.rs (line 95)
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
fn main(mut gba: agb::Gba) -> ! {
let (gfx, mut vram) = gba.display.video.tiled0();
let mut map = gfx.background(
agb::display::Priority::P0,
RegularBackgroundSize::Background32x32,
TileFormat::FourBpp,
);
let mut window = gba.display.window.get();
window
.win_in(WinIn::Win0)
.set_background_enable(map.background(), true)
.set_position(&Rect::new((10, 10).into(), (64, 64).into()))
.enable();
let dmas = gba.dma.dma();
example_logo::display_logo(&mut map, &mut vram);
let mut pos: Vector2D<FNum> = (10, 10).into();
let mut velocity: Vector2D<FNum> = Vector2D::new(1.into(), 1.into());
let vblank = VBlank::get();
let circle: Box<[_]> = (1..64i32)
.map(|i| {
let y = 32 - i;
let x = (32 * 32 - y * y).isqrt();
let x1 = 32 - x;
let x2 = 32 + x;
((x1 as u16) << 8) | (x2 as u16)
})
.collect();
let mut circle_poses = vec![0; 160];
loop {
pos += velocity;
if pos.x.floor() > WIDTH - 64 || pos.x.floor() < 0 {
velocity.x *= -1;
}
if pos.y.floor() > HEIGHT - 64 || pos.y.floor() < 0 {
velocity.y *= -1;
}
let x_pos = pos.x.floor().max(0) as u16;
let y_pos = pos.y.floor().max(0);
let x_adjustment = x_pos << 8 | x_pos;
for (i, value) in circle_poses.iter_mut().enumerate() {
let i = i as i32;
if i <= y_pos || i >= y_pos + 64 {
*value = 0;
continue;
}
*value = circle[(i - y_pos) as usize - 1] + x_adjustment;
}
window
.win_in(WinIn::Win0)
.set_position(&Rect::new(pos.floor(), (64, 65).into()));
window.commit();
let dma_controllable = window.win_in(WinIn::Win0).horizontal_position_dma();
let _transfer = unsafe { dmas.dma0.hblank_transfer(&dma_controllable, &circle_poses) };
vblank.wait_for_vblank();
}
}
examples/object_text_render.rs (line 73)
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
fn main(mut gba: agb::Gba) -> ! {
let (mut unmanaged, _sprites) = gba.display.object.get_unmanaged();
let mut palette = [0x0; 16];
palette[1] = 0xFF_FF;
palette[2] = 0x00_FF;
let palette = Palette16::new(palette);
let palette = PaletteVram::new(&palette).unwrap();
let timer = gba.timers.timers();
let mut timer: agb::timer::Timer = timer.timer2;
timer.set_enabled(true);
timer.set_divider(agb::timer::Divider::Divider256);
let mut wr = ObjectTextRender::new(&FONT, Size::S16x16, palette);
let start = timer.value();
let player_name = "You";
let _ = writeln!(
wr,
"Woah!{change2} {player_name}! {change1}Hey there! I have a bunch of text I want to show you. However, you will find that the amount of text I can display is limited. Who'd have thought! Good thing that my text system supports scrolling! It only took around 20 jank versions to get here!",
change2 = ChangeColour::new(2),
change1 = ChangeColour::new(1),
);
let end = timer.value();
agb::println!(
"Write took {} cycles",
256 * (end.wrapping_sub(start) as u32)
);
let vblank = agb::interrupt::VBlank::get();
let mut input = agb::input::ButtonController::new();
let start = timer.value();
wr.layout((WIDTH, 40), TextAlignment::Justify, 2);
let end = timer.value();
agb::println!(
"Layout took {} cycles",
256 * (end.wrapping_sub(start) as u32)
);
let mut line_done = false;
let mut frame = 0;
loop {
vblank.wait_for_vblank();
input.update();
let oam = &mut unmanaged.iter();
wr.commit(oam);
let start = timer.value();
if frame % 4 == 0 {
line_done = !wr.next_letter_group();
}
if line_done && input.is_just_pressed(Button::A) {
line_done = false;
wr.pop_line();
}
wr.update((0, HEIGHT - 40));
let end = timer.value();
frame += 1;
agb::println!(
"Took {} cycles, line done {}",
256 * (end.wrapping_sub(start) as u32),
line_done
);
}
}