mirror of
https://github.com/dpethes/rerogue.git
synced 2025-06-07 18:58:32 +02:00
181 lines
4.4 KiB
ObjectPascal
181 lines
4.4 KiB
ObjectPascal
unit hmt_parser;
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils, Classes,
|
|
rs_image;
|
|
|
|
type
|
|
THmtMaterial = record
|
|
type_: shortint;
|
|
tex_index: shortint;
|
|
unknown_float1, unknown_float2: single;
|
|
zero: integer;
|
|
hex_a: integer;
|
|
name: array[0..15] of byte;
|
|
end;
|
|
|
|
THmtTexture = record
|
|
data_offset: integer;
|
|
palette_offset: integer;
|
|
name_offset: integer;
|
|
width, height: word;
|
|
name: array[0..15] of byte;
|
|
name_string: string;
|
|
image: TRSImage;
|
|
end;
|
|
|
|
THmtFile = record
|
|
material_count: integer;
|
|
texture_offset: integer;
|
|
texture_count: integer;
|
|
materials: array of THmtMaterial;
|
|
textures: array of THmtTexture;
|
|
end;
|
|
|
|
function ParseHmtFile(const fname: string): THmtFile;
|
|
|
|
//**************************************************************************************************
|
|
implementation
|
|
|
|
function NameToString(name: array of byte): string;
|
|
var
|
|
i: Integer;
|
|
begin
|
|
result := '';
|
|
for i := 0 to length(name) - 1 do begin
|
|
if name[i] = 0 then break;
|
|
result += char( name[i] );
|
|
end;
|
|
end;
|
|
|
|
|
|
procedure ReadTexture(var tex: THmtTexture; var f: TMemoryStream);
|
|
const
|
|
ImageDescription: array[0..5] of TImageDescription = (
|
|
(palette_entries: 16; sample_bits: 4),
|
|
(palette_entries: 256; sample_bits: 8),
|
|
(palette_entries: 0; sample_bits: 16),
|
|
(palette_entries: 0; sample_bits: 32),
|
|
(palette_entries: 0; sample_bits: 4),
|
|
(palette_entries: 0; sample_bits: 16)
|
|
);
|
|
var
|
|
image: TRSImage;
|
|
buf: array[0..27] of byte;
|
|
description: TImageDescription;
|
|
bpp: byte;
|
|
color_rgba: integer;
|
|
pos: int64;
|
|
begin
|
|
tex.data_offset := f.ReadDWord;
|
|
f.ReadBuffer(buf, 28);
|
|
tex.palette_offset := f.ReadDWord;
|
|
tex.name_offset := f.ReadDWord;
|
|
tex.width := f.ReadWord;
|
|
tex.height := f.ReadWord;
|
|
|
|
f.ReadByte; //0x01
|
|
bpp := f.ReadByte;
|
|
image.type_ := f.ReadByte;
|
|
f.ReadByte;
|
|
color_rgba := f.ReadDWord;
|
|
|
|
pos := f.Position;
|
|
f.Seek(tex.name_offset, TSeekOrigin.soBeginning);
|
|
f.ReadBuffer(tex.name, 16);
|
|
tex.name_string := NameToString(tex.name);
|
|
f.Seek(pos, TSeekOrigin.soBeginning);
|
|
|
|
description := ImageDescription[image.type_];
|
|
image.sampleBits := description.sample_bits;
|
|
image.paletteEntries := description.palette_entries;
|
|
image.width := tex.width;
|
|
image.height := tex.height;
|
|
|
|
writeln('name: ', tex.name_string);
|
|
writeln('size: ', tex.width, 'x', tex.height);
|
|
writeln('subtype: ', image.type_, ' bpp: ', bpp);
|
|
writeln('sample bits: ', image.sampleBits);
|
|
writeln('palette offset: ', tex.palette_offset);
|
|
writeln('data offset: ', tex.data_offset);
|
|
|
|
if tex.palette_offset > 0 then begin
|
|
writeln('palette entries: ', image.paletteEntries);
|
|
f.Seek(tex.palette_offset, TSeekOrigin.soBeginning);
|
|
LoadPalette(image, f);
|
|
end;
|
|
f.Seek(tex.data_offset, TSeekOrigin.soBeginning);
|
|
LoadSamples(image, f);
|
|
DecodePixels(image);
|
|
|
|
f.Seek(pos, TSeekOrigin.soBeginning);
|
|
writeln;
|
|
tex.image := image;
|
|
end;
|
|
|
|
|
|
procedure ReadMaterial(var mat: THmtMaterial; var f: TMemoryStream);
|
|
begin
|
|
mat.type_ := f.ReadWord;
|
|
mat.tex_index := f.ReadWord;
|
|
mat.unknown_float1 := f.ReadDWord;
|
|
mat.unknown_float2 := f.ReadDWord;
|
|
mat.zero := f.ReadDWord;
|
|
mat.hex_a := f.ReadDWord;
|
|
f.ReadBuffer(mat.name, 16);
|
|
|
|
writeln(NameToString(mat.name));
|
|
if (mat.zero <> 0) or (mat.hex_a <> $A) then
|
|
writeln('unusual file');
|
|
writeln(' type1: ', mat.type_);
|
|
writeln(' type2: ', mat.tex_index);
|
|
end;
|
|
|
|
|
|
function ParseHmtFile(const fname: string): THmtFile;
|
|
var
|
|
f: TMemoryStream;
|
|
hmt: THmtFile;
|
|
i: Integer;
|
|
begin
|
|
f := TMemoryStream.Create;
|
|
f.LoadFromFile(fname);
|
|
|
|
//read main info
|
|
hmt.material_count := f.ReadDWord;
|
|
hmt.texture_offset := f.ReadDWord;
|
|
f.Seek(hmt.texture_offset, TSeekOrigin.soBeginning);
|
|
hmt.texture_count := f.ReadDWord;
|
|
f.Seek(8, TSeekOrigin.soBeginning);
|
|
|
|
//read materials
|
|
writeln('materials: ', hmt.material_count);
|
|
SetLength(hmt.materials, hmt.material_count);
|
|
for i := 0 to hmt.material_count - 1 do begin
|
|
ReadMaterial(hmt.materials[i], f);
|
|
end;
|
|
|
|
if hmt.texture_count = 0 then begin
|
|
result := hmt;
|
|
f.Free;
|
|
exit;
|
|
end;
|
|
|
|
//read textures
|
|
writeln('textures: ', hmt.texture_count);
|
|
f.Seek(hmt.texture_offset + 4, TSeekOrigin.soBeginning);
|
|
SetLength(hmt.textures, hmt.texture_count);
|
|
for i := 0 to hmt.texture_count - 1 do begin
|
|
ReadTexture(hmt.textures[i], f);
|
|
end;
|
|
|
|
f.Free;
|
|
result := hmt;
|
|
end;
|
|
|
|
end.
|
|
|