Generation of palette/nametables simplified and refactored for palettes
parent
ff08ee4e46
commit
5d8f7294ef
|
@ -1,27 +1,44 @@
|
||||||
use std::{error::Error, convert::TryInto};
|
use std::{error::Error, convert::TryInto};
|
||||||
|
use image::GenericImageView;
|
||||||
use crate::reskit::tileset::image_to_tiles;
|
use crate::reskit::tileset::image_to_tiles;
|
||||||
use super::converter::{TiledTilemap, Layer, SystemPlane};
|
use super::converter::{TiledTilemap, Layer, SystemPlane};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Output the .bin file (using `tileset` tool to build it) containing each of the tiles
|
* Output the .bin and .pal file (using `tileset` tool to build it) containing each of the tiles
|
||||||
* in the Tiled Editor tileset.
|
* and palettes in the Tiled Editor tileset.
|
||||||
*/
|
*/
|
||||||
pub fn get_tiles( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
pub fn get_tiles( tilemap: &TiledTilemap ) -> Result<(Vec<u8>, Vec<u8>), Box<dyn Error>> {
|
||||||
let mut palette: [u16; 16] = [ 0; 16 ];
|
let mut system_pals: [[u16; 16]; 4] = [
|
||||||
|
[ 0; 16 ],
|
||||||
|
[ 0; 16 ],
|
||||||
|
[ 0; 16 ],
|
||||||
|
[ 0; 16 ]
|
||||||
|
];
|
||||||
let mut all_tiles: Vec<u8> = Vec::new();
|
let mut all_tiles: Vec<u8> = Vec::new();
|
||||||
|
|
||||||
for tile_y in 0..tilemap.height {
|
let tiles_height = tilemap.tileset.image.height() / 8; // --system md
|
||||||
for tile_x in 0..tilemap.width {
|
let tiles_width = tilemap.tileset.image.width() / 8; // --system md
|
||||||
let tile = tilemap.tileset.image.clone().crop(
|
|
||||||
tile_x as u32,
|
for tile_y in 0..tiles_height {
|
||||||
tile_y as u32,
|
for tile_x in 0..tiles_width {
|
||||||
8, // --system md
|
let tile = tilemap.tileset.image.clone().crop( tile_x * 8, tile_y * 8, 8, 8 );
|
||||||
8 // --system md
|
|
||||||
);
|
// Fake palette (see below)
|
||||||
|
let mut fake: [u16; 16] = [ 0; 16 ];
|
||||||
|
|
||||||
let tile_bin = image_to_tiles(
|
let tile_bin = image_to_tiles(
|
||||||
&tile,
|
&tile,
|
||||||
&mut palette,
|
{
|
||||||
|
// Determine if palette is used here or it is a dummy palette
|
||||||
|
let selected_pal = tilemap.tileset.palettes[ ( ( tile_y * tiles_width ) + tile_x ) as usize ];
|
||||||
|
if let Some( selected_pal ) = selected_pal {
|
||||||
|
&mut system_pals[ selected_pal as usize ]
|
||||||
|
} else {
|
||||||
|
// Fake-a-palette
|
||||||
|
// You will get an error in get_tilemap if you try to use this palette-less tile
|
||||||
|
&mut fake
|
||||||
|
}
|
||||||
|
},
|
||||||
"tile"
|
"tile"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -29,19 +46,18 @@ pub fn get_tiles( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define result and write palette to top of result
|
// Define result and write palettes
|
||||||
let mut result: Vec<u8> = Vec::new();
|
let mut palettes: Vec<u8> = Vec::new();
|
||||||
for i in 0..palette.len() {
|
for pal in 0..system_pals.len() {
|
||||||
let bytes = palette[ i ].to_be_bytes();
|
for i in 0..system_pals[ pal ].len() {
|
||||||
|
let bytes = system_pals[ pal ][ i ].to_be_bytes();
|
||||||
for i in 0..2 {
|
for i in 0..2 {
|
||||||
result.push( bytes[ i ] );
|
palettes.push( bytes[ i ] );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extend all tiles onto result
|
Ok( ( all_tiles, palettes ) )
|
||||||
result.extend( all_tiles );
|
|
||||||
|
|
||||||
Ok( result )
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,11 +68,8 @@ pub fn get_tilemap( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>>
|
||||||
let layer_b: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneB, tiles: _ } ) );
|
let layer_b: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneB, tiles: _ } ) );
|
||||||
let layer_a: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneA, tiles: _ } ) );
|
let layer_a: Option<&Layer> = tilemap.layers.iter().find( | layer | matches!( layer, Layer::Tile { system_plane: SystemPlane::MdPlaneA, tiles: _ } ) );
|
||||||
|
|
||||||
let md_height_per_tile = 1; // --system md
|
|
||||||
let md_width_per_tile = 1; // --system md
|
|
||||||
|
|
||||||
// Each entry in a `--system md` tilemap is 16 bits
|
// Each entry in a `--system md` tilemap is 16 bits
|
||||||
let mut nametable: Vec<u16> = vec![ 0; ( tilemap.width * md_width_per_tile ) * ( tilemap.height * md_height_per_tile ) ];
|
let mut nametable: Vec<u16> = vec![ 0; tilemap.width * tilemap.height ];
|
||||||
|
|
||||||
if let Some( layer_b ) = layer_b {
|
if let Some( layer_b ) = layer_b {
|
||||||
let layer_b = match layer_b {
|
let layer_b = match layer_b {
|
||||||
|
@ -69,18 +82,15 @@ pub fn get_tilemap( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>>
|
||||||
let target_tile: u32 = *layer_b.get( ( y * tilemap.width ) + x ).ok_or( "internal error: invalid data in tilemap" )?;
|
let target_tile: u32 = *layer_b.get( ( y * tilemap.width ) + x ).ok_or( "internal error: invalid data in tilemap" )?;
|
||||||
let target_tile: u16 = target_tile.try_into()?;
|
let target_tile: u16 = target_tile.try_into()?;
|
||||||
if target_tile > 0 {
|
if target_tile > 0 {
|
||||||
let wide_tile_size = md_height_per_tile as u16 * md_width_per_tile as u16;
|
let source_tile = target_tile - 1;
|
||||||
let source_tile = ( target_tile - 1 ) * wide_tile_size;
|
|
||||||
let x = x * md_width_per_tile;
|
|
||||||
let y = y * md_height_per_tile;
|
|
||||||
|
|
||||||
// From the starting point of x, y "stamp" the target tile's indices
|
// From the starting point of x, y "stamp" the target tile's indices
|
||||||
let mut revolving_counter = 0;
|
let nametable_entry = source_tile;
|
||||||
for y_stamp in y..( y + md_height_per_tile ) {
|
let selected_pal = tilemap.tileset.palettes[ source_tile as usize ];
|
||||||
for x_stamp in x..( x + md_width_per_tile ) {
|
if let Some( selected_pal ) = selected_pal {
|
||||||
nametable[ ( y_stamp * ( tilemap.width * md_width_per_tile ) ) + x_stamp ] = source_tile + revolving_counter;
|
nametable[ ( y * tilemap.width ) + x ] = ( ( selected_pal as u16 ) << 13 ) | nametable_entry;
|
||||||
revolving_counter = ( revolving_counter + 1 ) % wide_tile_size;
|
} else {
|
||||||
}
|
return Err( format!( "invalid setting: tile {} in tileset has no defined palette", source_tile ) )?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,18 +110,15 @@ pub fn get_tilemap( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>>
|
||||||
let target_tile: u32 = *layer_a.get( ( y * tilemap.width ) + x ).ok_or( "internal error: invalid data in tilemap" )?;
|
let target_tile: u32 = *layer_a.get( ( y * tilemap.width ) + x ).ok_or( "internal error: invalid data in tilemap" )?;
|
||||||
let target_tile: u16 = target_tile.try_into()?;
|
let target_tile: u16 = target_tile.try_into()?;
|
||||||
if target_tile > 0 {
|
if target_tile > 0 {
|
||||||
let wide_tile_size = md_height_per_tile as u16 * md_width_per_tile as u16;
|
let source_tile = target_tile - 1;
|
||||||
let source_tile = ( target_tile - 1 ) * wide_tile_size;
|
|
||||||
let x = x * md_width_per_tile;
|
|
||||||
let y = y * md_height_per_tile;
|
|
||||||
|
|
||||||
// From the starting point of x, y "stamp" the target tile's indices
|
// From the starting point of x, y "stamp" the target tile's indices
|
||||||
let mut revolving_counter = 0;
|
let nametable_entry = source_tile;
|
||||||
for y_stamp in y..( y + md_height_per_tile ) {
|
let selected_pal = tilemap.tileset.palettes[ source_tile as usize ];
|
||||||
for x_stamp in x..( x + md_width_per_tile ) {
|
if let Some( selected_pal ) = selected_pal {
|
||||||
nametable[ ( y_stamp * ( tilemap.width * md_width_per_tile ) ) + x_stamp ] = source_tile + revolving_counter;
|
nametable[ ( y * tilemap.width ) + x ] = ( ( selected_pal as u16 ) << 13 ) | nametable_entry;
|
||||||
revolving_counter = ( revolving_counter + 1 ) % wide_tile_size;
|
} else {
|
||||||
}
|
return Err( format!( "invalid setting: tile {} in tileset has no defined palette", source_tile ) )?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue