diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index ddbe8638..d482b81f 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -1,10 +1,11 @@ -use palette16::Palette16OptimisationResults; +use palette16::{Palette16OptimisationResults, Palette16Optimiser}; use proc_macro::TokenStream; use proc_macro2::Literal; use syn::parse::Parser; use syn::{parse_macro_input, punctuated::Punctuated, LitStr}; use syn::{Expr, ExprLit, Lit}; +use std::collections::HashMap; use std::path::PathBuf; use std::{iter, path::Path, str}; @@ -68,9 +69,46 @@ pub fn include_gfx(input: TokenStream) -> TokenStream { let include_path = path.to_string_lossy(); let images = config.images(); - let image_code = images.iter().map(|(image_name, &image)| { - convert_image(image, parent, image_name, &config.crate_prefix()) - }); + + let mut optimiser = Palette16Optimiser::new(None); + let mut assignment_offsets = HashMap::new(); + let mut assignment_offset = 0; + + for (name, settings) in images.iter() { + let image_filename = &parent.join(&settings.filename()); + let image = Image::load_from_file(image_filename); + + let tile_size = settings.tilesize().to_size(); + if image.width % tile_size != 0 || image.height % tile_size != 0 { + panic!("Image size not a multiple of tile size"); + } + + add_to_optimiser( + &mut optimiser, + &image, + tile_size, + settings.transparent_colour(), + ); + + let num_tiles = image.width * image.height / settings.tilesize().to_size().pow(2); + assignment_offsets.insert(name, assignment_offset); + assignment_offset += num_tiles; + } + + let optimisation_results = optimiser.optimise_palettes(); + + let mut image_code = vec![]; + + for (image_name, &image) in images.iter() { + image_code.push(convert_image( + image, + parent, + image_name, + &config.crate_prefix(), + &optimisation_results, + assignment_offsets[image_name], + )); + } let module = quote! { mod #module_name { @@ -217,38 +255,23 @@ fn convert_image( parent: &Path, variable_name: &str, crate_prefix: &str, + optimisation_results: &Palette16OptimisationResults, + assignment_offset: usize, ) -> proc_macro2::TokenStream { let image_filename = &parent.join(&settings.filename()); let image = Image::load_from_file(image_filename); - let tile_size = settings.tilesize().to_size(); - if image.width % tile_size != 0 || image.height % tile_size != 0 { - panic!("Image size not a multiple of tile size"); - } - - let optimiser = optimiser_for_image(&image, tile_size, settings.transparent_colour()); - let optimisation_results = optimiser.optimise_palettes(); - rust_generator::generate_code( variable_name, - &optimisation_results, + optimisation_results, &image, &image_filename.to_string_lossy(), settings.tilesize(), crate_prefix.to_owned(), + assignment_offset, ) } -fn optimiser_for_image( - image: &Image, - tile_size: usize, - transparent_colour: Option, -) -> palette16::Palette16Optimiser { - let mut palette_optimiser = palette16::Palette16Optimiser::new(transparent_colour); - add_to_optimiser(&mut palette_optimiser, image, tile_size, transparent_colour); - palette_optimiser -} - fn add_to_optimiser( palette_optimiser: &mut palette16::Palette16Optimiser, image: &Image, @@ -301,7 +324,7 @@ fn palette_tile_data( let tile_size = TileSize::Tile8; for image in images { - add_image_to_tile_data(&mut tile_data, image, tile_size, &optimiser) + add_image_to_tile_data(&mut tile_data, image, tile_size, &optimiser, 0) } let tile_data = collapse_to_4bpp(&tile_data); @@ -322,7 +345,8 @@ fn add_image_to_tile_data( tile_data: &mut Vec, image: &Image, tile_size: TileSize, - optimiser: &&Palette16OptimisationResults, + optimiser: &Palette16OptimisationResults, + assignment_offset: usize, ) { let tile_size = tile_size.to_size(); let tiles_x = image.width / tile_size; @@ -330,7 +354,7 @@ fn add_image_to_tile_data( for y in 0..tiles_y { for x in 0..tiles_x { - let palette_index = optimiser.assignments[y * tiles_x + x]; + let palette_index = optimiser.assignments[y * tiles_x + x + assignment_offset]; let palette = &optimiser.optimised_palettes[palette_index]; for inner_y in 0..tile_size / 8 { diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index 7f04b7eb..0a668036 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -14,6 +14,7 @@ pub(crate) fn generate_code( image_filename: &str, tile_size: TileSize, crate_prefix: String, + assignment_offset: usize, ) -> TokenStream { let crate_prefix = format_ident!("{}", crate_prefix); let output_variable_name = format_ident!("{}", output_variable_name); @@ -36,13 +37,20 @@ pub(crate) fn generate_code( let mut tile_data = Vec::new(); - add_image_to_tile_data(&mut tile_data, image, tile_size, &results); + add_image_to_tile_data(&mut tile_data, image, tile_size, results, assignment_offset); let tile_data = collapse_to_4bpp(&tile_data); let data = ByteString(&tile_data); - let assignments = results.assignments.iter().map(|&x| x as u8); + 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)] diff --git a/examples/hyperspace-roll/gfx/backgrounds.toml b/examples/hyperspace-roll/gfx/backgrounds.toml new file mode 100644 index 00000000..21ed1005 --- /dev/null +++ b/examples/hyperspace-roll/gfx/backgrounds.toml @@ -0,0 +1,25 @@ +version = "1.0" + +[image.stars] +filename = "stars.png" +tile_size = "8x8" +transparent_colour = "121105" + +[image.title] +filename = "title-screen.png" +tile_size = "8x8" + +[image.help] +filename = "help-text.png" +tile_size = "8x8" +transparent_colour = "121105" + +[image.descriptions1] +filename = "descriptions1.png" +tile_size = "8x8" +transparent_colour = "121105" + +[image.descriptions2] +filename = "descriptions2.png" +tile_size = "8x8" +transparent_colour = "121105" \ No newline at end of file diff --git a/examples/hyperspace-roll/gfx/descriptions.toml b/examples/hyperspace-roll/gfx/descriptions.toml deleted file mode 100644 index 9ce038e0..00000000 --- a/examples/hyperspace-roll/gfx/descriptions.toml +++ /dev/null @@ -1,11 +0,0 @@ -version = "1.0" - -[image.descriptions1] -filename = "descriptions1.png" -tile_size = "8x8" -transparent_colour = "121105" - -[image.descriptions2] -filename = "descriptions2.png" -tile_size = "8x8" -transparent_colour = "121105" \ No newline at end of file diff --git a/examples/hyperspace-roll/gfx/help.toml b/examples/hyperspace-roll/gfx/help.toml deleted file mode 100644 index 149b68d9..00000000 --- a/examples/hyperspace-roll/gfx/help.toml +++ /dev/null @@ -1,6 +0,0 @@ -version = "1.0" - -[image.help] -filename = "help-text.png" -tile_size = "8x8" -transparent_colour = "121105" diff --git a/examples/hyperspace-roll/gfx/stars.toml b/examples/hyperspace-roll/gfx/stars.toml deleted file mode 100644 index 354d1df4..00000000 --- a/examples/hyperspace-roll/gfx/stars.toml +++ /dev/null @@ -1,10 +0,0 @@ -version = "1.0" - -[image.stars] -filename = "stars.png" -tile_size = "8x8" -transparent_colour = "121105" - -[image.title] -filename = "title-screen.png" -tile_size = "8x8" \ No newline at end of file diff --git a/examples/hyperspace-roll/src/background.rs b/examples/hyperspace-roll/src/background.rs index c67cc709..037fa20a 100644 --- a/examples/hyperspace-roll/src/background.rs +++ b/examples/hyperspace-roll/src/background.rs @@ -5,17 +5,23 @@ use agb::{ use crate::sfx::Sfx; -include_gfx!("gfx/stars.toml"); - -include_gfx!("gfx/help.toml"); +include_gfx!("gfx/backgrounds.toml"); pub fn load_palettes(vram: &mut VRamManager) { - vram.set_background_palettes(&[ - stars::stars.palettes[0].clone(), - crate::customise::DESCRIPTIONS_1_PALETTE.clone(), - crate::customise::DESCRIPTIONS_2_PALETTE.clone(), - help::help.palettes[0].clone(), - ]); + vram.set_background_palettes(backgrounds::stars.palettes); +} + +fn description_tileset() -> (TileSet<'static>, TileSet<'static>) { + let descriptions_1_tileset = TileSet::new( + backgrounds::descriptions1.tiles, + agb::display::tiled::TileFormat::FourBpp, + ); + let descriptions_2_tileset = TileSet::new( + backgrounds::descriptions2.tiles, + agb::display::tiled::TileFormat::FourBpp, + ); + + (descriptions_1_tileset, descriptions_2_tileset) } pub(crate) fn load_help_text( @@ -24,18 +30,69 @@ pub(crate) fn load_help_text( help_text_line: u16, at_tile: (u16, u16), ) { - let help_tileset = TileSet::new(help::help.tiles, agb::display::tiled::TileFormat::FourBpp); + let help_tileset = TileSet::new( + backgrounds::help.tiles, + agb::display::tiled::TileFormat::FourBpp, + ); for x in 0..16 { + let tile_id = help_text_line * 16 + x; background.set_tile( vram, (x + at_tile.0, at_tile.1).into(), &help_tileset, - TileSetting::new(help_text_line * 16 + x, false, false, 3), + TileSetting::new( + tile_id, + false, + false, + backgrounds::help.palette_assignments[tile_id as usize], + ), ) } } +pub(crate) fn load_description( + upgrade: usize, + descriptions_map: &mut RegularMap, + vram: &mut VRamManager, +) { + let (descriptions_1_tileset, descriptions_2_tileset) = description_tileset(); + + for y in 0..11 { + for x in 0..8 { + if upgrade < 10 { + let tile_id = y * 8 + x + 8 * 11 * upgrade as u16; + + descriptions_map.set_tile( + vram, + (x, y).into(), + &descriptions_1_tileset, + TileSetting::new( + tile_id, + false, + false, + backgrounds::descriptions1.palette_assignments[tile_id as usize], + ), + ) + } else { + let tile_id = y * 8 + x + 8 * 11 * (upgrade as u16 - 10); + + descriptions_map.set_tile( + vram, + (x, y).into(), + &descriptions_2_tileset, + TileSetting::new( + tile_id, + false, + false, + backgrounds::descriptions2.palette_assignments[tile_id as usize], + ), + ) + } + } + } +} + // Expects a 64x32 map fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_tileset: &TileSet) { for x in 0..64u16 { @@ -47,7 +104,16 @@ fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_til } else { rng::gen().rem_euclid(64) as u16 }; - let tile_setting = TileSetting::new(tile_id, false, false, 0); + let tile_setting = TileSetting::new( + tile_id, + false, + false, + if blank { + 0 + } else { + backgrounds::stars.palette_assignments[tile_id as usize] + }, + ); map.set_tile(vram, (x, y).into(), stars_tileset, tile_setting); } @@ -58,8 +124,11 @@ fn create_background_map(map: &mut RegularMap, vram: &mut VRamManager, stars_til pub fn show_title_screen(background: &mut RegularMap, vram: &mut VRamManager, sfx: &mut Sfx) { background.set_scroll_pos((0_u16, 0_u16).into()); - vram.set_background_palettes(stars::title.palettes); - let tile_set = TileSet::new(stars::title.tiles, agb::display::tiled::TileFormat::FourBpp); + vram.set_background_palettes(backgrounds::title.palettes); + let tile_set = TileSet::new( + backgrounds::title.tiles, + agb::display::tiled::TileFormat::FourBpp, + ); background.hide(); for x in 0..30u16 { @@ -73,7 +142,7 @@ pub fn show_title_screen(background: &mut RegularMap, vram: &mut VRamManager, sf tile_id, false, false, - stars::title.palette_assignments[tile_id as usize], + backgrounds::title.palette_assignments[tile_id as usize], ), ); } @@ -100,7 +169,7 @@ impl<'a> StarBackground<'a> { background2: &'a mut RegularMap, vram: &'_ mut VRamManager, ) -> Self { - let stars_tileset = TileSet::new(stars::stars.tiles, TileFormat::FourBpp); + let stars_tileset = TileSet::new(backgrounds::stars.tiles, TileFormat::FourBpp); create_background_map(background1, vram, &stars_tileset); create_background_map(background2, vram, &stars_tileset); diff --git a/examples/hyperspace-roll/src/customise.rs b/examples/hyperspace-roll/src/customise.rs index c91f3cd9..a6d9e5b6 100644 --- a/examples/hyperspace-roll/src/customise.rs +++ b/examples/hyperspace-roll/src/customise.rs @@ -1,26 +1,20 @@ use agb::{ display::{ object::{Object, ObjectController}, - palette16::Palette16, - tiled::{RegularMap, TileSet, TileSetting, TiledMap}, + tiled::{RegularMap, TiledMap}, HEIGHT, WIDTH, }, - include_gfx, input::{Button, Tri}, }; use alloc::vec::Vec; use crate::{ + background::load_description, graphics::{FACE_SPRITES, MODIFIED_BOX, SELECTED_BOX, SELECT_BOX}, Agb, Die, Face, PlayerDice, }; -include_gfx!("gfx/descriptions.toml"); - -pub const DESCRIPTIONS_1_PALETTE: &Palette16 = &descriptions::descriptions1.palettes[0]; -pub const DESCRIPTIONS_2_PALETTE: &Palette16 = &descriptions::descriptions2.palettes[0]; - enum CustomiseState { Dice, Face, @@ -174,15 +168,6 @@ pub(crate) fn customise_screen( help_background.set_scroll_pos((u16::MAX - 148, u16::MAX - 34).into()); crate::background::load_help_text(&mut agb.vram, help_background, 0, (0, 0)); - let descriptions_1_tileset = TileSet::new( - descriptions::descriptions1.tiles, - agb::display::tiled::TileFormat::FourBpp, - ); - let descriptions_2_tileset = TileSet::new( - descriptions::descriptions2.tiles, - agb::display::tiled::TileFormat::FourBpp, - ); - // create the dice let mut _net = create_net(&agb.obj, &player_dice.dice[0], &[]); @@ -301,37 +286,11 @@ pub(crate) fn customise_screen( if (upgrades[cursor.upgrade] as u32) < 17 { if cursor.upgrade != old_updade { - for y in 0..11 { - for x in 0..8 { - if (upgrades[cursor.upgrade] as usize) < 10 { - descriptions_map.set_tile( - &mut agb.vram, - (x, y).into(), - &descriptions_1_tileset, - TileSetting::new( - y * 8 + x + 8 * 11 * upgrades[cursor.upgrade] as u16, - false, - false, - 1, - ), - ) - } else { - descriptions_map.set_tile( - &mut agb.vram, - (x, y).into(), - &descriptions_2_tileset, - TileSetting::new( - y * 8 - + x - + 8 * 11 * (upgrades[cursor.upgrade] as u16 - 10), - false, - false, - 2, - ), - ) - } - } - } + load_description( + upgrades[cursor.upgrade] as usize, + descriptions_map, + &mut agb.vram, + ); } descriptions_map.show(); } else {