From 4daafdec20c7f7020330c1737f2f873066b78c81 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 20:41:04 +0100 Subject: [PATCH] Actually output some rust code --- agb-image-converter/src/colour.rs | 5 ++ agb-image-converter/src/lib.rs | 14 +++- agb-image-converter/src/palette16.rs | 15 +++++ agb-image-converter/src/rust_generator.rs | 80 +++++++++++++++++++++++ agb/src/display/mod.rs | 1 + agb/src/display/palette16.rs | 9 +++ 6 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 agb-image-converter/src/rust_generator.rs create mode 100644 agb/src/display/palette16.rs diff --git a/agb-image-converter/src/colour.rs b/agb-image-converter/src/colour.rs index 4592a450..f5440e6f 100644 --- a/agb-image-converter/src/colour.rs +++ b/agb-image-converter/src/colour.rs @@ -9,4 +9,9 @@ impl Colour { pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { Colour { r, g, b } } + + pub fn to_rgb15(&self) -> u16 { + let (r, g, b) = (self.r as u16, self.g as u16, self.b as u16); + ((r >> 3) & 31) | (((g >> 3) & 31) << 5) | (((b >> 3) & 31) << 10) + } } diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 5c64af2d..9e2288c0 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; mod colour; mod image_loader; mod palette16; +mod rust_generator; use image_loader::Image; @@ -41,7 +42,18 @@ pub fn convert_image(settings: &ImageConverterConfig) { let optimiser = optimiser_for_image(&image, tile_size); let optimisation_results = optimiser.optimise_palettes(settings.transparent_colour); - println!("{:#?}", optimisation_results); + let stdout = std::io::stdout(); + let handle = stdout.lock(); + let mut writer = std::io::BufWriter::new(handle); + + rust_generator::generate_code( + &mut writer, + &optimisation_results, + &image, + settings.tile_size, + "HELLO", + ) + .expect("Failed to write data"); } fn optimiser_for_image(image: &Image, tile_size: usize) -> palette16::Palette16Optimiser { diff --git a/agb-image-converter/src/palette16.rs b/agb-image-converter/src/palette16.rs index d83d6f2c..d705164a 100644 --- a/agb-image-converter/src/palette16.rs +++ b/agb-image-converter/src/palette16.rs @@ -27,6 +27,12 @@ impl Palette16 { self.colours.push(colour); true } + pub fn colour_index(&self, colour: Colour) -> u8 { + self.colours + .iter() + .position(|c| *c == colour) + .expect("Can't get a colour index without it existing") as u8 + } fn union_length(&self, other: &Palette16) -> usize { self.colours @@ -44,6 +50,15 @@ impl Palette16 { } } +impl IntoIterator for Palette16 { + type Item = Colour; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.colours.into_iter() + } +} + pub(crate) struct Palette16Optimiser { palettes: Vec, colours: Vec, diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs new file mode 100644 index 00000000..f667dd25 --- /dev/null +++ b/agb-image-converter/src/rust_generator.rs @@ -0,0 +1,80 @@ +use std::io; +use std::io::Write; + +use crate::image_loader::Image; +use crate::palette16::Palette16OptimisationResults; +use crate::TileSize; + +pub(crate) fn generate_code( + output: &mut dyn Write, + results: &Palette16OptimisationResults, + image: &Image, + tile_size: TileSize, + tile_name: &str, +) -> io::Result<()> { + write!( + output, + "pub const {}_PALETTE_DATA: &'static [agb::display::palette16::Palette16] = &[\n", + tile_name + )?; + + for palette in &results.optimised_palettes { + write!(output, " agb::display::palette16::Palette16::new([")?; + + for colour in palette.clone() { + write!(output, "0x{:08x}, ", colour.to_rgb15())?; + } + + write!(output, "]),\n")?; + } + + write!(output, "];\n\n")?; + + write!( + output, + "pub const {}_TILE_DATA: &'static [u32] = &[\n", + tile_name + )?; + + let tile_size = tile_size.to_size(); + + let tiles_x = image.width / tile_size; + let tiles_y = image.height / tile_size; + + for y in 0..tiles_y { + for x in 0..tiles_x { + let palette_index = results.assignments[y * tiles_x + x]; + let palette = &results.optimised_palettes[palette_index]; + write!( + output, + " /* {}, {} (palette index {}) */\n", + x, y, palette_index + )?; + + for inner_y in 0..tile_size / 8 { + write!(output, " ")?; + + for inner_x in 0..tile_size / 8 { + for j in inner_y * 8..inner_y * 8 + 8 { + write!(output, "0x")?; + + for i in (inner_x * 8..inner_x * 8 + 7).rev() { + let colour = image.colour(x * tile_size + i, y * tile_size + j); + let colour_index = palette.colour_index(colour); + + write!(output, "{:x}", colour_index)?; + } + + write!(output, ", ")?; + } + } + } + + write!(output, "\n")?; + } + } + + write!(output, "];\n")?; + + Ok(()) +} diff --git a/agb/src/display/mod.rs b/agb/src/display/mod.rs index f5dd4faa..614c8cdf 100644 --- a/agb/src/display/mod.rs +++ b/agb/src/display/mod.rs @@ -7,6 +7,7 @@ use video::Video; pub mod bitmap3; pub mod bitmap4; pub mod object; +pub mod palette16; pub mod tiled0; pub mod vblank; pub mod video; diff --git a/agb/src/display/palette16.rs b/agb/src/display/palette16.rs new file mode 100644 index 00000000..dd9ecf80 --- /dev/null +++ b/agb/src/display/palette16.rs @@ -0,0 +1,9 @@ +pub struct Palette16 { + colours: [u16; 16], +} + +impl Palette16 { + pub const fn new(colours: [u16; 16]) -> Self { + Palette16 { colours } + } +}