diff --git a/samples_cbm/petscii_tile/Makefile b/samples_cbm/petscii_tile/Makefile index 9e2d0ba..b8e7316 100644 --- a/samples_cbm/petscii_tile/Makefile +++ b/samples_cbm/petscii_tile/Makefile @@ -4,10 +4,10 @@ NAME = p128 project.av: p128-ref-template.png $(ALOEVERA) create project project.av $(ALOEVERA) -p project.av palette import cbm_palette p128-ref-template.png -# $(ALOEVERA) -p project.gx16 imageset import text_set_1 8 8 pixel-font.png -# $(ALOEVERA) -p project.gx16 imageset format text_set_1 palette_1 1 -# $(ALOEVERA) -p project.gx16 asm ./output/ all - $(ALOEVERA) -p project.av asm -f ca65 ./output/ all + $(ALOEVERA) -p project.av imageset import test_set_1 4 8 p128-ref-template.png + $(ALOEVERA) -p project.av imageset format -v test_set_1 cbm_palette 8 +# $(ALOEVERA) -p project.av asm ./output/ all +# $(ALOEVERA) -p project.av asm -f ca65 ./output/ all generate_resources: project.av diff --git a/samples_cbm/petscii_tile/p128-ref-template.aseprite b/samples_cbm/petscii_tile/p128-ref-template.aseprite new file mode 100644 index 0000000..db522bd Binary files /dev/null and b/samples_cbm/petscii_tile/p128-ref-template.aseprite differ diff --git a/samples_cbm/petscii_tile/p128-ref-template.png b/samples_cbm/petscii_tile/p128-ref-template.png index 3e4707e..4bbe68a 100644 Binary files a/samples_cbm/petscii_tile/p128-ref-template.png and b/samples_cbm/petscii_tile/p128-ref-template.png differ diff --git a/src/bin/aloevera.yml b/src/bin/aloevera.yml index 3900a2b..b097602 100644 --- a/src/bin/aloevera.yml +++ b/src/bin/aloevera.yml @@ -114,6 +114,11 @@ subcommands: - pixel_depth: help: Target Pixel Depth (8, 4, 2 or 1) index: 3 + - vic2_mc_bmp: + help: Constrain image for VIC2 Multicolor bitmap mode cells (experimental) + long: vic_mc_bmp + short: v + takes_value: false - tilemap: about: Import and manipulate tilemaps subcommands: diff --git a/src/cmd/imageset/command.rs b/src/cmd/imageset/command.rs index 2775750..de19ab2 100644 --- a/src/cmd/imageset/command.rs +++ b/src/cmd/imageset/command.rs @@ -42,7 +42,6 @@ pub struct ImageSetImportArgs { pub fn imageset_import(g_args: &GlobalArgs, args: &ImageSetImportArgs) -> Result<(), Error> { let png_bytes = common::read_file_bin(&args.input_file)?; let config = VeraImageSetLoadConfig::default(); - println!("{}, {}", args.frame_width, args.frame_height); let mut imageset = VeraImageSet::new(&args.id, args.frame_width, args.frame_height); imageset.load_from_png(png_bytes, &config)?; insert_imageset(g_args.project_file.clone(), &args.id, &imageset)?; @@ -55,6 +54,7 @@ pub struct ImageSetFormatArgs { pub imageset_id: String, pub palette_id: String, pub pixel_depth: VeraPixelDepth, + pub vic2_mc_bmp: bool, } /// Imageset format @@ -74,7 +74,21 @@ pub fn imageset_format(g_args: &GlobalArgs, args: &ImageSetFormatArgs) -> Result return Err(ErrorKind::ArgumentError(msg).into()); } }; - imageset.format_indices(&palette, args.pixel_depth)?; + let mut pixel_depth = args.pixel_depth; + if args.vic2_mc_bmp { + imageset.constrain_vic_bmp_color_cells = true; + pixel_depth = VeraPixelDepth::BPP4; + if imageset.frame_width != 4 || imageset.frame_height != 8 { + let msg = format!( + "Imagesets formatted for Vic2 Multicolour Tiled mode MUST have 4x8 tile dimensions" + ); + return Err(ErrorKind::ArgumentError(msg).into()); + } + if palette.entries.len() != 16 { + let msg = format!("Palettes used to format Vic2 Multicolour Tiled mode Imagesets MUST have only 16 colours"); + } + } + imageset.format_indices(&palette, pixel_depth)?; insert_imageset(g_args.project_file.clone(), &args.imageset_id, &imageset)?; Ok(()) diff --git a/src/cmd/imageset/parse.rs b/src/cmd/imageset/parse.rs index efef382..118a06b 100644 --- a/src/cmd/imageset/parse.rs +++ b/src/cmd/imageset/parse.rs @@ -63,11 +63,13 @@ pub fn parse_imageset_format_args( return Err(ErrorKind::ArgumentError(msg).into()); } }; + let vic2_mc_bmp = args.is_present("vic2_mc_bmp"); Ok(ImageSetFormatArgs { imageset_id: imageset_id.into(), palette_id: palette_id.into(), pixel_depth, + vic2_mc_bmp, }) } diff --git a/vera/src/error.rs b/vera/src/error.rs index 8e3da1f..f784040 100644 --- a/vera/src/error.rs +++ b/vera/src/error.rs @@ -142,6 +142,12 @@ pub enum ErrorKind { /// Bitmap doesn't have an Imageset #[fail(display = "Bitmap {} doesn't reference an imageset", _0)] BitmapNoImageSet(String), + /// VIC Color Bitmap more error constraint + #[fail( + display = "VIC Multicolor BMP formatting, each cell must only contain palette index 0 + 3 distinct colors at index {}", + _0 + )] + VICColorBMP(usize), /// Other #[fail(display = "Generic error: {}", _0)] GenericError(String), diff --git a/vera/src/imageset.rs b/vera/src/imageset.rs index a68bcc4..b304d3a 100644 --- a/vera/src/imageset.rs +++ b/vera/src/imageset.rs @@ -312,6 +312,8 @@ pub struct VeraImageSet { pub frame_data: Vec, /// whether frame data has been culled pub culled: bool, + /// whether image tile areas should be constrained to vic2 mc bitmap mode + pub constrain_vic_bmp_color_cells: bool, /// whether this imageset has been formatted pub formatted: bool, } @@ -328,6 +330,7 @@ impl VeraImageSet { frames_per_col: 0, frame_data: vec![], culled: false, + constrain_vic_bmp_color_cells: false, formatted: false, }; retval.reset(); @@ -448,7 +451,7 @@ impl VeraImageSet { "Formatting imageset {} to palette at depth of {}", self.id, depth ); - for frame in self.frame_data.iter_mut() { + for (frame_index, frame) in self.frame_data.iter_mut().enumerate() { if depth == VeraPixelDepth::BPP1 { for mut p in frame.data.iter_mut() { p.is_1bpp = true; @@ -520,12 +523,38 @@ impl VeraImageSet { } } } + + if self.constrain_vic_bmp_color_cells { + // always include index 0 (black or whatever background color is set to) + let mut used_palette_entries = vec![0]; + for p in frame.data.iter_mut() { + let index = match p.pal_index { + Some(i) => i, + None => return Err(ErrorKind::PaletteIndexMissing(0, 0, 0).into()), + }; + if !used_palette_entries.contains(&index) { + used_palette_entries.push(index); + } + } + if used_palette_entries.len() > 4 { + return Err(ErrorKind::VICColorBMP(frame_index).into()); + } + } } self.depth = Some(depth); self.store_flip_hashes(); self.formatted = true; Ok(()) } + + pub fn assemble_vic2_bmp( + &self, + tiles_per_copy_x: u8, + tiles_per_copy_y: u8, + ) -> Result { + let retval = AssembledPrimitive::new(self.id()); + Ok(retval) + } } impl fmt::Display for VeraImageSet { @@ -562,6 +591,9 @@ impl Assemblable for VeraImageSet { if !self.formatted { return Err(ErrorKind::ImageSetNotFormatted(format!("{}", self.id)).into()); } + if self.constrain_vic_bmp_color_cells { + return self.assemble_vic2_bmp(3, 3); + } let mut retval = AssembledPrimitive::new(self.id()); retval.add_meta(format!("{} - size is {}", self.id, self.size())); let depth = match self.depth { diff --git a/vera/src/palette.rs b/vera/src/palette.rs index 064feb3..2c6a462 100644 --- a/vera/src/palette.rs +++ b/vera/src/palette.rs @@ -78,7 +78,7 @@ pub struct VeraPalette { /// Id pub id: String, /// Palette values - entries: Vec, + pub entries: Vec, } impl Default for VeraPalette { diff --git a/vera/tests/data/imageset/indexed-vic2-multicolor-tiled.png b/vera/tests/data/imageset/indexed-vic2-multicolor-tiled.png new file mode 100644 index 0000000..4bbe68a Binary files /dev/null and b/vera/tests/data/imageset/indexed-vic2-multicolor-tiled.png differ diff --git a/vera/tests/imageset.rs b/vera/tests/imageset.rs index 2416be7..445f6c7 100644 --- a/vera/tests/imageset.rs +++ b/vera/tests/imageset.rs @@ -384,3 +384,37 @@ fn image_flip() -> Result<(), Error> { Ok(()) } + +#[test] +fn imageset_vic2_multicolor_bmp_tiled() -> Result<(), Error> { + init_test_logger(); + let test_png = include_bytes!("data/imageset/indexed-vic2-multicolor-tiled.png"); + let mut pal_config = VeraPaletteLoadConfig::default(); + pal_config.sort = false; + let palette = VeraPalette::derive_from_png("pal", test_png.to_vec(), &pal_config)?; + + println!("{}", palette); + assert_eq!(palette.len(), 16); + assert_eq!(palette.index_of_rgb(0x0, 0x0, 0x0), Some(0)); + assert_eq!(palette.index_of_rgb(0xF0, 0xF0, 0xF0), Some(1)); + assert_eq!(palette.index_of_rgb(0x90, 0x90, 0x90), Some(15)); + + let mut set = VeraImageSet::new("vic_set_1", 4, 8); + let mut config = VeraImageSetLoadConfig::default(); + config.cull_duplicates = true; + set.load_from_png(test_png.to_vec(), &config)?; + set.constrain_vic_bmp_color_cells = true; + set.format_indices(&palette, VeraPixelDepth::BPP4)?; + println!("{}", set); + + /*assert_eq!(set.size(), 256); + assert!(set.frame_at(1).is_err());*/ + + let frame = set.frame_at(1)?; + println!("{}", frame); + assert!(frame.pixel_at_coord(0, 8).is_err()); + assert!(frame.pixel_at_coord(4, 0).is_err()); + assert_eq!(frame.pixel_at_coord(1, 1)?.pal_index, Some(2)); + + Ok(()) +}