Metatile converter
parent
3e5338670a
commit
93558cf3c8
|
@ -1,6 +1,6 @@
|
||||||
use std::{error::Error, collections::HashMap};
|
use std::{error::Error, collections::HashMap};
|
||||||
use image::GenericImageView;
|
use image::GenericImageView;
|
||||||
use crate::reskit::{tileset::image_to_tiles, utility::symbol_to_pascal, cli::settings::TileOrder};
|
use crate::reskit::{tileset::image_to_tiles, utility::{symbol_to_pascal, print_info}, cli::settings::TileOrder};
|
||||||
use super::{converter::{TiledTilemap, Layer, SystemPlane, TiledTileset}, dmapack::get_buckets};
|
use super::{converter::{TiledTilemap, Layer, SystemPlane, TiledTileset}, dmapack::get_buckets};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -114,8 +114,10 @@ pub fn get_tiles( tilemap: &TiledTilemap ) -> Result<(Vec<u8>, Vec<u8>), Box<dyn
|
||||||
* Format:
|
* Format:
|
||||||
* <<< HEADER >>>
|
* <<< HEADER >>>
|
||||||
* 2 bytes: The offset to the instances table
|
* 2 bytes: The offset to the instances table
|
||||||
* (n) 2 byte offsets: For the number of defined metatiles, 16-bit offsets into the file
|
* For each metatile:
|
||||||
* pointing to the metatile definition. Index into this table = the metatile ID.
|
* 2 bytes: Metatile width
|
||||||
|
* 2 bytes: Metatile height
|
||||||
|
* 2 bytes: Offset into `dmapack` buckets pointing directly to the metatile
|
||||||
*
|
*
|
||||||
* <<< DEFINITIONS >>>
|
* <<< DEFINITIONS >>>
|
||||||
* For each `dmapack` bucket:
|
* For each `dmapack` bucket:
|
||||||
|
@ -131,8 +133,10 @@ pub fn get_tiles( tilemap: &TiledTilemap ) -> Result<(Vec<u8>, Vec<u8>), Box<dyn
|
||||||
* 2 bytes: Y coordinate (world, divide by 8 to get tile coordinate).
|
* 2 bytes: Y coordinate (world, divide by 8 to get tile coordinate).
|
||||||
*/
|
*/
|
||||||
pub fn get_metatile_maps( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
pub fn get_metatile_maps( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Error>> {
|
||||||
|
print_info( &format!( "number of metatiles: {}", tilemap.metatiles.len() ) );
|
||||||
|
|
||||||
// Assemble header of offsets
|
// Assemble header of offsets
|
||||||
let header_offset = ( tilemap.metatiles.len() * 2 ) + 2;
|
let header_offset = ( tilemap.metatiles.len() * 6 ) + 2;
|
||||||
let mut header: Vec<u8> = vec![];
|
let mut header: Vec<u8> = vec![];
|
||||||
|
|
||||||
// Get offsets for each bucket
|
// Get offsets for each bucket
|
||||||
|
@ -140,33 +144,43 @@ pub fn get_metatile_maps( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Er
|
||||||
let mut bucket_offsets: HashMap<u16, usize> = HashMap::new();
|
let mut bucket_offsets: HashMap<u16, usize> = HashMap::new();
|
||||||
let mut total_offset = header_offset;
|
let mut total_offset = header_offset;
|
||||||
for ( bucket_id, bucket ) in &buckets {
|
for ( bucket_id, bucket ) in &buckets {
|
||||||
|
print_info( &format!( "bucket {} is of size {}", bucket_id, bucket.len() ) );
|
||||||
bucket_offsets.insert( *bucket_id, total_offset );
|
bucket_offsets.insert( *bucket_id, total_offset );
|
||||||
total_offset += bucket.len();
|
total_offset += bucket.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the offset for each metatile within the buckets
|
// Get the offset for each metatile within the buckets
|
||||||
|
let mut index = 0;
|
||||||
for metatile in &tilemap.metatiles {
|
for metatile in &tilemap.metatiles {
|
||||||
let bucket_offset = bucket_offsets.get( &metatile.pack.bucket ).ok_or( "internal error: no offset for dmapack bucket" )?;
|
let bucket_offset = bucket_offsets.get( &metatile.pack.bucket ).ok_or( "internal error: no offset for dmapack bucket" )?;
|
||||||
let cell_x = metatile.pack.slot[ 0 ];
|
let cell_x = metatile.pack.slot[ 0 ];
|
||||||
let cell_y = metatile.pack.slot[ 1 ];
|
let cell_y = metatile.pack.slot[ 1 ];
|
||||||
|
|
||||||
let metatile_byte_offset: u16 = *bucket_offset as u16 + ( ( ( cell_y * 64 ) + cell_x ) * 2 );
|
let metatile_byte_offset: u16 = *bucket_offset as u16 + ( ( ( cell_y * 64 ) + cell_x ) * 2 );
|
||||||
|
header.extend( metatile.width.to_be_bytes() );
|
||||||
|
header.extend( metatile.height.to_be_bytes() );
|
||||||
header.extend( metatile_byte_offset.to_be_bytes() );
|
header.extend( metatile_byte_offset.to_be_bytes() );
|
||||||
|
|
||||||
|
print_info( &format!( "metatile {}: width {} height {} file offset {}", index, metatile.width, metatile.height, metatile_byte_offset ) );
|
||||||
|
index += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assemble definitions
|
// Assemble definitions
|
||||||
let mut definitions: Vec<u8> = vec![];
|
let mut definitions: Vec<u8> = vec![];
|
||||||
|
let mut wasted_space: usize = 0;
|
||||||
for ( _, bucket ) in &buckets {
|
for ( _, bucket ) in &buckets {
|
||||||
for cell in bucket {
|
for cell in bucket {
|
||||||
if let Some( nametable_entry ) = cell {
|
if let Some( nametable_entry ) = cell {
|
||||||
definitions.extend( nametable_entry.to_be_bytes() );
|
definitions.extend( nametable_entry.to_be_bytes() );
|
||||||
} else {
|
} else {
|
||||||
definitions.extend( ( 0 as u16 ).to_be_bytes() );
|
definitions.extend( ( 0 as u16 ).to_be_bytes() );
|
||||||
|
wasted_space += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
print_info( &format!( "total dmapack unused space is {} bytes", wasted_space ) );
|
||||||
|
|
||||||
// Assemble instances
|
// Assemble instances
|
||||||
let mut instances: Vec<u8> = vec![];
|
let mut instances: Vec<u8> = vec![];
|
||||||
|
|
||||||
|
@ -179,13 +193,16 @@ pub fn get_metatile_maps( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Er
|
||||||
for tile_x in 0..tilemap.width {
|
for tile_x in 0..tilemap.width {
|
||||||
let item_at = tiles.get( ( tile_y * tilemap.width ) + tile_x ).ok_or( "internal error: tilemap does not correlate to width/height" )?;
|
let item_at = tiles.get( ( tile_y * tilemap.width ) + tile_x ).ok_or( "internal error: tilemap does not correlate to width/height" )?;
|
||||||
if *item_at != 0 {
|
if *item_at != 0 {
|
||||||
|
let metatile = tilemap.metatiles.iter().find( | metatile | metatile.id == *item_at ).ok_or( "invalid file: metatile definition not found" )?;
|
||||||
|
|
||||||
// What index-ID was that?
|
// What index-ID was that?
|
||||||
let index_id = tilemap.metatiles.iter().position( | metatile | metatile.id == *item_at ).ok_or( "invalid file: metatile id not found" )?;
|
let index_id = tilemap.metatiles.iter().position( | metatile | metatile.id == *item_at ).ok_or( "invalid file: metatile id not found" )?;
|
||||||
|
|
||||||
// Write the data to subdefinitions
|
// Write the data to subdefinitions
|
||||||
|
print_info( &format!( "plane B metatile instance: id {}, x {}, y {}", index_id, ( ( tile_x * 8 ) as u16 ), ( ( ( tile_y - ( metatile.height as usize - 1 ) ) * 8 ) as u16 ) ) );
|
||||||
subdefinitions.extend( ( index_id as u16 ).to_be_bytes() );
|
subdefinitions.extend( ( index_id as u16 ).to_be_bytes() );
|
||||||
subdefinitions.extend( ( ( tile_x * 8 ) as u16 ).to_be_bytes() );
|
subdefinitions.extend( ( ( tile_x * 8 ) as u16 ).to_be_bytes() );
|
||||||
subdefinitions.extend( ( ( tile_y * 8 ) as u16 ).to_be_bytes() );
|
subdefinitions.extend( ( ( ( tile_y - ( metatile.height as usize - 1 ) ) * 8 ) as u16 ).to_be_bytes() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,13 +222,16 @@ pub fn get_metatile_maps( tilemap: &TiledTilemap ) -> Result<Vec<u8>, Box<dyn Er
|
||||||
for tile_x in 0..tilemap.width {
|
for tile_x in 0..tilemap.width {
|
||||||
let item_at = tiles.get( ( tile_y * tilemap.width ) + tile_x ).ok_or( "internal error: tilemap does not correlate to width/height" )?;
|
let item_at = tiles.get( ( tile_y * tilemap.width ) + tile_x ).ok_or( "internal error: tilemap does not correlate to width/height" )?;
|
||||||
if *item_at != 0 {
|
if *item_at != 0 {
|
||||||
|
let metatile = tilemap.metatiles.iter().find( | metatile | metatile.id == *item_at ).ok_or( "invalid file: metatile definition not found" )?;
|
||||||
|
|
||||||
// What index-ID was that?
|
// What index-ID was that?
|
||||||
let index_id = tilemap.metatiles.iter().position( | metatile | metatile.id == *item_at ).ok_or( "invalid file: metatile id not found" )?;
|
let index_id = tilemap.metatiles.iter().position( | metatile | metatile.id == *item_at ).ok_or( "invalid file: metatile id not found" )?;
|
||||||
|
|
||||||
// Write the data to subdefinitions
|
// Write the data to subdefinitions
|
||||||
|
print_info( &format!( "plane A metatile instance: id {}, x {}, y {}", index_id, ( ( tile_x * 8 ) as u16 ), ( ( ( tile_y - ( metatile.height as usize - 1 ) ) * 8 ) as u16 ) ) );
|
||||||
subdefinitions.extend( ( index_id as u16 ).to_be_bytes() );
|
subdefinitions.extend( ( index_id as u16 ).to_be_bytes() );
|
||||||
subdefinitions.extend( ( ( tile_x * 8 ) as u16 ).to_be_bytes() );
|
subdefinitions.extend( ( ( tile_x * 8 ) as u16 ).to_be_bytes() );
|
||||||
subdefinitions.extend( ( ( tile_y * 8 ) as u16 ).to_be_bytes() );
|
subdefinitions.extend( ( ( ( tile_y - ( metatile.height as usize - 1 ) ) * 8 ) as u16 ).to_be_bytes() );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue