mirror of
https://github.com/italicsjenga/agb.git
synced 2025-01-11 09:31:34 +11:00
Optimise all palettes together
This commit is contained in:
parent
c87a9ff077
commit
e97061a5af
agb-image-converter/src
examples/hyperspace-roll
|
@ -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<Colour>,
|
||||
) -> 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<u8>,
|
||||
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 {
|
||||
|
|
|
@ -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)]
|
||||
|
|
25
examples/hyperspace-roll/gfx/backgrounds.toml
Normal file
25
examples/hyperspace-roll/gfx/backgrounds.toml
Normal file
|
@ -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"
|
|
@ -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"
|
|
@ -1,6 +0,0 @@
|
|||
version = "1.0"
|
||||
|
||||
[image.help]
|
||||
filename = "help-text.png"
|
||||
tile_size = "8x8"
|
||||
transparent_colour = "121105"
|
|
@ -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"
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue