Maraiah/src/marathon/shp.rs

375 lines
8.2 KiB
Rust
Raw Normal View History

2019-02-09 11:02:23 -08:00
//! Marathon Shapes format handling.
2019-02-10 20:29:12 -08:00
use crate::durandal::{bin::*, err::*, fx32::*, image::*, text::*};
2019-02-09 11:02:23 -08:00
use bitflags::bitflags;
2019-02-10 20:29:12 -08:00
fn color(b: &[u8]) -> ResultS<(usize, ColorShp)>
2019-02-09 11:02:23 -08:00
{
2019-02-10 20:29:12 -08:00
let l = c_byte(b, 0)?;
let i = c_byte(b, 1)? as usize;
let r = c_u16b(b, 2)?;
let g = c_u16b(b, 4)?;
let b = c_u16b(b, 6)?;
let l = match l {
128 => Ok(true),
0 => Ok(false),
_ => Err(err_msg("invalid flag in color")),
}?;
2019-02-09 11:02:23 -08:00
2019-02-10 20:29:12 -08:00
Ok((i, ColorShp::Opaque{r, g, b, l}))
}
2019-02-09 11:02:23 -08:00
2019-02-10 20:33:38 -08:00
fn clut_collection(b: &[u8],
2019-02-11 03:29:01 -08:00
clu_num: usize,
clr_num: usize)
2019-02-10 20:33:38 -08:00
-> ResultS<Vec<Vec<ColorShp>>>
2019-02-10 20:29:12 -08:00
{
let mut tables = vec![vec![ColorShp::Translucent; clr_num]; clu_num];
let mut p = 0;
for i in 0..clu_num {
let clut = &mut tables[i];
for j in 0..clr_num {
let (i, cr) = color(c_data(b, p..)?)?;
if i >= clr_num {
bail!("invalid index");
}
clut[i] = cr;
p += 8;
}
}
Ok(tables)
2019-02-09 11:02:23 -08:00
}
2019-02-11 03:29:01 -08:00
fn bitmap<'a>(b: &[u8], clut: &'a [ColorShp]) -> ResultS<ImageShp<'a>>
{
let width = c_u16b(b, 0)? as usize;
let height = c_u16b(b, 2)? as usize;
let pitch = c_u16b(b, 4)? as usize;
let flags = c_u16b(b, 6)?;
let bpp = c_u16b(b, 8)?;
let flags = ok!(BmpFlags::from_bits(flags), "bad BmpFlags")?;
let alpha = flags.contains(BmpFlags::Transparent);
if bpp != 8 {
bail!("invalid bit depth (should always be 8)");
}
if flags.contains(BmpFlags::ColumnMajor) {
bail!("column major format not supported");
}
if pitch == u16::max_value() as usize {
bail!("compressed shape bitmap not supported");
}
let mut im = ImageShp::new(width, height, clut, alpha);
// let mut p = 30 + if flags.contains(BmpFlags::ColumnMajor) {
// 4 * width
// } else {
// 4 * height
// };
let mut p = 30 + 4 * height;
for _ in 0..height {
for _ in 0..width {
im.cr.push(b[p]);
p += 1;
}
}
Ok(im)
}
fn bitmap_collection<'a>(b: &[u8],
bmp_ofs: usize,
bmp_num: usize,
clut: &'a [ColorShp])
-> ResultS<Vec<ImageShp<'a>>>
{
let mut bitmaps = Vec::with_capacity(bmp_num);
let mut p = bmp_ofs;
for _ in 0..bmp_num {
let ofs = c_u32b(b, p)? as usize;
let bmp = bitmap(c_data(b, ofs..)?, clut)?;
use std::{fs, io};
let out = fs::File::create(&format!("out/shape{}.ppm", ofs))?;
let mut out = io::BufWriter::new(out);
write_ppm(&mut out, &bmp)?;
p += 4;
}
Ok(bitmaps)
}
2019-02-10 20:29:12 -08:00
/*
2019-02-09 11:02:23 -08:00
fn frame(b: &[u8]) -> ResultS<()>
{
2019-02-10 20:29:12 -08:00
let flags = c_u16b(b, 0)?;
let minlight = c_u32b(b, 2)?;
let bmp_ind = c_u16b(b, 6)?;
// orig_x = c_i16b(b, 8)?;
// orig_y = c_i16b(b, 10)?;
// key_x = c_i16b(b, 12)?;
// key_y = c_i16b(b, 14)?;
let wrl_l = c_i16b(b, 16)?;
let wrl_r = c_i16b(b, 18)?;
let wrl_t = c_i16b(b, 20)?;
let wrl_b = c_i16b(b, 22)?;
let wrl_x = c_i16b(b, 24)?;
let wrl_y = c_i16b(b, 26)?;
let flags = ok!(FrameFlags::from_bits(flags), "bad flag")?;
2019-02-09 11:02:23 -08:00
let minlight = Fx32::from_bits(minlight);
dbg!(flags);
dbg!(minlight);
dbg!(bmp_ind);
dbg!(wrl_l);
dbg!(wrl_r);
dbg!(wrl_t);
dbg!(wrl_b);
dbg!(wrl_x);
dbg!(wrl_y);
Ok(())
}
fn sequence(b: &[u8]) -> ResultS<()>
{
2019-02-10 20:29:12 -08:00
// sq_type = c_u16b(b, 0)?;
// flags = c_u16b(b, 2)?;
let name = c_data(b, 4..38)?;
let v_type = c_u16b(b, 38)?;
let frames = c_u16b(b, 40)?;
let ticks = c_u16b(b, 42)?;
let key = c_u16b(b, 44)?;
let xfer = c_u16b(b, 46)?;
let xfer_pd = c_u16b(b, 48)?;
let snd_beg = c_u16b(b, 50)?;
let snd_key = c_u16b(b, 52)?;
let snd_end = c_u16b(b, 54)?;
// xform = c_u16b(b, 56)?;
let loop_f = c_u16b(b, 58)?;
let name = mac_roman_conv(ok!(pascal_str(name), "bad string")?);
2019-02-09 11:02:23 -08:00
let snd_beg = ObjID::from_repr(snd_beg);
let snd_key = ObjID::from_repr(snd_key);
let snd_end = ObjID::from_repr(snd_end);
dbg!(name);
dbg!(v_type);
dbg!(frames);
dbg!(ticks);
dbg!(key);
dbg!(xfer);
dbg!(xfer_pd);
dbg!(snd_beg);
dbg!(snd_key);
dbg!(snd_end);
dbg!(loop_f);
Ok(())
}
2019-02-10 20:29:12 -08:00
*/
2019-02-09 11:02:23 -08:00
2019-02-10 20:29:12 -08:00
fn collection(b: &[u8]) -> ResultS<Collection>
2019-02-09 11:02:23 -08:00
{
2019-02-10 20:29:12 -08:00
let version = c_u16b(b, 0)?;
let cl_type = c_u16b(b, 2)?;
// flags = c_u16b(b, 4)?;
let clr_num = c_u16b(b, 6)? as usize;
let clu_num = c_u16b(b, 8)? as usize;
let clu_ofs = c_u32b(b, 10)? as usize;
let seq_num = c_u16b(b, 14)? as usize;
let seq_ofs = c_u32b(b, 16)? as usize;
let frm_num = c_u16b(b, 20)? as usize;
let frm_ofs = c_u32b(b, 22)? as usize;
let bmp_num = c_u16b(b, 26)? as usize;
let bmp_ofs = c_u32b(b, 28)? as usize;
// xform = c_i16b(b, 30)?;
let size = c_u32b(b, 32)? as usize;
2019-02-09 11:02:23 -08:00
let cl_type = CollectionType::from_repr(cl_type)?;
if version != 3 {
2019-02-10 20:29:12 -08:00
bail!("invalid collection version number");
2019-02-09 11:02:23 -08:00
}
2019-02-10 20:29:12 -08:00
/*
2019-02-09 11:02:23 -08:00
for i in 0..frm_num {
2019-02-10 20:29:12 -08:00
let p = c_u32b(b, frm_ofs + 4 * i)? as usize;
frame(c_data(b, p..)?)?;
2019-02-09 11:02:23 -08:00
}
for i in 0..seq_num {
2019-02-10 20:29:12 -08:00
let p = c_u32b(b, seq_ofs + 4 * i)? as usize;
sequence(c_data(b, p..)?)?;
2019-02-09 11:02:23 -08:00
}
2019-02-10 20:29:12 -08:00
*/
2019-02-09 11:02:23 -08:00
2019-02-11 03:29:01 -08:00
let tables = clut_collection(&b[clu_ofs..], clu_num, clr_num)?;
let bitmaps = bitmap_collection(b, bmp_ofs, bmp_num, &tables[0])?;
2019-02-10 20:29:12 -08:00
Ok(Collection{clr_num, tables, bitmaps: Vec::new()})
2019-02-09 11:02:23 -08:00
}
pub fn testfn_replaceme(b: &[u8]) -> ResultS<()>
{
for i in 0..32 {
let p = 32 * i;
2019-02-10 20:29:12 -08:00
// status = c_u16b(b, p + 0)?;
// flags = c_u16b(b, p + 2)?;
let offset_lo = c_u32b(b, p + 4)? as usize;
let length_lo = c_u32b(b, p + 8)? as usize;
let offset_hi = c_u32b(b, p + 12)? as usize;
let length_hi = c_u32b(b, p + 16)? as usize;
2019-02-10 20:33:38 -08:00
let collections =
(if offset_lo != u32::max_value() as usize {
Some(collection(c_data(b, offset_lo..offset_lo + length_lo)?)?)
} else {
None
},
if offset_hi != u32::max_value() as usize {
Some(collection(c_data(b, offset_hi..offset_hi + length_hi)?)?)
} else {
None
});
2019-02-10 20:29:12 -08:00
dbg!(collections);
}
Ok(())
}
2019-02-11 03:29:01 -08:00
impl ImageShp<'_>
{
fn new(w: usize, h: usize, clut: &[ColorShp], alpha: bool) -> ImageShp
{
ImageShp{w, h, clut, alpha, cr: Vec::with_capacity(w * h)}
}
}
2019-02-10 20:29:12 -08:00
impl Image for ImageShp<'_>
{
type Output = ColorShp;
fn w(&self) -> usize {self.w}
fn h(&self) -> usize {self.h}
2019-02-11 03:29:01 -08:00
fn cr_at(&self, x: usize, y: usize) -> &Self::Output
2019-02-10 20:29:12 -08:00
{
2019-02-11 03:29:01 -08:00
static TRANSLUCENT_COLOR: ColorShp = ColorShp::Translucent;
let cr = self.cr[x + y * self.w] as usize;
if self.alpha && cr == 0 {
&TRANSLUCENT_COLOR
} else {
self.clut.get(cr).unwrap_or(&TRANSLUCENT_COLOR)
}
2019-02-10 20:29:12 -08:00
}
}
impl Color for ColorShp
{
fn r(&self) -> u16
{
2019-02-11 03:29:01 -08:00
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{r, ..} => r,
2019-02-09 11:02:23 -08:00
}
2019-02-10 20:29:12 -08:00
}
fn g(&self) -> u16
{
2019-02-11 03:29:01 -08:00
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{g, ..} => g,
2019-02-09 11:02:23 -08:00
}
}
2019-02-10 20:29:12 -08:00
fn b(&self) -> u16
{
2019-02-11 03:29:01 -08:00
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{b, ..} => b,
2019-02-10 20:29:12 -08:00
}
}
fn a(&self) -> u16
{
2019-02-11 03:29:01 -08:00
match *self {
ColorShp::Translucent => 0,
ColorShp::Opaque{..} => u16::max_value(),
2019-02-10 20:29:12 -08:00
}
}
}
#[derive(Clone, Debug)]
enum ColorShp
{
Translucent,
2019-02-10 20:33:38 -08:00
Opaque
{
2019-02-10 20:29:12 -08:00
r: u16,
g: u16,
b: u16,
l: bool,
2019-02-10 20:33:38 -08:00
},
2019-02-10 20:29:12 -08:00
}
#[derive(Debug)]
struct ImageShp<'a>
{
2019-02-11 03:29:01 -08:00
w: usize,
h: usize,
cr: Vec<u8>,
alpha: bool,
clut: &'a [ColorShp],
2019-02-10 20:29:12 -08:00
}
#[derive(Debug)]
struct Collection<'a>
{
clr_num: usize,
tables: Vec<Vec<ColorShp>>,
bitmaps: Vec<ImageShp<'a>>,
2019-02-09 11:02:23 -08:00
}
2019-02-11 03:29:01 -08:00
bitflags! {
pub struct BmpFlags: u16
{
const ColumnMajor = 0x80_00;
const Transparent = 0x40_00;
}
}
2019-02-09 11:02:23 -08:00
bitflags! {
pub struct FrameFlags: u16
{
const Obscure = 0x20_00;
const FlipY = 0x40_00;
const FlipX = 0x80_00;
}
}
c_enum! {
#[derive(Debug)]
pub enum CollectionType: u16
{
0 => Unused,
1 => Wall,
2 => Object,
3 => Interface,
4 => Scenery,
}
}
// EOF