From 58d6876e17ba2af6b2d1cb7a2222e69e0bcd0849 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 19 Apr 2021 22:51:41 +0100 Subject: [PATCH 01/17] Add hello world program --- agb-image-converter/Cargo.lock | 7 +++++++ agb-image-converter/Cargo.toml | 5 +++++ agb-image-converter/src/main.rs | 3 +++ 3 files changed, 15 insertions(+) create mode 100644 agb-image-converter/Cargo.lock create mode 100644 agb-image-converter/Cargo.toml create mode 100644 agb-image-converter/src/main.rs diff --git a/agb-image-converter/Cargo.lock b/agb-image-converter/Cargo.lock new file mode 100644 index 00000000..c0343560 --- /dev/null +++ b/agb-image-converter/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "agb-image-converter" +version = "0.1.0" diff --git a/agb-image-converter/Cargo.toml b/agb-image-converter/Cargo.toml new file mode 100644 index 00000000..c3dc5975 --- /dev/null +++ b/agb-image-converter/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "agb-image-converter" +version = "0.1.0" +authors = ["Gwilym Kuiper "] +edition = "2018" diff --git a/agb-image-converter/src/main.rs b/agb-image-converter/src/main.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/agb-image-converter/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} From c8d0f82c349d971fc54c1c5177bbe0f8ab791365 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 19 Apr 2021 23:01:28 +0100 Subject: [PATCH 02/17] Actually make a library and start sketching out the interface --- agb-image-converter/src/lib.rs | 41 +++++++++++++++++++++++++++++++++ agb-image-converter/src/main.rs | 3 --- 2 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 agb-image-converter/src/lib.rs delete mode 100644 agb-image-converter/src/main.rs diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs new file mode 100644 index 00000000..c9401b76 --- /dev/null +++ b/agb-image-converter/src/lib.rs @@ -0,0 +1,41 @@ +#[derive(Debug, Clone, Copy)] +pub struct Colour { + r: u8, + g: u8, + b: u8, +} + +impl Colour { + pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { + Colour { r, g, b } + } +} + +#[derive(Debug, Clone, Copy)] +pub enum TileSize { + Tile8, + Tile16, +} + +pub struct ImageConverter {} + +pub struct ImageConverterConfigBuilder { + transparent_colour: Option, + tile_size: TileSize, +} + +impl ImageConverterConfigBuilder { + pub fn new_with_tile_size(tile_size: TileSize) -> Self { + ImageConverterConfigBuilder { + tile_size, + transparent_colour: None, + } + } + + pub fn with_transparent_colour(&self, transparent_colour: Colour) -> Self { + ImageConverterConfigBuilder { + transparent_colour: Some(transparent_colour), + ..*self + } + } +} diff --git a/agb-image-converter/src/main.rs b/agb-image-converter/src/main.rs deleted file mode 100644 index e7a11a96..00000000 --- a/agb-image-converter/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} From 725543912ad08141a7556480c868bd577019f460 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Mon, 19 Apr 2021 23:15:03 +0100 Subject: [PATCH 03/17] Add image loading --- agb-image-converter/Cargo.lock | 325 +++++++++++++++++++++++++++++++++ agb-image-converter/Cargo.toml | 3 + agb-image-converter/src/lib.rs | 41 +---- 3 files changed, 338 insertions(+), 31 deletions(-) diff --git a/agb-image-converter/Cargo.lock b/agb-image-converter/Cargo.lock index c0343560..ca3183df 100644 --- a/agb-image-converter/Cargo.lock +++ b/agb-image-converter/Cargo.lock @@ -2,6 +2,331 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "agb-image-converter" version = "0.1.0" +dependencies = [ + "image", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bytemuck" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "deflate" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "gif" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "gif", + "jpeg-decoder", + "num-iter", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + +[[package]] +name = "jpeg-decoder" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" +dependencies = [ + "rayon", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" + +[[package]] +name = "memoffset" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +dependencies = [ + "adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "png" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide 0.3.7", +] + +[[package]] +name = "rayon" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "tiff" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" +dependencies = [ + "jpeg-decoder", + "miniz_oxide 0.4.4", + "weezl", +] + +[[package]] +name = "weezl" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" diff --git a/agb-image-converter/Cargo.toml b/agb-image-converter/Cargo.toml index c3dc5975..3635cf2d 100644 --- a/agb-image-converter/Cargo.toml +++ b/agb-image-converter/Cargo.toml @@ -3,3 +3,6 @@ name = "agb-image-converter" version = "0.1.0" authors = ["Gwilym Kuiper "] edition = "2018" + +[dependencies] +image = "0.23.14" \ No newline at end of file diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index c9401b76..10e07096 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -1,15 +1,8 @@ -#[derive(Debug, Clone, Copy)] -pub struct Colour { - r: u8, - g: u8, - b: u8, -} +use std::path; -impl Colour { - pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { - Colour { r, g, b } - } -} +mod colour; + +pub use colour::Colour; #[derive(Debug, Clone, Copy)] pub enum TileSize { @@ -17,25 +10,11 @@ pub enum TileSize { Tile16, } -pub struct ImageConverter {} - -pub struct ImageConverterConfigBuilder { - transparent_colour: Option, - tile_size: TileSize, +pub struct ImageConverterConfig { + pub transparent_colour: Option, + pub tile_size: TileSize, + pub input_file: path::PathBuf, + pub output_file: path::PathBuf, } -impl ImageConverterConfigBuilder { - pub fn new_with_tile_size(tile_size: TileSize) -> Self { - ImageConverterConfigBuilder { - tile_size, - transparent_colour: None, - } - } - - pub fn with_transparent_colour(&self, transparent_colour: Colour) -> Self { - ImageConverterConfigBuilder { - transparent_colour: Some(transparent_colour), - ..*self - } - } -} +pub fn convert_image(setting: &ImageConverterConfig) {} From 0fe4e23758d0e1834a0fd4d2bb983acac8295a97 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 00:40:07 +0100 Subject: [PATCH 04/17] Add palette optimisation --- agb-image-converter/src/colour.rs | 12 ++ agb-image-converter/src/image_loader.rs | 37 ++++++ agb-image-converter/src/lib.rs | 60 ++++++++- agb-image-converter/src/palette16.rs | 170 ++++++++++++++++++++++++ 4 files changed, 275 insertions(+), 4 deletions(-) create mode 100644 agb-image-converter/src/colour.rs create mode 100644 agb-image-converter/src/image_loader.rs create mode 100644 agb-image-converter/src/palette16.rs diff --git a/agb-image-converter/src/colour.rs b/agb-image-converter/src/colour.rs new file mode 100644 index 00000000..4592a450 --- /dev/null +++ b/agb-image-converter/src/colour.rs @@ -0,0 +1,12 @@ +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct Colour { + pub r: u8, + pub g: u8, + pub b: u8, +} + +impl Colour { + pub fn from_rgb(r: u8, g: u8, b: u8) -> Self { + Colour { r, g, b } + } +} diff --git a/agb-image-converter/src/image_loader.rs b/agb-image-converter/src/image_loader.rs new file mode 100644 index 00000000..aa3f5921 --- /dev/null +++ b/agb-image-converter/src/image_loader.rs @@ -0,0 +1,37 @@ +use std::path; + +use image::GenericImageView; + +use crate::colour::Colour; + +pub(crate) struct Image { + pub width: usize, + pub height: usize, + colour_data: Vec, +} + +impl Image { + pub fn load_from_file(image_path: &path::Path) -> Self { + let img = image::open(image_path).expect("Expected image to exist"); + let (width, height) = img.dimensions(); + + let width = width as usize; + let height = height as usize; + + let mut colour_data = Vec::with_capacity(width * height); + + for (_, _, pixel) in img.pixels() { + colour_data.push(Colour::from_rgb(pixel[0], pixel[1], pixel[2])); + } + + Image { + width, + height, + colour_data, + } + } + + pub fn colour(&self, x: usize, y: usize) -> Colour { + self.colour_data[x + y * self.width] + } +} diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 10e07096..3f3905ca 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -1,6 +1,10 @@ -use std::path; +use std::path::PathBuf; mod colour; +mod image_loader; +mod palette16; + +use image_loader::Image; pub use colour::Colour; @@ -10,11 +14,59 @@ pub enum TileSize { Tile16, } +impl TileSize { + fn to_size(&self) -> usize { + match &self { + TileSize::Tile8 => 8, + TileSize::Tile16 => 16, + } + } +} + pub struct ImageConverterConfig { pub transparent_colour: Option, pub tile_size: TileSize, - pub input_file: path::PathBuf, - pub output_file: path::PathBuf, + pub input_image: PathBuf, + pub output_file: PathBuf, } -pub fn convert_image(setting: &ImageConverterConfig) {} +pub fn convert_image(settings: &ImageConverterConfig) { + let image = Image::load_from_file(&settings.input_image); + + let tile_size = settings.tile_size.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); + let optimisation_results = optimiser.optimise_palettes(settings.transparent_colour); + + println!("{:?}", optimisation_results); +} + +fn optimiser_for_image(image: &Image, tile_size: usize) -> palette16::Palette16Optimiser { + let tiles_x = image.width / tile_size; + let tiles_y = image.height / tile_size; + + let mut palette_optimiser = palette16::Palette16Optimiser::new(); + + for y in 0..tiles_y { + for x in 0..tiles_x { + let mut palette = palette16::Palette16::new(); + + for j in 0..tile_size { + for i in 0..tile_size { + let colour = image.colour(x * tile_size + i, y * tile_size + j); + + if !palette.add_colour(colour) { + panic!("Tile contains more than 16 colours"); + } + } + } + + palette_optimiser.add_palette(palette); + } + } + + palette_optimiser +} diff --git a/agb-image-converter/src/palette16.rs b/agb-image-converter/src/palette16.rs new file mode 100644 index 00000000..5522c937 --- /dev/null +++ b/agb-image-converter/src/palette16.rs @@ -0,0 +1,170 @@ +use crate::colour::Colour; +use std::collections::HashSet; + +const MAX_COLOURS: usize = 256; +const MAX_COLOURS_PER_PALETTE: usize = 16; + +#[derive(Debug, Clone, Eq, PartialEq, Hash)] +pub(crate) struct Palette16 { + colours: Vec, +} + +impl Palette16 { + pub fn new() -> Self { + Palette16 { + colours: Vec::with_capacity(MAX_COLOURS_PER_PALETTE), + } + } + + pub fn add_colour(&mut self, colour: Colour) -> bool { + if self.colours.contains(&colour) { + return false; + } + + if self.colours.len() == MAX_COLOURS_PER_PALETTE { + panic!("Can have at most 16 colours in a single palette"); + } + self.colours.push(colour); + true + } + + fn union_length(&self, other: &Palette16) -> usize { + self.colours + .iter() + .chain(&other.colours) + .collect::>() + .len() + } + + fn is_satisfied_by(&self, other: &Palette16) -> bool { + self.colours + .iter() + .collect::>() + .is_subset(&other.colours.iter().collect::>()) + } +} + +pub(crate) struct Palette16Optimiser { + palettes: Vec, + colours: Vec, +} + +#[derive(Debug)] +pub(crate) struct Palette16OptimisationResults { + pub optimised_palettes: Vec, + pub assignments: Vec, +} + +impl Palette16Optimiser { + pub fn new() -> Self { + Palette16Optimiser { + palettes: vec![], + colours: Vec::new(), + } + } + + pub fn add_palette(&mut self, palette: Palette16) { + self.palettes.push(palette.clone()); + + for colour in palette.colours { + if self.colours.contains(&colour) { + continue; + } + + self.colours.push(colour); + } + + if self.colours.len() > MAX_COLOURS { + panic!("Cannot have over 256 colours"); + } + } + + pub fn optimise_palettes( + &self, + transparent_colour: Option, + ) -> Palette16OptimisationResults { + let mut assignments = vec![0; self.palettes.len()]; + let mut optimised_palettes = vec![]; + + let mut unsatisfied_palettes = self + .palettes + .iter() + .cloned() + .collect::>(); + + while unsatisfied_palettes.len() > 0 { + let palette = self.find_maximal_palette_for(&unsatisfied_palettes, transparent_colour); + + for test_palette in unsatisfied_palettes.clone() { + if test_palette.is_satisfied_by(&palette) { + unsatisfied_palettes.remove(&test_palette); + } + } + + for (i, overall_palette) in self.palettes.iter().enumerate() { + if overall_palette.is_satisfied_by(&palette) { + assignments[i] = optimised_palettes.len(); + } + } + + optimised_palettes.push(palette); + + if optimised_palettes.len() == MAX_COLOURS / MAX_COLOURS_PER_PALETTE { + panic!("Failed to find covering palettes"); + } + } + + Palette16OptimisationResults { + assignments, + optimised_palettes, + } + } + + fn find_maximal_palette_for( + &self, + unsatisfied_palettes: &HashSet, + transparent_colour: Option, + ) -> Palette16 { + let mut palette = Palette16::new(); + + if let Some(transparent_colour) = transparent_colour { + palette.add_colour(transparent_colour); + } + + loop { + let mut colour_usage = vec![0; MAX_COLOURS]; + let mut a_colour_is_used = false; + + for current_palette in unsatisfied_palettes { + if palette.union_length(¤t_palette) > MAX_COLOURS_PER_PALETTE { + continue; + } + + for colour in ¤t_palette.colours { + if let Some(colour_index) = self.colours.iter().position(|c| c == colour) { + colour_usage[colour_index] += 1; + a_colour_is_used = true; + } + } + } + + if !a_colour_is_used { + return palette; + } + + let best_index = colour_usage + .iter() + .enumerate() + .max_by(|(_, usage1), (_, usage2)| usage1.cmp(usage2)) + .unwrap() + .0; + + let best_colour = self.colours[best_index]; + + palette.add_colour(best_colour); + if palette.colours.len() == MAX_COLOURS_PER_PALETTE { + return palette; + } + } + } +} From b5e01fc2dc3a77e9f082d5a03204f6b429648226 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 00:40:14 +0100 Subject: [PATCH 05/17] Want to exclude every target directory --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0bf0d905..15aac9f2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ -*/target +target /out /.vscode From beff079880d47469b722a251c92027810ba39396 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 00:57:26 +0100 Subject: [PATCH 06/17] Don't try to check the same colour repeatedly --- agb-image-converter/src/palette16.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/agb-image-converter/src/palette16.rs b/agb-image-converter/src/palette16.rs index 5522c937..d83d6f2c 100644 --- a/agb-image-converter/src/palette16.rs +++ b/agb-image-converter/src/palette16.rs @@ -141,6 +141,10 @@ impl Palette16Optimiser { } for colour in ¤t_palette.colours { + if palette.colours.contains(&colour) { + continue; + } + if let Some(colour_index) = self.colours.iter().position(|c| c == colour) { colour_usage[colour_index] += 1; a_colour_is_used = true; From f92daa3fc3ad36e49edd19f8df65728eef8e730f Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 00:57:47 +0100 Subject: [PATCH 07/17] Improve debug output --- agb-image-converter/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 3f3905ca..5c64af2d 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -41,7 +41,7 @@ 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); + println!("{:#?}", optimisation_results); } fn optimiser_for_image(image: &Image, tile_size: usize) -> palette16::Palette16Optimiser { @@ -58,9 +58,7 @@ fn optimiser_for_image(image: &Image, tile_size: usize) -> palette16::Palette16O for i in 0..tile_size { let colour = image.colour(x * tile_size + i, y * tile_size + j); - if !palette.add_colour(colour) { - panic!("Tile contains more than 16 colours"); - } + palette.add_colour(colour); } } From 4728f2280613ec3b299de1c241d56cf16420f432 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 00:58:03 +0100 Subject: [PATCH 08/17] Name crate correctly and add a simple test program --- agb-image-converter/Cargo.lock | 2 +- agb-image-converter/Cargo.toml | 2 +- agb-image-converter/src/bin/convert.rs | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) create mode 100644 agb-image-converter/src/bin/convert.rs diff --git a/agb-image-converter/Cargo.lock b/agb-image-converter/Cargo.lock index ca3183df..e81e9ed8 100644 --- a/agb-image-converter/Cargo.lock +++ b/agb-image-converter/Cargo.lock @@ -15,7 +15,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" [[package]] -name = "agb-image-converter" +name = "agb_image_converter" version = "0.1.0" dependencies = [ "image", diff --git a/agb-image-converter/Cargo.toml b/agb-image-converter/Cargo.toml index 3635cf2d..2be58b95 100644 --- a/agb-image-converter/Cargo.toml +++ b/agb-image-converter/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "agb-image-converter" +name = "agb_image_converter" version = "0.1.0" authors = ["Gwilym Kuiper "] edition = "2018" diff --git a/agb-image-converter/src/bin/convert.rs b/agb-image-converter/src/bin/convert.rs new file mode 100644 index 00000000..0e7d3206 --- /dev/null +++ b/agb-image-converter/src/bin/convert.rs @@ -0,0 +1,15 @@ +use std::env; + +use agb_image_converter::{convert_image, ImageConverterConfig, TileSize}; + +fn main() -> () { + let args: Vec<_> = env::args().collect(); + + let file_path = &args[1]; + convert_image(&ImageConverterConfig { + transparent_colour: None, + tile_size: TileSize::Tile8, + input_image: file_path.into(), + output_file: "".into(), + }); +} From 4daafdec20c7f7020330c1737f2f873066b78c81 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 20:41:04 +0100 Subject: [PATCH 09/17] 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 } + } +} From d1412fb709f1e58855408d8ae59728488c4e4db6 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 20:51:49 +0100 Subject: [PATCH 10/17] Actually write to a file and also include palette assignments --- agb-image-converter/src/bin/convert.rs | 4 +++- agb-image-converter/src/lib.rs | 10 ++++++---- agb-image-converter/src/rust_generator.rs | 17 ++++++++++++++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/agb-image-converter/src/bin/convert.rs b/agb-image-converter/src/bin/convert.rs index 0e7d3206..0796b7b4 100644 --- a/agb-image-converter/src/bin/convert.rs +++ b/agb-image-converter/src/bin/convert.rs @@ -6,10 +6,12 @@ fn main() -> () { let args: Vec<_> = env::args().collect(); let file_path = &args[1]; + let output_path = &args[2]; convert_image(&ImageConverterConfig { transparent_colour: None, tile_size: TileSize::Tile8, input_image: file_path.into(), - output_file: "".into(), + output_file: output_path.into(), + output_name: "HELLO".to_owned(), }); } diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 9e2288c0..3209ac37 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -1,3 +1,5 @@ +use std::fs::File; +use std::io::BufWriter; use std::path::PathBuf; mod colour; @@ -29,6 +31,7 @@ pub struct ImageConverterConfig { pub tile_size: TileSize, pub input_image: PathBuf, pub output_file: PathBuf, + pub output_name: String, } pub fn convert_image(settings: &ImageConverterConfig) { @@ -42,16 +45,15 @@ pub fn convert_image(settings: &ImageConverterConfig) { let optimiser = optimiser_for_image(&image, tile_size); let optimisation_results = optimiser.optimise_palettes(settings.transparent_colour); - let stdout = std::io::stdout(); - let handle = stdout.lock(); - let mut writer = std::io::BufWriter::new(handle); + let output_file = File::create(&settings.output_file).expect("Failed to create file"); + let mut writer = BufWriter::new(output_file); rust_generator::generate_code( &mut writer, &optimisation_results, &image, settings.tile_size, - "HELLO", + &settings.output_name, ) .expect("Failed to write data"); } diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index f667dd25..1f241f35 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -74,7 +74,22 @@ pub(crate) fn generate_code( } } - write!(output, "];\n")?; + write!(output, "];\n\n")?; + + write!( + output, + "pub const {}_PALETTE_ASSIGNMENT: &'static [u8] = &[", + tile_name + )?; + + for (i, assignment) in results.assignments.iter().enumerate() { + if i % 16 == 0 { + write!(output, "\n ")?; + } + write!(output, "{}, ", assignment)?; + } + + write!(output, "\n];\n")?; Ok(()) } From b4c3bd7356b68e74e23748db0dad7ceb3997fb68 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 21:07:57 +0100 Subject: [PATCH 11/17] Don't generate if source hasn't been modified --- agb-image-converter/src/lib.rs | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 3209ac37..681b1be4 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -1,6 +1,9 @@ +use std::fs; use std::fs::File; +use std::io; use std::io::BufWriter; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; +use std::time::SystemTime; mod colour; mod image_loader; @@ -35,6 +38,15 @@ pub struct ImageConverterConfig { } pub fn convert_image(settings: &ImageConverterConfig) { + let source_modified_time = + get_modified_time(&settings.input_image).unwrap_or(SystemTime::now()); + let target_modified_time = + get_modified_time(&settings.output_file).unwrap_or(SystemTime::UNIX_EPOCH); + + if source_modified_time < target_modified_time { + return; + } + let image = Image::load_from_file(&settings.input_image); let tile_size = settings.tile_size.to_size(); @@ -82,3 +94,8 @@ fn optimiser_for_image(image: &Image, tile_size: usize) -> palette16::Palette16O palette_optimiser } + +fn get_modified_time(path: impl AsRef) -> io::Result { + let metadata = fs::metadata(path)?; + metadata.modified() +} From 74544374a5a11d0abe56acc48b869fae66f4b3cf Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 21:56:04 +0100 Subject: [PATCH 12/17] Add a test logo with a chicken and a whale --- agb/gfx/test_logo.png | Bin 0 -> 1585 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 agb/gfx/test_logo.png diff --git a/agb/gfx/test_logo.png b/agb/gfx/test_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..07b3017d537d30bfc7442fdf830ac50e91a7ac43 GIT binary patch literal 1585 zcmeAS@N?(olHy`uVBq!ia0y~yU~~YoKX9-C$wJ+|*+7c1ILO_JVcj{ImkbQ7uRUEH zLn`LHy?by~XsXPyhvnBBRbIGE5SThMvRR;0Nr_{VcgD2^jphQqi(YFS7c>#r)v_Q^ zTp%OiiiUQN5_^`($_(=fX?%7cFK>-`|G8&-_WHfoZra;fzOLVQw{HJ^_5~N1z2`F= z2x1Xfq1xb}%gB<&sSx1J&=|$UaYe{s!88V@t$fp}9^cI~|61YAyXDM3nZ<7Q?{A&Y z*S@vxbC}(FQFPTP24(+JIq^dH(dPLt=KbC0UE8;G&ELA5qqo)<->%)vgvBa^X5DS- z9<#T;Z`}0l^X;y!@z1yIOwE(x=RH4i%1U$C=yN6A{DK6Zh2DH<()_=m< zH@b{D^YI(@I^o-sW4qt~xA4T%AW``5m#=i`pJ_J6-e z^}CzllU3CFWjrU%sd#f<BrLblT`TsmVB<5zFvOs&-ZdQ%AQ4kk0efda^>Mom6H=MpI7nx zSNYUy(v!W1)hDTl@B3-w`RVpiZqG^D;q`u#Vs`(^p7i9#)$5a0*2n&~@htk)I(@Rr zf4l#Flb&=hxA&U#=kHy8&q@6D`zq(${@FSc==JRBDX%`WZkBJhtbh08!s~6HX0#kn z$jjCKUOpxC&fcB(!+;4-`@qzVOnbJjy%T@!X+qhCTWe}3rD?x0J$(1U{sY*PB_dF= zOG&X7s`=#pK0J1Td;NS1nX0=lQaU>)Mq7i!{>?+i@^ko8?N;wi@|6!~8q53C zKE8Nz(#>r~jYd|6Myql+rF{AI_PcXD|GQvNjA1J(pmB1y?nB^rV3ARB;HI$hW?j=p zqpX#lQ*TaIU7Y5>U`_3z^^SzHvjp}=i9$^P7GZ9Je@#X*l{vNZ~E5RzBb~ORW$za#g?X^ zr6oKF_TSg96)M;-efRRA>u;}3+f_%vxBnT~Z-!1_O+NS?SO+k8y85}Sb4q9e0IQ~f ARsaA1 literal 0 HcmV?d00001 From 62e0c346c503e26276f8589234bdc27263a1d8d9 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 22:52:23 +0100 Subject: [PATCH 13/17] End-to-end logo working --- agb-image-converter/src/lib.rs | 21 +- agb-image-converter/src/rust_generator.rs | 24 +- agb/Cargo.lock | 324 ++++++++++++++++++++++ agb/Cargo.toml | 3 + agb/build.rs | 10 + agb/gfx/test_logo.png | Bin 1585 -> 1402 bytes agb/src/display/mod.rs | 1 + agb/src/display/palette16.rs | 2 +- agb/src/display/tiled0.rs | 17 +- 9 files changed, 363 insertions(+), 39 deletions(-) diff --git a/agb-image-converter/src/lib.rs b/agb-image-converter/src/lib.rs index 681b1be4..399abb3c 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -1,9 +1,6 @@ -use std::fs; use std::fs::File; -use std::io; use std::io::BufWriter; -use std::path::{Path, PathBuf}; -use std::time::SystemTime; +use std::path::PathBuf; mod colour; mod image_loader; @@ -34,19 +31,9 @@ pub struct ImageConverterConfig { pub tile_size: TileSize, pub input_image: PathBuf, pub output_file: PathBuf, - pub output_name: String, } pub fn convert_image(settings: &ImageConverterConfig) { - let source_modified_time = - get_modified_time(&settings.input_image).unwrap_or(SystemTime::now()); - let target_modified_time = - get_modified_time(&settings.output_file).unwrap_or(SystemTime::UNIX_EPOCH); - - if source_modified_time < target_modified_time { - return; - } - let image = Image::load_from_file(&settings.input_image); let tile_size = settings.tile_size.to_size(); @@ -65,7 +52,6 @@ pub fn convert_image(settings: &ImageConverterConfig) { &optimisation_results, &image, settings.tile_size, - &settings.output_name, ) .expect("Failed to write data"); } @@ -94,8 +80,3 @@ fn optimiser_for_image(image: &Image, tile_size: usize) -> palette16::Palette16O palette_optimiser } - -fn get_modified_time(path: impl AsRef) -> io::Result { - let metadata = fs::metadata(path)?; - metadata.modified() -} diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index 1f241f35..bac750c7 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -10,31 +10,29 @@ pub(crate) fn generate_code( 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 + "pub const PALETTE_DATA: &'static [crate::display::palette16::Palette16] = &[\n", )?; for palette in &results.optimised_palettes { - write!(output, " agb::display::palette16::Palette16::new([")?; + write!(output, " crate::display::palette16::Palette16::new([")?; for colour in palette.clone() { write!(output, "0x{:08x}, ", colour.to_rgb15())?; } + for _ in palette.clone().into_iter().len()..16 { + write!(output, "0x00000000, ")?; + } + write!(output, "]),\n")?; } write!(output, "];\n\n")?; - write!( - output, - "pub const {}_TILE_DATA: &'static [u32] = &[\n", - tile_name - )?; + write!(output, "pub const TILE_DATA: &'static [u32] = &[\n",)?; let tile_size = tile_size.to_size(); @@ -58,7 +56,7 @@ pub(crate) fn generate_code( for j in inner_y * 8..inner_y * 8 + 8 { write!(output, "0x")?; - for i in (inner_x * 8..inner_x * 8 + 7).rev() { + for i in (inner_x * 8..inner_x * 8 + 8).rev() { let colour = image.colour(x * tile_size + i, y * tile_size + j); let colour_index = palette.colour_index(colour); @@ -76,11 +74,7 @@ pub(crate) fn generate_code( write!(output, "];\n\n")?; - write!( - output, - "pub const {}_PALETTE_ASSIGNMENT: &'static [u8] = &[", - tile_name - )?; + write!(output, "pub const PALETTE_ASSIGNMENT: &'static [u8] = &[")?; for (i, assignment) in results.assignments.iter().enumerate() { if i % 16 == 0 { diff --git a/agb/Cargo.lock b/agb/Cargo.lock index e90be4aa..d18eca59 100644 --- a/agb/Cargo.lock +++ b/agb/Cargo.lock @@ -2,15 +2,339 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler32" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" + [[package]] name = "agb" version = "0.1.1" dependencies = [ + "agb_image_converter", "bitflags", ] +[[package]] +name = "agb_image_converter" +version = "0.1.0" +dependencies = [ + "image", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "bytemuck" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" + +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + +[[package]] +name = "crc32fast" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +dependencies = [ + "cfg-if", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if", + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49" +dependencies = [ + "autocfg", + "cfg-if", + "lazy_static", +] + +[[package]] +name = "deflate" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73770f8e1fe7d64df17ca66ad28994a0a623ea497fa69486e14984e715c5d174" +dependencies = [ + "adler32", + "byteorder", +] + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "gif" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a668f699973d0f573d15749b7002a9ac9e1f9c6b220e7b165601334c173d8de" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "hermit-abi" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" +dependencies = [ + "libc", +] + +[[package]] +name = "image" +version = "0.23.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24ffcb7e7244a9bf19d35bf2883b9c080c4ced3c07a9895572178cdb8f13f6a1" +dependencies = [ + "bytemuck", + "byteorder", + "color_quant", + "gif", + "jpeg-decoder", + "num-iter", + "num-rational", + "num-traits", + "png", + "scoped_threadpool", + "tiff", +] + +[[package]] +name = "jpeg-decoder" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229d53d58899083193af11e15917b5640cd40b29ff475a1fe4ef725deb02d0f2" +dependencies = [ + "rayon", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" + +[[package]] +name = "memoffset" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435" +dependencies = [ + "adler32", +] + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2021c8337a54d21aca0d59a92577a029af9431cb59b909b03252b9c164fad59" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12ac428b1cb17fce6f731001d307d351ec70a6d202fc2e60f7d4c5e42d8f4f07" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "png" +version = "0.16.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6" +dependencies = [ + "bitflags", + "crc32fast", + "deflate", + "miniz_oxide 0.3.7", +] + +[[package]] +name = "rayon" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" +dependencies = [ + "autocfg", + "crossbeam-deque", + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-utils", + "lazy_static", + "num_cpus", +] + +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + +[[package]] +name = "scopeguard" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" + +[[package]] +name = "tiff" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a53f4706d65497df0c4349241deddf35f84cee19c87ed86ea8ca590f4464437" +dependencies = [ + "jpeg-decoder", + "miniz_oxide 0.4.4", + "weezl", +] + +[[package]] +name = "weezl" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b77fdfd5a253be4ab714e4ffa3c49caf146b4de743e97510c0656cf90f1e8e" diff --git a/agb/Cargo.toml b/agb/Cargo.toml index 571cca77..580036b6 100644 --- a/agb/Cargo.toml +++ b/agb/Cargo.toml @@ -18,3 +18,6 @@ lto = true [dependencies] bitflags = "1.0" + +[build-dependencies] +agb_image_converter = { path = "../agb-image-converter" } \ No newline at end of file diff --git a/agb/build.rs b/agb/build.rs index 47275134..b46c17aa 100644 --- a/agb/build.rs +++ b/agb/build.rs @@ -1,6 +1,9 @@ +use agb_image_converter::{convert_image, Colour, ImageConverterConfig, TileSize}; + fn main() { println!("cargo:rerun-if-changed=crt0.s"); println!("cargo:rerun-if-changed=interrupt_simple.s"); + println!("cargo:rerun-if-changed=gfx/test_logo.png"); let out_file_name = "crt0.o"; let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR environment variable must be specified"); @@ -19,4 +22,11 @@ fn main() { } println!("cargo:rustc-link-search={}", out_dir); + + convert_image(&ImageConverterConfig { + transparent_colour: Some(Colour::from_rgb(1, 1, 1)), + tile_size: TileSize::Tile8, + input_image: "gfx/test_logo.png".into(), + output_file: format!("{}/test_logo.rs", out_dir).into(), + }); } diff --git a/agb/gfx/test_logo.png b/agb/gfx/test_logo.png index 07b3017d537d30bfc7442fdf830ac50e91a7ac43..e0c3f5abf67009552486721c6b39879c9e63ff90 100644 GIT binary patch literal 1402 zcmeAS@N?(olHy`uVBq!ia0vp^AAooP2OE$yy8SQ}NHG=%xjQkeJ16s!fq~V;)5S5Q zV$R#U2fJiLnT~yY-^VDesN2LC`1ppKxR6so6GziC!80j#4aAR)6!Wl4hW2NQ%n$0)g)VztA{5ber=9vqY`d@3WXRUi}_yJtYBe){-UeXSU#~si_HW&!C*RlCpQ)C=!}~KXu2_HJ!W+-t zmhX>#68|Ac`9sj@v~1IF)e@I1s^*)xC1|K2A+wjgGTCzv%FN2N>oh(Yd}gcSQJ$}V z6EP!o@o5idZ&zGNZJWwO4q7N1hzKJg>A9`pa^{ZcFyT_;gHbCYu>Y+}lwe<6VaChUM%2{yKS%eg6IZMg0D(KXzm0fj3tc z-~VUzqv3J$-~Ye2Zd6?{dD|J2lKZQUw6VOiM{^F)X}48w^4UJp=D7xce0%{XW7PUzcbIKo|}K2gXbs<68gvdKrwu-`S14K Qz`~Tl)78&qol`;+0Ik-9#Q*>R literal 1585 zcmeAS@N?(olHy`uVBq!ia0y~yU~~YoKX9-C$wJ+|*+7c1ILO_JVcj{ImkbQ7uRUEH zLn`LHy?by~XsXPyhvnBBRbIGE5SThMvRR;0Nr_{VcgD2^jphQqi(YFS7c>#r)v_Q^ zTp%OiiiUQN5_^`($_(=fX?%7cFK>-`|G8&-_WHfoZra;fzOLVQw{HJ^_5~N1z2`F= z2x1Xfq1xb}%gB<&sSx1J&=|$UaYe{s!88V@t$fp}9^cI~|61YAyXDM3nZ<7Q?{A&Y z*S@vxbC}(FQFPTP24(+JIq^dH(dPLt=KbC0UE8;G&ELA5qqo)<->%)vgvBa^X5DS- z9<#T;Z`}0l^X;y!@z1yIOwE(x=RH4i%1U$C=yN6A{DK6Zh2DH<()_=m< zH@b{D^YI(@I^o-sW4qt~xA4T%AW``5m#=i`pJ_J6-e z^}CzllU3CFWjrU%sd#f<BrLblT`TsmVB<5zFvOs&-ZdQ%AQ4kk0efda^>Mom6H=MpI7nx zSNYUy(v!W1)hDTl@B3-w`RVpiZqG^D;q`u#Vs`(^p7i9#)$5a0*2n&~@htk)I(@Rr zf4l#Flb&=hxA&U#=kHy8&q@6D`zq(${@FSc==JRBDX%`WZkBJhtbh08!s~6HX0#kn z$jjCKUOpxC&fcB(!+;4-`@qzVOnbJjy%T@!X+qhCTWe}3rD?x0J$(1U{sY*PB_dF= zOG&X7s`=#pK0J1Td;NS1nX0=lQaU>)Mq7i!{>?+i@^ko8?N;wi@|6!~8q53C zKE8Nz(#>r~jYd|6Myql+rF{AI_PcXD|GQvNjA1J(pmB1y?nB^rV3ARB;HI$hW?j=p zqpX#lQ*TaIU7Y5>U`_3z^^SzHvjp}=i9$^P7GZ9Je@#X*l{vNZ~E5RzBb~ORW$za#g?X^ zr6oKF_TSg96)M;-efRRA>u;}3+f_%vxBnT~Z-!1_O+NS?SO+k8y85}Sb4q9e0IQ~f ARsaA1 diff --git a/agb/src/display/mod.rs b/agb/src/display/mod.rs index 614c8cdf..456b46c1 100644 --- a/agb/src/display/mod.rs +++ b/agb/src/display/mod.rs @@ -6,6 +6,7 @@ use video::Video; pub mod bitmap3; pub mod bitmap4; +pub mod example_logo; pub mod object; pub mod palette16; pub mod tiled0; diff --git a/agb/src/display/palette16.rs b/agb/src/display/palette16.rs index dd9ecf80..ea653a48 100644 --- a/agb/src/display/palette16.rs +++ b/agb/src/display/palette16.rs @@ -1,5 +1,5 @@ pub struct Palette16 { - colours: [u16; 16], + pub(crate) colours: [u16; 16], } impl Palette16 { diff --git a/agb/src/display/tiled0.rs b/agb/src/display/tiled0.rs index 100deaa0..e220eb44 100644 --- a/agb/src/display/tiled0.rs +++ b/agb/src/display/tiled0.rs @@ -3,8 +3,8 @@ use core::convert::TryInto; use crate::memory_mapped::MemoryMapped1DArray; use super::{ - object::ObjectControl, set_graphics_mode, set_graphics_settings, DisplayMode, GraphicsSettings, - DISPLAY_CONTROL, + object::ObjectControl, palette16, set_graphics_mode, set_graphics_settings, DisplayMode, + GraphicsSettings, DISPLAY_CONTROL, }; const PALETTE_BACKGROUND: MemoryMapped1DArray = @@ -12,7 +12,7 @@ const PALETTE_BACKGROUND: MemoryMapped1DArray = const PALETTE_SPRITE: MemoryMapped1DArray = unsafe { MemoryMapped1DArray::new(0x0500_0200) }; -const TILE_BACKGROUND: MemoryMapped1DArray = +const TILE_BACKGROUND: MemoryMapped1DArray = unsafe { MemoryMapped1DArray::new(0x06000000) }; const TILE_SPRITE: MemoryMapped1DArray = unsafe { MemoryMapped1DArray::new(0x06010000) }; @@ -144,6 +144,17 @@ impl Tiled0 { } } + pub fn set_background_palettes(&mut self, palettes: &[palette16::Palette16]) { + for (palette_index, entry) in palettes.iter().enumerate() { + for (colour_index, &colour) in entry.colours.iter().enumerate() { + self.set_background_palette_entry( + (palette_index * 16 + colour_index) as u8, + colour, + ); + } + } + } + pub fn set_sprite_tilemap(&mut self, tiles: &[u32]) { for (index, &tile) in tiles.iter().enumerate() { self.set_sprite_tilemap_entry(index as u32, tile) From 5234c7181ea1cc4491cfb0154b9a299b0300a273 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 22:56:47 +0100 Subject: [PATCH 14/17] Fix all the clippy lints --- agb-image-converter/src/bin/convert.rs | 3 +-- agb-image-converter/src/colour.rs | 2 +- agb-image-converter/src/lib.rs | 4 ++-- agb-image-converter/src/palette16.rs | 4 ++-- agb-image-converter/src/rust_generator.rs | 22 ++++++++++++---------- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/agb-image-converter/src/bin/convert.rs b/agb-image-converter/src/bin/convert.rs index 0796b7b4..82737b86 100644 --- a/agb-image-converter/src/bin/convert.rs +++ b/agb-image-converter/src/bin/convert.rs @@ -2,7 +2,7 @@ use std::env; use agb_image_converter::{convert_image, ImageConverterConfig, TileSize}; -fn main() -> () { +fn main() { let args: Vec<_> = env::args().collect(); let file_path = &args[1]; @@ -12,6 +12,5 @@ fn main() -> () { tile_size: TileSize::Tile8, input_image: file_path.into(), output_file: output_path.into(), - output_name: "HELLO".to_owned(), }); } diff --git a/agb-image-converter/src/colour.rs b/agb-image-converter/src/colour.rs index f5440e6f..31151d87 100644 --- a/agb-image-converter/src/colour.rs +++ b/agb-image-converter/src/colour.rs @@ -10,7 +10,7 @@ impl Colour { Colour { r, g, b } } - pub fn to_rgb15(&self) -> u16 { + 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 399abb3c..2d8b3450 100644 --- a/agb-image-converter/src/lib.rs +++ b/agb-image-converter/src/lib.rs @@ -18,8 +18,8 @@ pub enum TileSize { } impl TileSize { - fn to_size(&self) -> usize { - match &self { + fn to_size(self) -> usize { + match self { TileSize::Tile8 => 8, TileSize::Tile16 => 16, } diff --git a/agb-image-converter/src/palette16.rs b/agb-image-converter/src/palette16.rs index d705164a..0c7e3451 100644 --- a/agb-image-converter/src/palette16.rs +++ b/agb-image-converter/src/palette16.rs @@ -107,7 +107,7 @@ impl Palette16Optimiser { .cloned() .collect::>(); - while unsatisfied_palettes.len() > 0 { + while !unsatisfied_palettes.is_empty() { let palette = self.find_maximal_palette_for(&unsatisfied_palettes, transparent_colour); for test_palette in unsatisfied_palettes.clone() { @@ -130,8 +130,8 @@ impl Palette16Optimiser { } Palette16OptimisationResults { - assignments, optimised_palettes, + assignments, } } diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index bac750c7..5824ca78 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -11,9 +11,9 @@ pub(crate) fn generate_code( image: &Image, tile_size: TileSize, ) -> io::Result<()> { - write!( + writeln!( output, - "pub const PALETTE_DATA: &'static [crate::display::palette16::Palette16] = &[\n", + "pub const PALETTE_DATA: &'static [crate::display::palette16::Palette16] = &[", )?; for palette in &results.optimised_palettes { @@ -27,12 +27,13 @@ pub(crate) fn generate_code( write!(output, "0x00000000, ")?; } - write!(output, "]),\n")?; + writeln!(output, "]),")?; } - write!(output, "];\n\n")?; + writeln!(output, "];")?; + writeln!(output)?; - write!(output, "pub const TILE_DATA: &'static [u32] = &[\n",)?; + writeln!(output, "pub const TILE_DATA: &'static [u32] = &[",)?; let tile_size = tile_size.to_size(); @@ -43,9 +44,9 @@ pub(crate) fn generate_code( for x in 0..tiles_x { let palette_index = results.assignments[y * tiles_x + x]; let palette = &results.optimised_palettes[palette_index]; - write!( + writeln!( output, - " /* {}, {} (palette index {}) */\n", + " /* {}, {} (palette index {}) */", x, y, palette_index )?; @@ -68,11 +69,12 @@ pub(crate) fn generate_code( } } - write!(output, "\n")?; + writeln!(output)?; } } - write!(output, "];\n\n")?; + writeln!(output, "];")?; + writeln!(output)?; write!(output, "pub const PALETTE_ASSIGNMENT: &'static [u8] = &[")?; @@ -83,7 +85,7 @@ pub(crate) fn generate_code( write!(output, "{}, ", assignment)?; } - write!(output, "\n];\n")?; + writeln!(output, "\n];")?; Ok(()) } From 4b143f464ce1e3743bddd3a47c617230578f0c98 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 22:58:26 +0100 Subject: [PATCH 15/17] Also run clippy on the image converter --- .github/workflows/rust.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 4eddb22f..fadea272 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -46,6 +46,9 @@ jobs: - name: Run Clippy on agb working-directory: agb run: cargo clippy --verbose + - name: Run Clippy on agb image converter + working-directory: agb-image-converter + run: cargo clippy --verbose - name: Run Tests for agb working-directory: agb run: cargo test --verbose From ba2813f92722dbdbd802956877af34e6a952ab0a Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 22:58:53 +0100 Subject: [PATCH 16/17] Add example for the logo and ensure that it gets included in the library --- agb/examples/test_logo.rs | 41 +++++++++++++++++++++++++++++++++ agb/src/display/example_logo.rs | 1 + 2 files changed, 42 insertions(+) create mode 100644 agb/examples/test_logo.rs create mode 100644 agb/src/display/example_logo.rs diff --git a/agb/examples/test_logo.rs b/agb/examples/test_logo.rs new file mode 100644 index 00000000..97d2c5de --- /dev/null +++ b/agb/examples/test_logo.rs @@ -0,0 +1,41 @@ +#![no_std] +#![feature(start)] + +extern crate agb; + +use agb::display::{example_logo, tiled0}; + +#[start] +fn main(_argc: isize, _argv: *const *const u8) -> isize { + let mut gba = agb::Gba::new(); + let mut gfx = gba.display.video.tiled0(); + + gfx.set_background_palettes(example_logo::PALETTE_DATA); + gfx.set_background_tilemap(example_logo::TILE_DATA); + + gfx.background_0.enable(); + gfx.background_0 + .set_background_size(tiled0::BackgroundSize::S32x32); + gfx.background_0 + .set_colour_mode(tiled0::ColourMode::FourBitPerPixel); + + gfx.background_0.set_screen_base_block(20); + + let mut entries: [u16; 32 * 20] = [0; 32 * 20]; + for i in 0..(32 * 20) { + let x = i % 32; + let y = i / 32; + + if x >= 30 { + continue; + } + + let tile_id = (x + y * 30) as u16; + let palette_entry = example_logo::PALETTE_ASSIGNMENT[tile_id as usize] as u16; + entries[i] = tile_id | (palette_entry << 12); + } + + gfx.copy_to_map(20, &entries); + + loop {} +} diff --git a/agb/src/display/example_logo.rs b/agb/src/display/example_logo.rs new file mode 100644 index 00000000..8ae0d052 --- /dev/null +++ b/agb/src/display/example_logo.rs @@ -0,0 +1 @@ +include!(concat!(env!("OUT_DIR"), "/test_logo.rs")); From 8575f7d3d61364d856675300e180bdd02c83fcc9 Mon Sep 17 00:00:00 2001 From: Gwilym Kuiper Date: Tue, 20 Apr 2021 23:04:32 +0100 Subject: [PATCH 17/17] No need to put static --- agb-image-converter/src/rust_generator.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/agb-image-converter/src/rust_generator.rs b/agb-image-converter/src/rust_generator.rs index 5824ca78..d6f42469 100644 --- a/agb-image-converter/src/rust_generator.rs +++ b/agb-image-converter/src/rust_generator.rs @@ -13,7 +13,7 @@ pub(crate) fn generate_code( ) -> io::Result<()> { writeln!( output, - "pub const PALETTE_DATA: &'static [crate::display::palette16::Palette16] = &[", + "pub const PALETTE_DATA: &[crate::display::palette16::Palette16] = &[", )?; for palette in &results.optimised_palettes { @@ -33,7 +33,7 @@ pub(crate) fn generate_code( writeln!(output, "];")?; writeln!(output)?; - writeln!(output, "pub const TILE_DATA: &'static [u32] = &[",)?; + writeln!(output, "pub const TILE_DATA: &[u32] = &[",)?; let tile_size = tile_size.to_size(); @@ -76,7 +76,7 @@ pub(crate) fn generate_code( writeln!(output, "];")?; writeln!(output)?; - write!(output, "pub const PALETTE_ASSIGNMENT: &'static [u8] = &[")?; + write!(output, "pub const PALETTE_ASSIGNMENT: &[u8] = &[")?; for (i, assignment) in results.assignments.iter().enumerate() { if i % 16 == 0 {