agb/agb-image-converter/src/rust_generator.rs

152 lines
4.6 KiB
Rust
Raw Normal View History

use crate::deduplicator::{DeduplicatedData, Transformation};
2021-04-21 05:41:04 +10:00
use crate::palette16::Palette16OptimisationResults;
2023-04-14 07:18:13 +10:00
use crate::{add_image_256_to_tile_data, add_image_to_tile_data, collapse_to_4bpp};
use crate::{image_loader::Image, ByteString};
2021-04-21 05:41:04 +10:00
use proc_macro2::TokenStream;
use quote::{format_ident, quote};
2023-08-29 23:39:41 +10:00
use std::collections::BTreeMap;
use std::iter;
pub(crate) fn generate_palette_code(
2021-04-21 05:41:04 +10:00
results: &Palette16OptimisationResults,
crate_prefix: &str,
) -> TokenStream {
let crate_prefix = format_ident!("{}", crate_prefix);
let palettes = results.optimised_palettes.iter().map(|palette| {
let colours = palette
.clone()
.into_iter()
.map(|colour| colour.to_rgb15())
.chain(iter::repeat(0))
2023-01-07 05:26:03 +11:00
.take(16);
quote! {
#crate_prefix::display::palette16::Palette16::new([
#(#colours),*
])
2021-04-21 05:41:04 +10:00
}
});
2021-04-21 05:41:04 +10:00
quote! {
pub const PALETTES: &[#crate_prefix::display::palette16::Palette16] = &[#(#palettes),*];
}
}
pub(crate) fn generate_code(
output_variable_name: &str,
results: &Palette16OptimisationResults,
image: &Image,
image_filename: &str,
crate_prefix: String,
assignment_offset: Option<usize>,
deduplicate: bool,
) -> TokenStream {
let crate_prefix = format_ident!("{}", crate_prefix);
let output_variable_name = format_ident!("{}", output_variable_name);
let (image, dedup_data) = if deduplicate {
let (new_image, dedup_data) =
crate::deduplicator::deduplicate_image(image, assignment_offset.is_some());
(new_image, dedup_data)
} else {
(
image.clone(),
(0..(image.width * image.height / 8 / 8))
.map(|i| DeduplicatedData {
new_index: i,
transformation: Transformation::none(),
})
.collect(),
)
};
2023-08-29 23:39:41 +10:00
let remap_index = dedup_data
.iter()
.enumerate()
.map(|(i, data)| (data.new_index, i))
.collect::<BTreeMap<_, _>>(); // BTreeMap so that values below is in order
let remap_index = remap_index.values().cloned().collect::<Vec<_>>();
2022-08-12 08:48:57 +10:00
let (tile_data, assignments) = if let Some(assignment_offset) = assignment_offset {
let mut tile_data = Vec::new();
2021-04-21 05:41:04 +10:00
2023-08-29 23:39:41 +10:00
add_image_to_tile_data(
&mut tile_data,
&image,
results,
assignment_offset,
false,
&remap_index,
);
2021-04-21 05:41:04 +10:00
2022-08-12 08:48:57 +10:00
let tile_data = collapse_to_4bpp(&tile_data);
2023-04-14 07:18:13 +10:00
let num_tiles = image.width * image.height / 8usize.pow(2);
2022-08-12 08:48:57 +10:00
2023-08-29 23:39:41 +10:00
let all_assignments = &results.assignments[assignment_offset..];
let assignments = (0..num_tiles)
.map(|tile_id| all_assignments[remap_index[tile_id]] as u8)
2022-08-12 08:48:57 +10:00
.collect();
(tile_data, assignments)
} else {
let mut tile_data = Vec::new();
2021-07-27 08:38:22 +10:00
add_image_256_to_tile_data(&mut tile_data, &image, results);
2022-08-12 07:22:44 +10:00
2022-08-12 08:48:57 +10:00
(tile_data, vec![])
};
let tile_settings = dedup_data.iter().map(|data| {
let palette_assignment = assignments.get(data.new_index).unwrap_or(&0);
let vflipped = data.transformation.vflip;
let hflipped = data.transformation.hflip;
2023-08-29 23:13:40 +10:00
let index = data.new_index as u16;
quote! {
#crate_prefix::display::tiled::TileSetting::new(#index, #hflipped, #vflipped, #palette_assignment)
}
});
2022-08-12 08:48:57 +10:00
let data = ByteString(&tile_data);
2023-08-31 01:08:43 +10:00
let tile_format = if assignment_offset.is_some() {
quote! { #crate_prefix::display::tiled::TileFormat::FourBpp }
} else {
quote! { #crate_prefix::display::tiled::TileFormat::EightBpp }
};
quote! {
#[allow(non_upper_case_globals)]
pub const #output_variable_name: #crate_prefix::display::tile_data::TileData = {
const _: &[u8] = include_bytes!(#image_filename);
2022-10-22 22:41:58 +11:00
const TILE_DATA: &[u8] = {
pub struct AlignedAs<Align, Bytes: ?Sized> {
pub _align: [Align; 0],
pub bytes: Bytes,
}
2023-09-06 09:21:27 +10:00
const ALIGNED: &AlignedAs<u32, [u8]> = &AlignedAs {
2022-10-22 22:41:58 +11:00
_align: [],
bytes: *#data,
};
&ALIGNED.bytes
};
2023-08-31 01:08:43 +10:00
const TILE_SET: #crate_prefix::display::tiled::TileSet = #crate_prefix::display::tiled::TileSet::new(TILE_DATA, #tile_format);
const TILE_SETTINGS: &[#crate_prefix::display::tiled::TileSetting] = &[
#(#tile_settings),*
];
2023-08-31 01:08:43 +10:00
#crate_prefix::display::tile_data::TileData::new(TILE_SET, TILE_SETTINGS)
};
2021-04-21 05:41:04 +10:00
}
}