mirror of
https://github.com/dpethes/rerogue.git
synced 2025-06-07 18:58:32 +02:00
dat repack: use common units
This commit is contained in:
parent
32d9abb3ba
commit
86ea3565a4
@ -1,7 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<CONFIG>
|
<CONFIG>
|
||||||
<ProjectOptions>
|
<ProjectOptions>
|
||||||
<Version Value="9"/>
|
<Version Value="10"/>
|
||||||
<PathDelim Value="\"/>
|
<PathDelim Value="\"/>
|
||||||
<General>
|
<General>
|
||||||
<Flags>
|
<Flags>
|
||||||
@ -17,9 +17,6 @@
|
|||||||
<i18n>
|
<i18n>
|
||||||
<EnableI18N LFM="False"/>
|
<EnableI18N LFM="False"/>
|
||||||
</i18n>
|
</i18n>
|
||||||
<VersionInfo>
|
|
||||||
<StringTable ProductVersion=""/>
|
|
||||||
</VersionInfo>
|
|
||||||
<BuildModes Count="1">
|
<BuildModes Count="1">
|
||||||
<Item1 Name="Default" Default="True"/>
|
<Item1 Name="Default" Default="True"/>
|
||||||
</BuildModes>
|
</BuildModes>
|
||||||
@ -32,27 +29,19 @@
|
|||||||
<CommandLineParams Value="p r:\rogue_data\"/>
|
<CommandLineParams Value="p r:\rogue_data\"/>
|
||||||
</local>
|
</local>
|
||||||
</RunParams>
|
</RunParams>
|
||||||
<Units Count="4">
|
<Units Count="3">
|
||||||
<Unit0>
|
<Unit0>
|
||||||
<Filename Value="rs_repack.lpr"/>
|
<Filename Value="rs_repack.lpr"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
<UnitName Value="rs_repack"/>
|
|
||||||
</Unit0>
|
</Unit0>
|
||||||
<Unit1>
|
<Unit1>
|
||||||
<Filename Value="rsdat.pas"/>
|
|
||||||
<IsPartOfProject Value="True"/>
|
|
||||||
<UnitName Value="rsdat"/>
|
|
||||||
</Unit1>
|
|
||||||
<Unit2>
|
|
||||||
<Filename Value="rsdat_common.pas"/>
|
|
||||||
<IsPartOfProject Value="True"/>
|
|
||||||
<UnitName Value="rsdat_common"/>
|
|
||||||
</Unit2>
|
|
||||||
<Unit3>
|
|
||||||
<Filename Value="rsdat_pack.pas"/>
|
<Filename Value="rsdat_pack.pas"/>
|
||||||
<IsPartOfProject Value="True"/>
|
<IsPartOfProject Value="True"/>
|
||||||
<UnitName Value="rsdat_pack"/>
|
</Unit1>
|
||||||
</Unit3>
|
<Unit2>
|
||||||
|
<Filename Value="..\rs_units\rs_dat.pas"/>
|
||||||
|
<IsPartOfProject Value="True"/>
|
||||||
|
</Unit2>
|
||||||
</Units>
|
</Units>
|
||||||
</ProjectOptions>
|
</ProjectOptions>
|
||||||
<CompilerOptions>
|
<CompilerOptions>
|
||||||
@ -63,6 +52,7 @@
|
|||||||
</Target>
|
</Target>
|
||||||
<SearchPaths>
|
<SearchPaths>
|
||||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||||
|
<OtherUnitFiles Value="..\rs_units"/>
|
||||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||||
</SearchPaths>
|
</SearchPaths>
|
||||||
<CodeGeneration>
|
<CodeGeneration>
|
||||||
@ -73,12 +63,6 @@
|
|||||||
<StackChecks Value="True"/>
|
<StackChecks Value="True"/>
|
||||||
</Checks>
|
</Checks>
|
||||||
</CodeGeneration>
|
</CodeGeneration>
|
||||||
<Other>
|
|
||||||
<CompilerMessages>
|
|
||||||
<MsgFileName Value=""/>
|
|
||||||
</CompilerMessages>
|
|
||||||
<CompilerPath Value="$(CompPath)"/>
|
|
||||||
</Other>
|
|
||||||
</CompilerOptions>
|
</CompilerOptions>
|
||||||
<Debugging>
|
<Debugging>
|
||||||
<Exceptions Count="3">
|
<Exceptions Count="3">
|
||||||
|
@ -1,23 +1,22 @@
|
|||||||
program rs_repack;
|
program rs_repack;
|
||||||
|
|
||||||
uses
|
uses
|
||||||
sysutils, rsdat, rsdat_pack;
|
sysutils, rs_dat, rsdat_pack;
|
||||||
|
|
||||||
procedure UnpackData(const basedir: string);
|
procedure UnpackData(const basedir: string);
|
||||||
var
|
var
|
||||||
dat: TRSDatFile;
|
dat: TRSDatFile;
|
||||||
fhdr, fdat: string;
|
fhdr, fdat: string;
|
||||||
begin
|
begin
|
||||||
fhdr := basedir + 'DATA.HDR';
|
fhdr := basedir + RS_DATA_HDR;
|
||||||
fdat := basedir + 'DATA.DAT';
|
fdat := basedir + RS_DATA_DAT;
|
||||||
if not FileExists(fhdr) or not FileExists(fdat) then begin
|
if not FileExists(fhdr) or not FileExists(fdat) then begin
|
||||||
writeln('missing input files ', fhdr, ' or ', fdat);
|
writeln('missing input files ', fhdr, ' or ', fdat);
|
||||||
exit;
|
exit;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
dat := TRSDatFile.Create;
|
dat := TRSDatFile.Create(fhdr, fdat);
|
||||||
dat.ReadHeader(fhdr);
|
dat.Parse();
|
||||||
dat.ReadSections(fdat);
|
|
||||||
dat.WriteFilesToDirectory(basedir);
|
dat.WriteFilesToDirectory(basedir);
|
||||||
dat.Free;
|
dat.Free;
|
||||||
end;
|
end;
|
||||||
|
@ -1,221 +0,0 @@
|
|||||||
unit rsdat;
|
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
uses
|
|
||||||
Classes, SysUtils, rsdat_common;
|
|
||||||
|
|
||||||
type
|
|
||||||
{ TRSDatFile }
|
|
||||||
|
|
||||||
TRSDatFile = class
|
|
||||||
private
|
|
||||||
sections: array of TSection;
|
|
||||||
data: pbyte;
|
|
||||||
|
|
||||||
procedure ReadDatFile(const fname: string);
|
|
||||||
function ReadEntry(const stream: TMemoryStream): TFileNode;
|
|
||||||
procedure ReadSectionEntries(var section: TSection);
|
|
||||||
procedure ParseSectionStructure(var section: TSection);
|
|
||||||
|
|
||||||
public
|
|
||||||
procedure ReadHeader(const fname: string);
|
|
||||||
procedure ReadSections(const fname: string);
|
|
||||||
procedure WriteFilesToDirectory(const path: string);
|
|
||||||
constructor Create;
|
|
||||||
destructor Destroy; override;
|
|
||||||
end;
|
|
||||||
|
|
||||||
//**************************************************************************************************
|
|
||||||
implementation
|
|
||||||
|
|
||||||
procedure SaveFile(const name: string; const buffer: pbyte; const buf_size: integer);
|
|
||||||
var
|
|
||||||
f: file;
|
|
||||||
fname: string;
|
|
||||||
begin
|
|
||||||
fname := name;
|
|
||||||
AssignFile(f, fname);
|
|
||||||
Rewrite(f, 1);
|
|
||||||
BlockWrite(f, buffer^, buf_size);
|
|
||||||
CloseFile(f);
|
|
||||||
end;
|
|
||||||
|
|
||||||
{ TRSDatFile }
|
|
||||||
|
|
||||||
procedure TRSDatFile.ReadDatFile(const fname: string);
|
|
||||||
var
|
|
||||||
f: file;
|
|
||||||
fsize: integer;
|
|
||||||
begin
|
|
||||||
AssignFile(f, fname);
|
|
||||||
reset(f, 1);
|
|
||||||
fsize := FileSize(f);
|
|
||||||
data := getmem(fsize);
|
|
||||||
Blockread(f, data^, fsize);
|
|
||||||
closefile(f);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function TRSDatFile.ReadEntry(const stream: TMemoryStream): TFileNode;
|
|
||||||
var
|
|
||||||
entry: TFileEntry;
|
|
||||||
begin
|
|
||||||
stream.ReadBuffer(entry, 32);
|
|
||||||
result.name := Trim(entry.filename);
|
|
||||||
result.offset := entry.offset;
|
|
||||||
result.size := entry.length;
|
|
||||||
result.is_directory := (entry.type_flag and FEDirectoryFlag) <> 0;
|
|
||||||
result.subentries_count := entry.sub_entry_size div 32 - 1;
|
|
||||||
result.entry := entry;
|
|
||||||
result.data := nil;
|
|
||||||
//if (result.offset mod 32) <> 0 then writeln('unaligned offset');
|
|
||||||
writeln(stderr, format('name: %s size: %d dir: %s subsize: %d flags: %s',
|
|
||||||
[result.Name, entry.length, BoolToStr(result.is_directory),
|
|
||||||
entry.sub_entry_size, binStr(entry.type_flag, 16)]));
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRSDatFile.ReadSectionEntries(var section: TSection);
|
|
||||||
var
|
|
||||||
entries_offset: integer;
|
|
||||||
entries_length: integer;
|
|
||||||
entry_count: integer;
|
|
||||||
stream: TMemoryStream;
|
|
||||||
i: integer;
|
|
||||||
begin
|
|
||||||
entries_offset := (pinteger(section.data))^; //offset relative to section beginning
|
|
||||||
entries_length := (pinteger(section.data + 4))^; //length in bytes
|
|
||||||
section.size := entries_offset + entries_length;
|
|
||||||
entry_count := entries_length div 32; //actual count of entries
|
|
||||||
writeln('entries: ', entry_count);
|
|
||||||
|
|
||||||
stream := TMemoryStream.Create;
|
|
||||||
stream.WriteBuffer(section.data^, section.size);
|
|
||||||
stream.Seek(entries_offset, soBeginning);
|
|
||||||
|
|
||||||
SetLength(section.nodes, entry_count);
|
|
||||||
for i := 0 to entry_count - 1 do begin
|
|
||||||
section.nodes[i] := ReadEntry(stream);
|
|
||||||
end;
|
|
||||||
|
|
||||||
stream.Free;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure AddNode(const parent: PFileNode; var nodes: array of TFileNode; var node_index: integer);
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
node: PFileNode;
|
|
||||||
begin
|
|
||||||
if node_index > length(nodes) - 1 then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
//add current to parent
|
|
||||||
node := @nodes[node_index];
|
|
||||||
i := length(parent^.nodes);
|
|
||||||
Setlength(parent^.nodes, i + 1);
|
|
||||||
parent^.nodes[i] := node;
|
|
||||||
//writeln('added node: ', node^.name, ' to parent ', parent^.name);
|
|
||||||
|
|
||||||
//add all subentries if any
|
|
||||||
if node^.is_directory then begin
|
|
||||||
//writeln(' subentries: ', node^.subentries_count);
|
|
||||||
while CountSubNodes(node) < node^.subentries_count + 1 do begin
|
|
||||||
node_index += 1;
|
|
||||||
AddNode(node, nodes, node_index);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRSDatFile.ParseSectionStructure(var section: TSection);
|
|
||||||
var
|
|
||||||
node_idx: integer = 0;
|
|
||||||
begin
|
|
||||||
section.root.name := section.name;
|
|
||||||
section.root.is_directory := true;
|
|
||||||
section.root.data := nil;
|
|
||||||
while node_idx < length(section.nodes) do begin
|
|
||||||
AddNode(@section.root, section.nodes, node_idx);
|
|
||||||
node_idx += 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRSDatFile.ReadHeader(const fname: string);
|
|
||||||
var
|
|
||||||
f: file;
|
|
||||||
section: TSection;
|
|
||||||
section_n: integer;
|
|
||||||
i: integer;
|
|
||||||
buffer: array[0..15] of char;
|
|
||||||
begin
|
|
||||||
assignfile(f, fname);
|
|
||||||
reset(f, 1);
|
|
||||||
section_n := FileSize(f) div 32;
|
|
||||||
SetLength(sections, section_n);
|
|
||||||
|
|
||||||
for i := 0 to section_n - 1 do begin
|
|
||||||
blockread(f, buffer, 16); //name
|
|
||||||
section.name := trim(buffer);
|
|
||||||
blockread(f, buffer, 12); //empty
|
|
||||||
blockread(f, section.offset, 4); //offset in DATA.DAT
|
|
||||||
sections[i] := section;
|
|
||||||
end;
|
|
||||||
|
|
||||||
closefile(f);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRSDatFile.ReadSections(const fname: string);
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
begin
|
|
||||||
ReadDatFile(fname);
|
|
||||||
for i := 0 to length(sections) - 1 do begin
|
|
||||||
Writeln('reading section ', sections[i].name);
|
|
||||||
sections[i].data := data + sections[i].offset;
|
|
||||||
ReadSectionEntries(sections[i]);
|
|
||||||
ParseSectionStructure(sections[i]);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure WriteDirectory(const node: PFileNode; const path: string; const data: pbyte);
|
|
||||||
var
|
|
||||||
dir: string;
|
|
||||||
subnode: PFileNode;
|
|
||||||
i: Integer;
|
|
||||||
begin
|
|
||||||
dir := path + node^.name;
|
|
||||||
if not DirectoryExists(dir) then
|
|
||||||
MkDir(dir);
|
|
||||||
for i := 0 to length(node^.nodes) - 1 do begin
|
|
||||||
subnode := node^.nodes[i];
|
|
||||||
if subnode^.is_directory then
|
|
||||||
WriteDirectory(subnode, dir + DirectorySeparator, data)
|
|
||||||
else
|
|
||||||
SaveFile(dir + DirectorySeparator + subnode^.name, data + subnode^.offset, subnode^.size);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure TRSDatFile.WriteFilesToDirectory(const path: string);
|
|
||||||
var
|
|
||||||
section: TSection;
|
|
||||||
begin
|
|
||||||
for section in sections do begin
|
|
||||||
WriteDirectory(@section.root, path, section.data);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
constructor TRSDatFile.Create;
|
|
||||||
begin
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
destructor TRSDatFile.Destroy;
|
|
||||||
begin
|
|
||||||
inherited Destroy;
|
|
||||||
sections := nil;
|
|
||||||
freemem(data);
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
||||||
|
|
@ -1,83 +0,0 @@
|
|||||||
unit rsdat_common;
|
|
||||||
|
|
||||||
{$mode objfpc}{$H+}
|
|
||||||
|
|
||||||
interface
|
|
||||||
|
|
||||||
type
|
|
||||||
(*
|
|
||||||
uint32 {4} - Offset
|
|
||||||
uint32 {4} - Length (entry count * 32)
|
|
||||||
uint32 {4} - Padding (all 255's) 0xFF FF FF FF
|
|
||||||
uint16 {2} - type flag:
|
|
||||||
%10000000 - folder
|
|
||||||
%00000010 - file
|
|
||||||
%10000010 - subfolder
|
|
||||||
uint16 {2} - directory subentries length (entry count * 32)
|
|
||||||
char {16} - Filename (null) (replace "_" with ".")
|
|
||||||
*)
|
|
||||||
TFileEntry = packed record
|
|
||||||
offset: longword;
|
|
||||||
length: longword;
|
|
||||||
padding: longword;
|
|
||||||
type_flag: word;
|
|
||||||
sub_entry_size: word;
|
|
||||||
filename: array[0..15] of char;
|
|
||||||
end;
|
|
||||||
PFileEntry = ^TFileEntry;
|
|
||||||
|
|
||||||
const
|
|
||||||
FEDirectoryFlag = %10000000;
|
|
||||||
|
|
||||||
type
|
|
||||||
//file or directory node
|
|
||||||
PFileNode = ^TFileNode;
|
|
||||||
|
|
||||||
TFileNode = record
|
|
||||||
Name: string;
|
|
||||||
is_directory: boolean;
|
|
||||||
subentries_count: integer;
|
|
||||||
offset: longword;
|
|
||||||
size: longword;
|
|
||||||
entry: TFileEntry;
|
|
||||||
Data: pbyte;
|
|
||||||
nodes: array of PFileNode; //children if directory
|
|
||||||
end;
|
|
||||||
|
|
||||||
//root
|
|
||||||
TSection = record
|
|
||||||
Name: string; //section name
|
|
||||||
offset: integer; //offset in dat file
|
|
||||||
size: integer; //section length in bytes
|
|
||||||
Data: pbyte; //data
|
|
||||||
nodes: array of TFileNode; //all file entries / nodes
|
|
||||||
root: TFileNode; //tree structure of nodes
|
|
||||||
end;
|
|
||||||
|
|
||||||
function CountSubNodes(node: PFileNode): integer;
|
|
||||||
function CountSubNodeSizes(node: PFileNode): integer;
|
|
||||||
|
|
||||||
//**************************************************************************************************
|
|
||||||
implementation
|
|
||||||
|
|
||||||
function CountSubNodes(node: PFileNode): integer;
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
begin
|
|
||||||
Result := 1;
|
|
||||||
if node^.is_directory then
|
|
||||||
for i := 0 to Length(node^.nodes) - 1 do
|
|
||||||
Result += CountSubNodes(node^.nodes[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function CountSubNodeSizes(node: PFileNode): integer;
|
|
||||||
var
|
|
||||||
i: integer;
|
|
||||||
begin
|
|
||||||
Result := node^.size;
|
|
||||||
if node^.is_directory then
|
|
||||||
for i := 0 to Length(node^.nodes) - 1 do
|
|
||||||
Result += CountSubNodeSizes(node^.nodes[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
@ -5,7 +5,7 @@ unit rsdat_pack;
|
|||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
Classes, SysUtils, rsdat_common;
|
Classes, SysUtils, rs_dat;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -13,15 +13,15 @@ type
|
|||||||
|
|
||||||
TRSDatPacker = class
|
TRSDatPacker = class
|
||||||
private
|
private
|
||||||
Sections: array of TSection;
|
Sections: array of TRsHdrSection;
|
||||||
Data: TMemoryStream;
|
Data: TMemoryStream;
|
||||||
|
|
||||||
procedure FreeSections;
|
procedure FreeSections;
|
||||||
procedure ReadSectionFiles(const basepath: string);
|
procedure ReadSectionFiles(const basepath: string);
|
||||||
procedure WriteData(path: string);
|
procedure WriteData(path: string);
|
||||||
procedure WriteHeader(path: string);
|
procedure WriteHeader(path: string);
|
||||||
procedure WriteNodeData(node: PFileNode);
|
procedure WriteNodeData(node: PRsDatFileNode);
|
||||||
procedure WriteFileEntries(node: PFileNode; const base_offset: integer);
|
procedure WriteFileEntries(node: PRsDatFileNode; const base_offset: integer);
|
||||||
|
|
||||||
public
|
public
|
||||||
procedure PackDirectory(const path: string);
|
procedure PackDirectory(const path: string);
|
||||||
@ -32,9 +32,9 @@ type
|
|||||||
//**************************************************************************************************
|
//**************************************************************************************************
|
||||||
implementation
|
implementation
|
||||||
|
|
||||||
procedure ReadFileNodes(parent: PFileNode; path: string);
|
procedure ReadFileNodes(parent: PRsDatFileNode; path: string);
|
||||||
var
|
var
|
||||||
node: PFileNode;
|
node: PRsDatFileNode;
|
||||||
info: TSearchRec;
|
info: TSearchRec;
|
||||||
n: integer;
|
n: integer;
|
||||||
f: file;
|
f: file;
|
||||||
@ -80,7 +80,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure FreeFileNodes(node: PFileNode; const no_disposing: boolean = false);
|
procedure FreeFileNodes(node: PRsDatFileNode; const no_disposing: boolean = false);
|
||||||
var
|
var
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
@ -99,8 +99,8 @@ procedure TRSDatPacker.ReadSectionFiles(const basepath: string);
|
|||||||
var
|
var
|
||||||
n: integer;
|
n: integer;
|
||||||
info: TSearchRec;
|
info: TSearchRec;
|
||||||
section: TSection;
|
section: TRsHdrSection;
|
||||||
node: TFileNode;
|
node: TRsDatFileNode;
|
||||||
begin
|
begin
|
||||||
n := 0;
|
n := 0;
|
||||||
if FindFirst(basepath + '*', faDirectory, Info) = 0 then begin
|
if FindFirst(basepath + '*', faDirectory, Info) = 0 then begin
|
||||||
@ -136,7 +136,7 @@ begin
|
|||||||
Sections := nil;
|
Sections := nil;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TRSDatPacker.WriteNodeData(node: PFileNode);
|
procedure TRSDatPacker.WriteNodeData(node: PRsDatFileNode);
|
||||||
var
|
var
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
@ -161,9 +161,9 @@ TFileEntry = packed record
|
|||||||
sub_entry_size: word;
|
sub_entry_size: word;
|
||||||
filename: array[0..15] of char;
|
filename: array[0..15] of char;
|
||||||
end; }
|
end; }
|
||||||
procedure TRSDatPacker.WriteFileEntries(node: PFileNode; const base_offset: integer);
|
procedure TRSDatPacker.WriteFileEntries(node: PRsDatFileNode; const base_offset: integer);
|
||||||
var
|
var
|
||||||
entry: TFileEntry;
|
entry: TRsDatFileEntry;
|
||||||
name: string;
|
name: string;
|
||||||
i: integer;
|
i: integer;
|
||||||
begin
|
begin
|
||||||
@ -175,9 +175,9 @@ begin
|
|||||||
entry.sub_entry_size := (node^.subentries_count + 1) * 32;
|
entry.sub_entry_size := (node^.subentries_count + 1) * 32;
|
||||||
|
|
||||||
if node^.is_directory then
|
if node^.is_directory then
|
||||||
entry.type_flag := FEDirectoryFlag
|
entry.type_flag := RS_DATA_FEDirectoryFlag
|
||||||
else
|
else
|
||||||
entry.type_flag := %00000010;
|
entry.type_flag := RS_DATA_FEFileFlag;
|
||||||
|
|
||||||
writeln(stderr, format('name: %s size: %d dir: %s subsize: %d',
|
writeln(stderr, format('name: %s size: %d dir: %s subsize: %d',
|
||||||
[node^.Name, entry.length, BoolToStr(node^.is_directory), entry.sub_entry_size]));
|
[node^.Name, entry.length, BoolToStr(node^.is_directory), entry.sub_entry_size]));
|
||||||
@ -200,7 +200,7 @@ var
|
|||||||
i, k: integer;
|
i, k: integer;
|
||||||
head: pinteger;
|
head: pinteger;
|
||||||
entries: integer;
|
entries: integer;
|
||||||
section: TSection;
|
section: TRsHdrSection;
|
||||||
begin
|
begin
|
||||||
Data := TMemoryStream.Create;
|
Data := TMemoryStream.Create;
|
||||||
Data.Size := 1 shl 20;
|
Data.Size := 1 shl 20;
|
||||||
@ -208,7 +208,7 @@ begin
|
|||||||
section := Sections[i];
|
section := Sections[i];
|
||||||
|
|
||||||
Writeln('writing section: ', section.name);
|
Writeln('writing section: ', section.name);
|
||||||
section.offset := Data.Position;
|
section.dat_offset := Data.Position;
|
||||||
Data.WriteQWord(0); //offset + size placeholder
|
Data.WriteQWord(0); //offset + size placeholder
|
||||||
|
|
||||||
Writeln('writing file data');
|
Writeln('writing file data');
|
||||||
@ -216,13 +216,13 @@ begin
|
|||||||
WriteNodeData(section.root.nodes[k]);
|
WriteNodeData(section.root.nodes[k]);
|
||||||
|
|
||||||
entries := section.root.subentries_count;
|
entries := section.root.subentries_count;
|
||||||
head := pinteger (pbyte(Data.Memory) + section.offset);
|
head := pinteger (pbyte(Data.Memory) + section.dat_offset);
|
||||||
head^ := Data.Position - section.offset;
|
head^ := Data.Position - section.dat_offset;
|
||||||
head += 1;
|
head += 1;
|
||||||
head^ := entries * 32;
|
head^ := entries * 32;
|
||||||
Writeln('writing file entries: ', entries);
|
Writeln('writing file entries: ', entries);
|
||||||
for k := 0 to Length(section.root.nodes) - 1 do
|
for k := 0 to Length(section.root.nodes) - 1 do
|
||||||
WriteFileEntries(section.root.nodes[k], section.offset);
|
WriteFileEntries(section.root.nodes[k], section.dat_offset);
|
||||||
|
|
||||||
//align?
|
//align?
|
||||||
for k := 1 to 4 - (Data.Position mod 4) do
|
for k := 1 to 4 - (Data.Position mod 4) do
|
||||||
@ -249,7 +249,7 @@ begin
|
|||||||
name[k] := byte( section_name[k] );
|
name[k] := byte( section_name[k] );
|
||||||
|
|
||||||
Blockwrite(f, name, 28);
|
Blockwrite(f, name, 28);
|
||||||
Blockwrite(f, Sections[i].offset, 4);
|
Blockwrite(f, Sections[i].dat_offset, 4);
|
||||||
end;
|
end;
|
||||||
CloseFile(f);
|
CloseFile(f);
|
||||||
end;
|
end;
|
||||||
|
@ -15,6 +15,7 @@ const
|
|||||||
RS_DATA_HDR = 'DATA.HDR';
|
RS_DATA_HDR = 'DATA.HDR';
|
||||||
RS_DATA_DAT = 'DATA.DAT';
|
RS_DATA_DAT = 'DATA.DAT';
|
||||||
RS_DATA_FEDirectoryFlag = %10000000;
|
RS_DATA_FEDirectoryFlag = %10000000;
|
||||||
|
RS_DATA_FEFileFlag = %00000010;
|
||||||
|
|
||||||
type
|
type
|
||||||
//data file entry
|
//data file entry
|
||||||
|
Loading…
x
Reference in New Issue
Block a user