From ff89f7f425d0c745f34b7f28bc6dbce551707801 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Thu, 11 Aug 2022 23:48:57 +0100 Subject: [PATCH] Get first example working --- agb-image-converter/src/lib.rs | 41 +++++++++++++- agb-image-converter/src/rust_generator.rs | 39 ++++++++----- agb/examples/affine_background.rs | 69 +++++++++++++++++++++++ agb/examples/affine_tiles.toml | 6 ++ agb/src/display/tiled/map.rs | 10 ++-- agb/src/syscall.rs | 6 +- 6 files changed, 147 insertions(+), 24 deletions(-) create mode 100644 agb/examples/affine_background.rs create mode 100644 agb/examples/affine_tiles.toml diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 235de782..8d6e7183 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -112,13 +112,18 @@ pub fn include_gfx(input: TokenStream) -> TokenStream { let mut image_code = vec![]; for (image_name, &image) in images.iter() { + let assignment_offset = match image.colours() { + Colours::Colours16 => Some(assignment_offsets[image_name]), + _ => None, + }; + image_code.push(convert_image( image, parent, image_name, &config.crate_prefix(), &optimisation_results, - assignment_offsets[image_name], + assignment_offset, )); } @@ -268,7 +273,7 @@ fn convert_image( variable_name: &str, crate_prefix: &str, optimisation_results: &Palette16OptimisationResults, - assignment_offset: usize, + assignment_offset: Option, ) -> proc_macro2::TokenStream { let image_filename = &parent.join(&settings.filename()); let image = Image::load_from_file(image_filename); @@ -384,6 +389,38 @@ fn add_image_to_tile_data( } } +fn add_image_256_to_tile_data( + tile_data: &mut Vec, + image: &Image, + tile_size: TileSize, + optimiser: &Palette16OptimisationResults, +) { + let tile_size = tile_size.to_size(); + let tiles_x = image.width / tile_size; + let tiles_y = image.height / tile_size; + + let all_colours: Vec<_> = optimiser + .optimised_palettes + .iter() + .flat_map(|p| p.colours()) + .collect(); + + for y in 0..tiles_y { + for x in 0..tiles_x { + for inner_y in 0..tile_size / 8 { + for inner_x in 0..tile_size / 8 { + for j in inner_y * 8..inner_y * 8 + 8 { + for i in inner_x * 8..inner_x * 8 + 8 { + let colour = image.colour(x * tile_size + i, y * tile_size + j); + tile_data.push(all_colours.iter().position(|c| **c == colour).unwrap() as u8); + } + } + } + } + } + } +} + fn flatten_group(expr: &Expr) -> &Expr { match expr { Expr::Group(group) => &group.expr, diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index 0a668036..3e70466c 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -1,5 +1,5 @@ use crate::palette16::Palette16OptimisationResults; -use crate::{add_image_to_tile_data, collapse_to_4bpp, TileSize}; +use crate::{add_image_256_to_tile_data, add_image_to_tile_data, collapse_to_4bpp, TileSize}; use crate::{image_loader::Image, ByteString}; use proc_macro2::TokenStream; @@ -14,7 +14,7 @@ pub(crate) fn generate_code( image_filename: &str, tile_size: TileSize, crate_prefix: String, - assignment_offset: usize, + assignment_offset: Option, ) -> TokenStream { let crate_prefix = format_ident!("{}", crate_prefix); let output_variable_name = format_ident!("{}", output_variable_name); @@ -35,23 +35,34 @@ pub(crate) fn generate_code( } }); - let mut tile_data = Vec::new(); + let (tile_data, assignments) = if let Some(assignment_offset) = assignment_offset { + let mut tile_data = Vec::new(); - add_image_to_tile_data(&mut tile_data, image, tile_size, results, assignment_offset); + add_image_to_tile_data(&mut tile_data, image, tile_size, results, assignment_offset); - let tile_data = collapse_to_4bpp(&tile_data); + let tile_data = collapse_to_4bpp(&tile_data); + + let num_tiles = image.width * image.height / tile_size.to_size().pow(2); + + let assignments = results + .assignments + .iter() + .skip(assignment_offset) + .take(num_tiles) + .map(|&x| x as u8) + .collect(); + + (tile_data, assignments) + } else { + let mut tile_data = Vec::new(); + + add_image_256_to_tile_data(&mut tile_data, image, tile_size, results); + + (tile_data, vec![]) + }; let data = ByteString(&tile_data); - let num_tiles = image.width * image.height / tile_size.to_size().pow(2); - - let assignments = results - .assignments - .iter() - .skip(assignment_offset) - .take(num_tiles) - .map(|&x| x as u8); - quote! { #[allow(non_upper_case_globals)] pub const #output_variable_name: #crate_prefix::display::tile_data::TileData = { diff --git a/agb/examples/affine_background.rs b/agb/examples/affine_background.rs new file mode 100644 index 00000000..f5519727 --- /dev/null +++ b/agb/examples/affine_background.rs @@ -0,0 +1,69 @@ +#![no_std] +#![no_main] + +use agb::{ + display::{ + tiled::{AffineBackgroundSize, TileFormat, TileSet, TiledMap}, + Priority, + }, + fixnum::{num, Num}, + include_gfx, + input::Tri, +}; + +include_gfx!("examples/affine_tiles.toml"); + +#[agb::entry] +fn main(mut gba: agb::Gba) -> ! { + let (gfx, mut vram) = gba.display.video.tiled2(); + let vblank = agb::interrupt::VBlank::get(); + + let tileset = TileSet::new(affine_tiles::water_tiles.tiles, TileFormat::EightBpp); + + vram.set_background_palettes(affine_tiles::water_tiles.palettes); + + let mut bg = gfx.background(Priority::P0, AffineBackgroundSize::Background32x32); + + for y in 0..32u16 { + for x in 0..32u16 { + bg.set_tile(&mut vram, (x, y).into(), &tileset, 1); + } + } + + bg.commit(&mut vram); + bg.show(); + + let mut rotation = num!(0.); + let rotation_increase = num!(1.); + + let mut input = agb::input::ButtonController::new(); + + loop { + input.update(); + + let x_dir = match input.x_tri() { + Tri::Positive => (1, 0).into(), + Tri::Negative => (-1, 0).into(), + _ => (0, 0).into(), + }; + + let y_dir = match input.y_tri() { + Tri::Positive => (0, 1).into(), + Tri::Negative => (0, -1).into(), + _ => (0, 0).into(), + }; + + let new_scroll_pos = bg.scroll_pos() + x_dir + y_dir; + agb::println!("{:?}", new_scroll_pos); + bg.set_scroll_pos(new_scroll_pos); + bg.set_transform((0i16, 0i16).into(), (1, 1).into(), rotation); + + rotation += rotation_increase; + if rotation >= num!(255.) { + rotation = 0.into(); + } + + vblank.wait_for_vblank(); + bg.commit(&mut vram); + } +} diff --git a/agb/examples/affine_tiles.toml b/agb/examples/affine_tiles.toml new file mode 100644 index 00000000..65d608a2 --- /dev/null +++ b/agb/examples/affine_tiles.toml @@ -0,0 +1,6 @@ +version = "1.0" + +[image.water_tiles] +filename = "water_tiles.png" +tile_size = "8x8" +colours = 256 \ No newline at end of file diff --git a/agb/src/display/tiled/map.rs b/agb/src/display/tiled/map.rs index 1933663a..7af1f57b 100644 --- a/agb/src/display/tiled/map.rs +++ b/agb/src/display/tiled/map.rs @@ -278,16 +278,16 @@ impl TiledMapPrivate for AffineMap { &mut self.tiles_dirty } fn x_scroll_mut(&mut self) -> &mut Self::Position { - &mut self.transform.position.x + &mut self.bg_center.x } fn y_scroll_mut(&mut self) -> &mut Self::Position { - &mut self.transform.position.y + &mut self.bg_center.y } fn x_scroll(&self) -> Self::Position { - self.transform.position.x + self.bg_center.x } fn y_scroll(&self) -> Self::Position { - self.transform.position.y + self.bg_center.y } fn affine_matrix(&self) -> Self::AffineMatrix { self.transform.matrix @@ -377,7 +377,7 @@ impl AffineMap { &mut self, display_center: Vector2D, scale: Vector2D>, - rotation: Num, + rotation: Num, ) { self.set_transform_raw(crate::syscall::bg_affine_matrix( self.bg_center, diff --git a/agb/src/syscall.rs b/agb/src/syscall.rs index 59d37a52..a91b8b79 100644 --- a/agb/src/syscall.rs +++ b/agb/src/syscall.rs @@ -159,21 +159,21 @@ pub fn bg_affine_matrix( bg_center: Vector2D>, display_center: Vector2D, scale: Vector2D>, - rotation: Num, + rotation: Num, ) -> BgAffineSetData { #[repr(C, packed)] struct Input { bg_center: Vector2D>, display_center: Vector2D, scale: Vector2D>, - rotation: u16, + rotation: Num, } let input = Input { bg_center, display_center, scale, - rotation: u16::from(rotation.to_raw()) << 8, + rotation, }; let mut output = MaybeUninit::uninit();