Integrate all the progress into master #6

Merged
jaby merged 595 commits from ToolBox into main 2025-01-01 13:17:44 +00:00
7 changed files with 132 additions and 11 deletions
Showing only changes of commit 00719f910c - Show all commits

View File

@ -93,7 +93,7 @@ fn encode<T: PSXImageConverter>(header_conv: &mut dyn HeaderEncoder, image: T, c
}
};
header_conv.encode_settings(width, height, pal_width, pal_height)?;
header_conv.encode_settings(color_depth, width, height, pal_width, pal_height)?;
header_conv.write_header(output)?;
header_conv.write_clut_header(output)?;

View File

@ -1,9 +1,8 @@
use super::super::types::{HeaderEncoder, set_member_value};
use super::super::{args::ColorType, types::{HeaderEncoder, set_member_value}};
use std::io::Write;
use tool_helper::{bits::BitRange, raw::RawConversion, Error};
#[repr(packed(1))]
#[allow(dead_code)]
pub struct Header {
value: u32
}
@ -22,7 +21,7 @@ impl Default for Header {
}
impl HeaderEncoder for Header {
fn encode_settings(&mut self, tex_width: u16, tex_height: u16, clut_width: u16, clut_height: u16) -> Result<(), Error> {
fn encode_settings(&mut self, _color_type: ColorType, tex_width: u16, tex_height: u16, clut_width: u16, clut_height: u16) -> Result<(), Error> {
if tex_width & 1 == 1 || tex_height & 1 == 1 {
Err(Error::from_text(format!("Image size (width: {}, height: {}) needs to be even", tex_width, tex_height)))
}

View File

@ -0,0 +1,16 @@
pub mod types;
use super::args::ColorType;
use std::io::Write;
use types::Header;
use tool_helper::{Error, Input};
pub type Arguments = super::args::Arguments;
pub fn convert(args: Arguments, input: Input, output: &mut dyn Write) -> Result<(), Error> {
let mut header_conv = Header::default();
match args.color_depth {
ColorType::Full16 => super::convert_full16(&mut header_conv, input, output),
_ => super::convert_palette_based(&mut header_conv, input, output, args.color_depth, args.clut_align, args.semi_transparent, args.transparent_palette),
}
}

View File

@ -0,0 +1,90 @@
use super::super::{args::ColorType, types::HeaderEncoder};
use std::io::Write;
use tool_helper::{bits::{Bit, BitRange}, raw::RawConversion, Error};
pub struct Header {
flag: u32,
clut_block: DataBlock,
pixel_block: DataBlock,
}
impl Header {
const ID_VALUE: u32 = BitRange::from_to(0, 7).as_value(0x10) as u32;
const ID_VERSION_VALUE:u32 = BitRange::from_to(8, 15).as_value(0x0) as u32;
const FLAG_PMODE_BIT_RANGE: BitRange = BitRange::from_to(0, 2);
const FLAG_CF_BIT: Bit = Bit::at(3);
const ID:u32 = Self::ID_VALUE | Self::ID_VERSION_VALUE;
}
impl Default for Header {
fn default() -> Self {
Header{flag: 0, clut_block: DataBlock::default(), pixel_block: DataBlock::default()}
}
}
impl HeaderEncoder for Header {
fn encode_settings(&mut self, color_type: ColorType, tex_width: u16, tex_height: u16, clut_width: u16, clut_height: u16) -> Result<(), Error> {
self.flag = match color_type {
ColorType::Clut4 => (Self::FLAG_PMODE_BIT_RANGE.as_value(0x0) | Self::FLAG_CF_BIT.as_value(true)) as u32,
ColorType::Clut8 => (Self::FLAG_PMODE_BIT_RANGE.as_value(0x1) | Self::FLAG_CF_BIT.as_value(true)) as u32,
ColorType::Full16 => (Self::FLAG_PMODE_BIT_RANGE.as_value(0x2) | Self::FLAG_CF_BIT.as_value(true)) as u32,
};
// TODO: Support tex & clut x/y
self.clut_block = DataBlock::new(0, 0, clut_width, clut_height);
self.pixel_block = DataBlock::new(0, 0, tex_width, tex_height);
Ok(())
}
fn write_header(&self, output: &mut dyn Write) -> Result<usize, Error> {
let bytes = output.write(&Header::ID.to_le_bytes())?;
Ok(bytes + output.write(&self.flag.to_le_bytes())?)
}
fn write_clut_header(&self, output: &mut dyn Write) -> Result<usize, Error> {
Ok(output.write(&self.clut_block.convert_to_raw())?)
}
fn write_pixel_header(&self, output: &mut dyn Write) -> Result<usize, Error> {
Ok(output.write(&self.pixel_block.convert_to_raw())?)
}
}
pub struct DataBlock {
bytes: u32,
x: u16,
y: u16,
w: u16,
h: u16,
}
impl DataBlock {
const RAW_HEADER_SIZE: usize = (4*std::mem::size_of::<u16>()) + std::mem::size_of::<u32>();
pub fn new(x: u16, y: u16, w: u16, h: u16) -> DataBlock {
let bytes = ((w as usize*h as usize) + Self::RAW_HEADER_SIZE) as u32;
DataBlock{bytes, x, y, w, h}
}
}
impl std::default::Default for DataBlock {
fn default() -> Self {
DataBlock{bytes: 0, x: 0, y: 0, w: 0, h: 0}
}
}
impl RawConversion<{Self::RAW_HEADER_SIZE}> for DataBlock {
fn convert_to_raw(&self) -> [u8; Self::RAW_HEADER_SIZE] {
let mut raw = [0u8; Self::RAW_HEADER_SIZE];
raw[ 0..4].copy_from_slice(&self.bytes.to_le_bytes());
raw[ 4..6].copy_from_slice(&self.y.to_le_bytes());
raw[ 6..8].copy_from_slice(&self.x.to_le_bytes());
raw[ 8..10].copy_from_slice(&self.h.to_le_bytes());
raw[10..12].copy_from_slice(&self.w.to_le_bytes());
raw
}
}

View File

@ -25,6 +25,8 @@ macro_rules! make_member_getter_setter {
pub(crate) use set_member_value;
use super::args;
#[repr(packed(1))]
#[allow(dead_code)]
pub struct Color {
@ -122,10 +124,10 @@ impl RawConversion<2> for Color {
}
pub trait HeaderEncoder {
fn encode_settings(&mut self, tex_width: u16, tex_height: u16, clut_width: u16, clut_height: u16) -> Result<(), Error>;
fn write_header(&self, output: &mut dyn Write) -> Result<usize, Error>;
fn write_clut_header(&self, output: &mut dyn Write) -> Result<usize, Error>;
fn write_pixel_header(&self, output: &mut dyn Write) -> Result<usize, Error>;
fn encode_settings(&mut self, color_type: args::ColorType, tex_width: u16, tex_height: u16, clut_width: u16, clut_height: u16) -> Result<(), Error>;
fn write_header(&self, output: &mut dyn Write) -> Result<usize, Error>;
fn write_clut_header(&self, output: &mut dyn Write) -> Result<usize, Error>;
fn write_pixel_header(&self, output: &mut dyn Write) -> Result<usize, Error>;
}
pub trait PSXImageConverter: std::iter::Iterator<Item = Color> {

View File

@ -1,6 +1,6 @@
[package]
name = "tool_helper"
version = "0.9.7"
version = "0.9.8"
edition = "2021"
[profile.release]

View File

@ -16,8 +16,12 @@ impl BitRange {
(1 << self.length) - 1
}
pub const fn as_value(&self, value: usize) -> usize {
(value & self.get_mask()) << self.start
}
pub const fn or_value(&self, dst_value: usize, value: usize) -> usize {
dst_value | ((value & self.get_mask()) << self.start)
dst_value | self.as_value(value)
}
}
@ -30,9 +34,19 @@ impl Bit {
Bit{pos}
}
pub const fn as_value(&self, is_set: bool) -> usize {
if is_set {
1 << self.pos
}
else {
0
}
}
pub const fn or_value(&self, dst_value: usize, is_set: bool) -> usize {
if is_set {
dst_value | (1 << self.pos)
dst_value | self.as_value(is_set)
}
else {