Index: /oup/current/OniUnPacker.bdsproj
===================================================================
--- /oup/current/OniUnPacker.bdsproj	(revision 10)
+++ /oup/current/OniUnPacker.bdsproj	(revision 10)
@@ -0,0 +1,183 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<BorlandProject>
+	<PersonalityInfo>
+		<Option>
+			<Option Name="Personality">Delphi.Personality</Option>
+			<Option Name="ProjectType"></Option>
+			<Option Name="Version">1.0</Option>
+			<Option Name="GUID">{5F594E8D-8185-4AC6-8191-2A0F26194CB4}</Option>
+		</Option>
+	</PersonalityInfo>
+	<Delphi.Personality>
+		<Source>
+			<Source Name="MainSource">OniUnPacker.dpr</Source>
+		</Source>
+		<FileVersion>
+			<FileVersion Name="Version">7.0</FileVersion>
+		</FileVersion>
+		<Compiler>
+			<Compiler Name="A">8</Compiler>
+			<Compiler Name="B">0</Compiler>
+			<Compiler Name="C">1</Compiler>
+			<Compiler Name="D">1</Compiler>
+			<Compiler Name="E">0</Compiler>
+			<Compiler Name="F">0</Compiler>
+			<Compiler Name="G">1</Compiler>
+			<Compiler Name="H">1</Compiler>
+			<Compiler Name="I">1</Compiler>
+			<Compiler Name="J">0</Compiler>
+			<Compiler Name="K">0</Compiler>
+			<Compiler Name="L">1</Compiler>
+			<Compiler Name="M">0</Compiler>
+			<Compiler Name="N">1</Compiler>
+			<Compiler Name="O">1</Compiler>
+			<Compiler Name="P">1</Compiler>
+			<Compiler Name="Q">0</Compiler>
+			<Compiler Name="R">0</Compiler>
+			<Compiler Name="S">0</Compiler>
+			<Compiler Name="T">0</Compiler>
+			<Compiler Name="U">0</Compiler>
+			<Compiler Name="V">1</Compiler>
+			<Compiler Name="W">0</Compiler>
+			<Compiler Name="X">1</Compiler>
+			<Compiler Name="Y">1</Compiler>
+			<Compiler Name="Z">1</Compiler>
+			<Compiler Name="ShowHints">True</Compiler>
+			<Compiler Name="ShowWarnings">True</Compiler>
+			<Compiler Name="UnitAliases">WinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;</Compiler>
+			<Compiler Name="NamespacePrefix"></Compiler>
+			<Compiler Name="GenerateDocumentation">False</Compiler>
+			<Compiler Name="DefaultNamespace"></Compiler>
+			<Compiler Name="SymbolDeprecated">True</Compiler>
+			<Compiler Name="SymbolLibrary">True</Compiler>
+			<Compiler Name="SymbolPlatform">True</Compiler>
+			<Compiler Name="SymbolExperimental">True</Compiler>
+			<Compiler Name="UnitLibrary">True</Compiler>
+			<Compiler Name="UnitPlatform">True</Compiler>
+			<Compiler Name="UnitDeprecated">True</Compiler>
+			<Compiler Name="UnitExperimental">True</Compiler>
+			<Compiler Name="HResultCompat">True</Compiler>
+			<Compiler Name="HidingMember">True</Compiler>
+			<Compiler Name="HiddenVirtual">True</Compiler>
+			<Compiler Name="Garbage">True</Compiler>
+			<Compiler Name="BoundsError">True</Compiler>
+			<Compiler Name="ZeroNilCompat">True</Compiler>
+			<Compiler Name="StringConstTruncated">True</Compiler>
+			<Compiler Name="ForLoopVarVarPar">True</Compiler>
+			<Compiler Name="TypedConstVarPar">True</Compiler>
+			<Compiler Name="AsgToTypedConst">True</Compiler>
+			<Compiler Name="CaseLabelRange">True</Compiler>
+			<Compiler Name="ForVariable">True</Compiler>
+			<Compiler Name="ConstructingAbstract">True</Compiler>
+			<Compiler Name="ComparisonFalse">True</Compiler>
+			<Compiler Name="ComparisonTrue">True</Compiler>
+			<Compiler Name="ComparingSignedUnsigned">True</Compiler>
+			<Compiler Name="CombiningSignedUnsigned">True</Compiler>
+			<Compiler Name="UnsupportedConstruct">True</Compiler>
+			<Compiler Name="FileOpen">True</Compiler>
+			<Compiler Name="FileOpenUnitSrc">True</Compiler>
+			<Compiler Name="BadGlobalSymbol">True</Compiler>
+			<Compiler Name="DuplicateConstructorDestructor">True</Compiler>
+			<Compiler Name="InvalidDirective">True</Compiler>
+			<Compiler Name="PackageNoLink">True</Compiler>
+			<Compiler Name="PackageThreadVar">True</Compiler>
+			<Compiler Name="ImplicitImport">True</Compiler>
+			<Compiler Name="HPPEMITIgnored">True</Compiler>
+			<Compiler Name="NoRetVal">True</Compiler>
+			<Compiler Name="UseBeforeDef">True</Compiler>
+			<Compiler Name="ForLoopVarUndef">True</Compiler>
+			<Compiler Name="UnitNameMismatch">True</Compiler>
+			<Compiler Name="NoCFGFileFound">True</Compiler>
+			<Compiler Name="MessageDirective">True</Compiler>
+			<Compiler Name="ImplicitVariants">True</Compiler>
+			<Compiler Name="UnicodeToLocale">True</Compiler>
+			<Compiler Name="LocaleToUnicode">True</Compiler>
+			<Compiler Name="ImagebaseMultiple">True</Compiler>
+			<Compiler Name="SuspiciousTypecast">True</Compiler>
+			<Compiler Name="PrivatePropAccessor">True</Compiler>
+			<Compiler Name="UnsafeType">False</Compiler>
+			<Compiler Name="UnsafeCode">False</Compiler>
+			<Compiler Name="UnsafeCast">False</Compiler>
+			<Compiler Name="OptionTruncated">True</Compiler>
+			<Compiler Name="WideCharReduced">True</Compiler>
+			<Compiler Name="DuplicatesIgnored">True</Compiler>
+			<Compiler Name="UnitInitSeq">True</Compiler>
+			<Compiler Name="LocalPInvoke">True</Compiler>
+			<Compiler Name="CodePage"></Compiler>
+		</Compiler>
+		<Linker>
+			<Linker Name="MapFile">0</Linker>
+			<Linker Name="OutputObjs">0</Linker>
+			<Linker Name="ConsoleApp">1</Linker>
+			<Linker Name="DebugInfo">False</Linker>
+			<Linker Name="RemoteSymbols">False</Linker>
+			<Linker Name="GenerateDRC">False</Linker>
+			<Linker Name="MinStackSize">16384</Linker>
+			<Linker Name="MaxStackSize">1048576</Linker>
+			<Linker Name="ImageBase">4194304</Linker>
+			<Linker Name="ExeDescription"></Linker>
+			<Linker Name="GenerateHpps">False</Linker>
+		</Linker>
+		<Directories>
+			<Directories Name="OutputDir">exe</Directories>
+			<Directories Name="UnitOutputDir">dcu</Directories>
+			<Directories Name="PackageDLLOutputDir"></Directories>
+			<Directories Name="PackageDCPOutputDir"></Directories>
+			<Directories Name="SearchPath"></Directories>
+			<Directories Name="Packages">xmlrtl;rtl;vcl;vclie;inet;inetdbbde;inetdbxpress;vclx;IndySystem;IndyCore;dbrtl;dsnap;soaprtl;IndyProtocols;bdertl;vcldbx;vcldb;webdsnap;websnap;vclactnband;GridPackd2005;TWrapGrid;Package1;A406_R70;CoolTrayIcon_D6plus</Directories>
+			<Directories Name="Conditionals"></Directories>
+			<Directories Name="DebugSourceDirs"></Directories>
+			<Directories Name="UsePackages">False</Directories>
+		</Directories>
+		<Parameters>
+			<Parameters Name="RunParams"></Parameters>
+			<Parameters Name="HostApplication"></Parameters>
+			<Parameters Name="Launcher"></Parameters>
+			<Parameters Name="UseLauncher">False</Parameters>
+			<Parameters Name="DebugCWD"></Parameters>
+			<Parameters Name="RemoteHost"></Parameters>
+			<Parameters Name="RemotePath"></Parameters>
+			<Parameters Name="RemoteLauncher"></Parameters>
+			<Parameters Name="RemoteCWD"></Parameters>
+			<Parameters Name="RemoteDebug">False</Parameters>
+			<Parameters Name="Debug Symbols Search Path"></Parameters>
+			<Parameters Name="LoadAllSymbols">True</Parameters>
+			<Parameters Name="LoadUnspecifiedSymbols">False</Parameters>
+		</Parameters>
+		<VersionInfo>
+			<VersionInfo Name="IncludeVerInfo">False</VersionInfo>
+			<VersionInfo Name="AutoIncBuild">False</VersionInfo>
+			<VersionInfo Name="MajorVer">1</VersionInfo>
+			<VersionInfo Name="MinorVer">0</VersionInfo>
+			<VersionInfo Name="Release">0</VersionInfo>
+			<VersionInfo Name="Build">0</VersionInfo>
+			<VersionInfo Name="Debug">False</VersionInfo>
+			<VersionInfo Name="PreRelease">False</VersionInfo>
+			<VersionInfo Name="Special">False</VersionInfo>
+			<VersionInfo Name="Private">False</VersionInfo>
+			<VersionInfo Name="DLL">False</VersionInfo>
+			<VersionInfo Name="Locale">1031</VersionInfo>
+			<VersionInfo Name="CodePage">1252</VersionInfo>
+		</VersionInfo>
+		<VersionInfoKeys>
+			<VersionInfoKeys Name="CompanyName"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileDescription"></VersionInfoKeys>
+			<VersionInfoKeys Name="FileVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="InternalName"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalCopyright"></VersionInfoKeys>
+			<VersionInfoKeys Name="LegalTrademarks"></VersionInfoKeys>
+			<VersionInfoKeys Name="OriginalFilename"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductName"></VersionInfoKeys>
+			<VersionInfoKeys Name="ProductVersion">1.0.0.0</VersionInfoKeys>
+			<VersionInfoKeys Name="Comments"></VersionInfoKeys>
+		</VersionInfoKeys>
+		<Language>
+			<Language Name="ActiveLang"></Language>
+			<Language Name="ProjectLang">$00000000</Language>
+			<Language Name="RootDir"></Language>
+		</Language>  <Excluded_Packages>
+      <Excluded_Packages Name="C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Borland Studio Projects\Bpl\TCrossEdit.bpl">(untitled)</Excluded_Packages>
+      <Excluded_Packages Name="d:\programme\borland\bds\3.0\Bin\dbwebxprt.bpl">Borland Web Wizard Package</Excluded_Packages>
+    </Excluded_Packages>
+  </Delphi.Personality>
+</BorlandProject>
Index: /oup/current/OniUnPacker.bdsproj.local
===================================================================
--- /oup/current/OniUnPacker.bdsproj.local	(revision 10)
+++ /oup/current/OniUnPacker.bdsproj.local	(revision 10)
@@ -0,0 +1,32 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<BorlandProject>
+	<Transactions>
+    <Transaction>2005.09.12 15:50:55.441.pas,C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Borland Studio Projects\Unit1.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit1_main.pas</Transaction>
+    <Transaction>2005.09.12 15:50:55.451.dfm,C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Borland Studio Projects\Unit1.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit1_main.dfm</Transaction>
+    <Transaction>2005.09.16 14:33:57.886.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit1.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit4_Exporters.pas</Transaction>
+    <Transaction>2005.09.19 21:00:33.217.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit5_preview.pas</Transaction>
+    <Transaction>2005.09.19 21:00:33.227.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit5_preview.dfm</Transaction>
+    <Transaction>2005.09.20 21:51:14.061.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit1.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit6_imgfuncs.pas</Transaction>
+    <Transaction>2005.10.16 00:37:22.880.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit7_txmpreplace.pas</Transaction>
+    <Transaction>2005.10.16 00:37:22.940.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit7_txmpreplace.dfm</Transaction>
+    <Transaction>2005.10.18 21:55:56.791.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit8_binedit.pas</Transaction>
+    <Transaction>2005.10.18 21:55:56.801.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit8_binedit.dfm</Transaction>
+    <Transaction>2005.10.20 04:00:18.974.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit1.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit9_data_structures.pas</Transaction>
+    <Transaction>2005.10.24 02:53:07.530.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb.pas</Transaction>
+    <Transaction>2005.10.24 02:53:07.540.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb.dfm</Transaction>
+    <Transaction>2005.10.28 00:20:57.420.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit11_extractor.pas</Transaction>
+    <Transaction>2005.10.28 00:20:57.440.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit11_extractor.dfm</Transaction>
+    <Transaction>2005.12.18 11:32:06.823.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit12_ValueEdit.pas</Transaction>
+    <Transaction>2005.12.18 11:32:06.833.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit12_ValueEdit.dfm</Transaction>
+    <Transaction>2005.12.22 16:36:15.685.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2_functions.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2_functions_ABS.pas</Transaction>
+    <Transaction>2005.12.22 16:39:50.444.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb_ABS.pas</Transaction>
+    <Transaction>2005.12.22 16:39:50.444.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb_ABS.dfm</Transaction>
+    <Transaction>2005.12.24 01:01:39.626.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb_ABS.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb.pas</Transaction>
+    <Transaction>2005.12.24 01:01:39.656.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb_ABS.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit10_leveldb.dfm</Transaction>
+    <Transaction>2005.12.24 01:01:49.189.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2_functions_ABS.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2_functions.pas</Transaction>
+    <Transaction>2006.03.08 23:10:57.921.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Include_DataStructureDefs.pas=</Transaction>
+    <Transaction>2006.03.29 13:26:01.629.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit14_settings.pas</Transaction>
+    <Transaction>2006.03.29 13:26:01.649.dfm,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit2.dfm=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit14_settings.dfm</Transaction>
+    <Transaction>2006.04.05 19:40:35.621.pas,C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit1.pas=C:\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker\Unit15_Classes.pas</Transaction>
+  </Transactions>
+</BorlandProject>
Index: /oup/current/OniUnPacker.cfg
===================================================================
--- /oup/current/OniUnPacker.cfg	(revision 10)
+++ /oup/current/OniUnPacker.cfg	(revision 10)
@@ -0,0 +1,40 @@
+-$A8
+-$B-
+-$C+
+-$D+
+-$E-
+-$F-
+-$G+
+-$H+
+-$I+
+-$J-
+-$K-
+-$L+
+-$M-
+-$N+
+-$O+
+-$P+
+-$Q-
+-$R-
+-$S-
+-$T-
+-$U-
+-$V+
+-$W-
+-$X+
+-$YD
+-$Z1
+-cg
+-AWinTypes=Windows;WinProcs=Windows;DbiTypes=BDE;DbiProcs=BDE;DbiErrs=BDE;
+-H+
+-W+
+-M
+-$M16384,1048576
+-K$00400000
+-E"exe"
+-N0"dcu"
+-LE"C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Borland Studio Projects\Bpl"
+-LN"C:\Dokumente und Einstellungen\Administrator\Eigene Dateien\Borland Studio Projects\Bpl"
+-w-UNSAFE_TYPE
+-w-UNSAFE_CODE
+-w-UNSAFE_CAST
Index: /oup/current/OniUnPacker.dpr
===================================================================
--- /oup/current/OniUnPacker.dpr	(revision 10)
+++ /oup/current/OniUnPacker.dpr	(revision 10)
@@ -0,0 +1,32 @@
+PROGRAM OniUnPacker;
+uses
+  Forms,
+  Unit1_main in 'Unit1_main.pas' {Form1},
+  Unit2_functions in 'Unit2_functions.pas',
+  Unit3_data in 'Unit3_data.pas',
+  Unit4_Exporters in 'Unit4_Exporters.pas',
+  Unit5_preview in 'Unit5_preview.pas' {Form5},
+  Unit6_imgfuncs in 'Unit6_imgfuncs.pas',
+  Unit7_txmpreplace in 'Unit7_txmpreplace.pas' {Form7},
+  Unit8_binedit in 'Unit8_binedit.pas' {Form8},
+  Unit9_data_structures in 'Unit9_data_structures.pas',
+  Unit10_leveldb in 'Unit10_leveldb.pas' {Form10},
+  Unit11_extractor in 'Unit11_extractor.pas' {Form11},
+  Unit12_ValueEdit in 'Unit12_ValueEdit.pas' {Form12},
+  Unit13_rawedit in 'Unit13_rawedit.pas' {Form13},
+  Unit14_settings in 'Unit14_settings.pas' {Form14},
+  ftypesAPI in 'TFileTypeRegistration\ftypesAPI.pas',
+  Unit15_Classes in 'Unit15_Classes.pas';
+
+{$R *.res}
+{$R icon2.res}
+
+BEGIN
+  Application.Initialize;
+  Application.Title:='Oni Un/Packer';
+  Application.CreateForm(TForm1, Form1);
+  Application.CreateForm(TForm10, Form10);
+  Application.CreateForm(TForm12, Form12);
+  Application.CreateForm(TForm14, Form14);
+  Application.Run;
+END.
Index: /oup/current/TFileTypeRegistration/IsAdmin.inc
===================================================================
--- /oup/current/TFileTypeRegistration/IsAdmin.inc	(revision 10)
+++ /oup/current/TFileTypeRegistration/IsAdmin.inc	(revision 10)
@@ -0,0 +1,90 @@
+function GetAdminSid: PSID;
+const
+  // bekannte SIDs ... (WinNT.h)
+  SECURITYNTAUTHORITY: TSIDIdentifierAuthority = (Value: (0, 0, 0, 0, 0, 5));
+  // bekannte RIDs ... (WinNT.h)
+  SECURITYBUILTINDOMAINRID: DWORD = $00000020;
+  DOMAINALIASRIDADMINS: DWORD = $00000220;
+begin
+  Result := nil;
+  AllocateAndInitializeSid(SECURITYNTAUTHORITY,
+    2,
+    SECURITYBUILTINDOMAINRID,
+    DOMAINALIASRIDADMINS,
+    0,
+    0,
+    0,
+    0,
+    0,
+    0,
+    Result);
+end;
+
+function IsAdmin: LongBool;
+var
+  TokenHandle      : THandle;
+  ReturnLength     : DWORD;
+  TokenInformation : PTokenGroups;
+  AdminSid         : PSID;
+  Loop             : Integer;
+  wv               : TOSVersionInfo;
+begin
+  wv.dwOSVersionInfoSize := sizeof(TOSversionInfo);
+  GetVersionEx(wv);
+
+  Result := (wv.dwPlatformId = VER_PLATFORM_WIN32_WINDOWS);
+
+  if(wv.dwPlatformId = VER_PLATFORM_WIN32_NT) then
+    begin
+      TokenHandle := 0;
+      if OpenProcessToken(GetCurrentProcess, TOKEN_QUERY, TokenHandle) then
+        try
+          ReturnLength := 0;
+          GetTokenInformation(TokenHandle, TokenGroups, nil, 0, ReturnLength);
+          TokenInformation := GetMemory(ReturnLength);
+          if Assigned(TokenInformation) then
+            try
+              if GetTokenInformation(TokenHandle, TokenGroups,
+                TokenInformation, ReturnLength, ReturnLength) then
+              begin
+                AdminSid := GetAdminSid;
+                for Loop := 0 to TokenInformation^.GroupCount - 1 do
+                  begin
+                    if EqualSid(TokenInformation^.Groups[Loop].Sid, AdminSid) then
+                      begin
+                        Result := True; break;
+                      end;
+                  end;
+                FreeSid(AdminSid);
+              end;
+            finally
+              FreeMemory(TokenInformation);
+            end;
+        finally
+          CloseHandle(TokenHandle);
+        end;
+    end;
+end;
+
+function WVersion: string; 
+var 
+  OSInfo: TOSVersionInfo; 
+begin 
+  Result := '3X'; 
+  OSInfo.dwOSVersionInfoSize := sizeof(TOSVERSIONINFO); 
+  GetVersionEx(OSInfo); 
+  case OSInfo.dwPlatformID of 
+    VER_PLATFORM_WIN32S: begin 
+        Result := '3X'; 
+        Exit; 
+      end; 
+    VER_PLATFORM_WIN32_WINDOWS: begin 
+        Result := '9X'; 
+        Exit; 
+      end; 
+    VER_PLATFORM_WIN32_NT: begin 
+        Result := 'NT'; 
+        Exit; 
+      end; 
+  end; //case 
+end;
Index: /oup/current/TFileTypeRegistration/SysUtils.inc
===================================================================
--- /oup/current/TFileTypeRegistration/SysUtils.inc	(revision 10)
+++ /oup/current/TFileTypeRegistration/SysUtils.inc	(revision 10)
@@ -0,0 +1,307 @@
+function fileexists(const szFilename: string): boolean;
+var
+  Handle   : THandle;
+  FindData : TWin32FindData;
+begin
+  Handle := FindFirstFile(pchar(szFilename),FindData);
+  Result := (Handle <> INVALID_HANDLE_VALUE);
+
+  if(Result) then Windows.FindClose(Handle);
+end;
+
+function ExtractFileDrive(const szFilename: string): string;
+var
+  i : integer;
+begin
+  Result := '';
+  i      := length(szFilename);
+  while(i > 0) do
+  begin
+    if(szFileName[i] = ':') then
+    begin
+      Result := copy(szFilename,1,i);
+      break;
+    end;
+
+    dec(i);
+  end;
+end;
+
+function ExtractFilePath(const szFilename: string): string;
+var
+  i : integer;
+begin
+  Result := '';
+  i      := length(szFileName);
+  while(i > 0) do
+  begin
+    if(szFileName[i] = ':') or
+      (szFileName[i] = '\') then
+    begin
+      Result := copy(szFileName,1,i);
+      break;
+    end;
+
+    dec(i);
+  end;
+end;
+
+function ExtractFileName(const szFilename: string): string;
+var
+  i : integer;
+begin
+  i := length(szFilename);
+  while(i > 0) do
+  begin
+    if(szFilename[i] = '\') then
+      break;
+
+    dec(i);
+  end;
+
+  Result := copy(szFilename,i + 1,length(szFilename));
+end;
+
+function CutFileExt(const szFilename: string): string;
+var
+  i : integer;
+begin
+  i := length(szFilename);
+  while(i > 0) do
+  begin
+    if(szFilename[i] = '.') then
+      break;
+
+    dec(i);
+  end;
+
+  if(i = 0) then Result := szFilename
+    else Result := copy(szFilename,1,i-1);
+end;
+
+function ChangeFileExt(const szFileName, szNewExt: string): string;
+begin
+  Result := CutFileExt(szFileName);
+
+  if(szNewExt[1] <> '.') then Result := Result + '.' + szNewExt
+    else Result := Result + szNewExt;
+end;
+
+function FileSearch(const Name, DirList: string): string;
+var
+  I, P, L: Integer;
+begin
+  Result := Name;
+  P      := 1;
+  L      := length(DirList);
+
+  while(true) do begin
+    if(fileexists(Result)) then exit;
+
+    while(P <= L) and (DirList[P] = ';') do inc(P);
+    if(P > L) then break;
+
+    I := P;
+    while(P <= L) and (DirList[P] <> ';') do inc(P);
+
+    Result   := copy(DirList,I,P-I);
+    if not(Result[length(Result)] in[':','\']) then
+      Result := Result + '\';
+
+    Result := Result + Name;
+  end;
+
+  Result  := '';
+end;
+
+function StrToIntDef(const s: string; const i: integer): integer;
+var
+  code : integer;
+begin
+  Val(s,Result,code); if(code <> 0) then
+                        Result := i;
+end;
+
+function IntToStr(const i: integer): string;
+begin
+  Str(i,Result);
+end;
+
+// -----------------------------------------------------------------------------
+
+function Format(fmt: string; params: array of const): string;
+var
+  pdw1,
+  pdw2 : PDWORD;
+  i    : integer;
+  pc   : PCHAR;
+begin
+  pdw1 := nil;
+
+  if High(params) >= 0 then
+    GetMem(pdw1, (High(params) + 1) * sizeof(Pointer));
+
+  pdw2  := pdw1;
+  for i := 0 to High(params) do
+    begin
+      pdw2^ := PDWORD(@params[i])^;
+      inc(pdw2);
+    end;
+
+  pc := GetMemory(1024);
+  if Assigned(pc) then
+    try
+      SetString(Result, pc, wvsprintf(pc, PCHAR(fmt), PCHAR(pdw1)));
+    finally
+      if (pdw1 <> nil) then FreeMem(pdw1);
+      FreeMem(pc);
+    end
+  else
+    Result := '';
+end;
+
+
+// -----------------------------------------------------------------------------
+
+function UpperCase(const s: string): string;
+var
+  i : integer;
+begin
+  Result := '';
+
+  if(length(s) > 0) then
+    begin
+      SetLength(Result,length(s));
+      for i := 1 to length(s) do
+        Result[i] := UpCase(s[i]);
+    end;
+end;
+
+function LowerCase(const s: string): string;
+var
+  i : integer;
+begin
+  Result := '';
+
+  if(length(s) > 0) then
+    begin
+      SetLength(Result,length(s));
+      for i := 1 to length(s) do
+        case s[i] of
+          'A'..'Z','Ä','Ö','Ü':
+            Result[i] := CHR(BYTE(s[i]) + 32);
+          else
+            Result[i] := s[i];
+        end;
+    end;
+end;
+
+function LoggedUser: string;
+var
+  dwLen  : dword;
+  fTest  : boolean;
+begin
+  Result := '';
+  dwLen  := MAX_PATH; SetLength(Result,dwLen);
+
+  fTest  := GetUserName(@Result[1],dwLen);
+
+  if(not fTest) and (GetLastError = ERROR_MORE_DATA) then begin
+    SetLength(Result,dwLen);
+    fTest := GetUserName(@Result[1],dwLen);
+  end;
+
+  if(fTest) and (Result[1] <> #0) then
+    SetLength(Result,dwLen - 1);
+end;
+
+// -----------------------------------------------------------------------------
+
+//
+// delete files during next reboot (code by sakura)
+//
+function DeleteFileDuringNextSystemBoot(aFileName: string): Boolean;
+var
+  ShortName,
+  winini    : string;
+  os        : TOSVersionInfo;
+  ts        : array of string;
+  f         : TextFile;
+  i         : integer;
+begin
+  Result := False;
+
+  // get OS version
+  os.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
+  GetVersionEx(os);
+
+  case os.dwPlatformId of
+    // NT systems
+    VER_PLATFORM_WIN32_NT:
+      Result := MoveFileEx(pchar(aFileName),nil,
+        MOVEFILE_REPLACE_EXISTING + MOVEFILE_DELAY_UNTIL_REBOOT);
+    // 9x systems
+    VER_PLATFORM_WIN32_WINDOWS:
+      begin
+        // get Windows folder
+        SetLength(winini,MAX_PATH+1);
+        SetLength(winini,GetWindowsDirectory(@winini[1],MAX_PATH+1));
+
+        if(winini <> '') then begin
+          if(winini[length(winini)] <> '\') then
+            winini := winini + '\';
+          winini   := winini + 'wininit.ini';
+
+          // get short name of the given file
+          SetLength(ShortName,MAX_PATH+1);
+          SetLength(ShortName,
+            GetShortPathName(@aFilename[1],@ShortName[1],MAX_PATH+1));
+
+          if(ShortName <> '') then begin
+            // add it to "wininit.ini" to delete
+            // during next reboot
+            SetLength(ts,0);
+
+            {$I-}
+            // get old file´s content
+            AssignFile(f,winini);
+            ReSet(f);
+            if(IoResult = 0) then begin
+              while(not eof(f)) do begin
+                SetLength(ts,length(ts)+1);
+                ReadLn(f,ts[length(ts)-1]);
+
+                if(lstrcmpi('[rename]',pchar(ts[length(ts)-1])) = 0) then begin
+                  SetLength(ts,length(ts)+1);
+                  ts[length(ts)-1] := 'NUL='+ShortName;
+                end;
+              end;
+              CloseFile(f);
+            end;
+
+            if(length(ts) = 0) then begin
+              SetLength(ts,2);
+              ts[0] := '[rename]';
+              ts[1] := 'NUL='+ShortName;
+            end;
+
+            // re-create
+            ReWrite(f);
+            Result := (IoResult = 0);
+            if(Result) then begin
+              for i := 0 to length(ts) - 1 do
+                WriteLn(f,ts[i]);
+
+              CloseFile(f);
+            end;
+            {$I+}
+
+            SetLength(ts,0);
+          end;
+        end;
+      end;
+    // only 9x and NT are supported
+    else
+      exit;
+  end;
+end;
Index: /oup/current/TFileTypeRegistration/demo.txt
===================================================================
--- /oup/current/TFileTypeRegistration/demo.txt	(revision 10)
+++ /oup/current/TFileTypeRegistration/demo.txt	(revision 10)
@@ -0,0 +1,34 @@
+uses
+  ftypesAPI;
+
+var
+  ftr    : TFileTypeRegistration;
+  s:String;
+
+
+ftr := TFileTypeRegistration.Create;
+if(ftr <> nil) then begin
+  try
+    if(LOWORD(wp) = IDC_CREATEFOO) then begin
+      if(ftr.RegisterType('.foo','FooFile','FOO-File')) then begin
+        ftr.AddHandler('open','notepad.exe "%1"','Öffnen');
+        ftr.AddHandler('print','notepad.exe /p "%1"');
+        ftr.SetDefaultHandler;
+        ftr.AddNewFileSupport('.foo');
+      end;
+    end;
+    if(LOWORD(wp) = IDC_DELPRINTVERB) then begin
+      if(ftr.GetInternalKey('.foo') <> '') then begin
+        ftr.DeleteHandler('print');
+        ftr.SetDefaultHandler('open');
+      end;
+    end;
+    if(LOWORD(wp) = IDC_REMOVEFOO) then begin
+      s := ftr.GetInternalKey('.foo');
+      if(MessageBox(hwndDlg,pchar('Wollen Sie wirklich ".foo" und "' + s + '" entfernen?'), 'Frage',MB_YESNO or MB_DEFBUTTON2 or MB_ICONQUESTION) = ID_YES) then
+        ftr.UnregisterType('.foo');
+    end;
+  finally
+    ftr.Free;
+  end;
+end;
Index: /oup/current/TFileTypeRegistration/ftypesAPI.pas
===================================================================
--- /oup/current/TFileTypeRegistration/ftypesAPI.pas	(revision 10)
+++ /oup/current/TFileTypeRegistration/ftypesAPI.pas	(revision 10)
@@ -0,0 +1,544 @@
+// -----------------------------------------------------------------------------
+//
+// TFileTypeRegistration-Klasse (Win32-API)
+// Copyright (c) 2004 Mathias Simmack
+//
+// -----------------------------------------------------------------------------
+
+// -- Revision history ---------------------------------------------------------
+//
+//   * erste Version
+//
+// -----------------------------------------------------------------------------
+unit ftypesAPI;
+
+interface
+
+uses
+  Windows, ShlObj;
+
+type
+  TFileTypeRegistration = class
+    FRegConnector : HKEY;
+    FExtension,
+    FInternalName : string;
+    FVerb         : string;
+  public
+    constructor Create;
+    destructor Destroy; override;
+    function RegisterType(const Extension, InternalName: string;
+      Description: string = ''; IconFile: string = '';
+      IconIndex: integer = -1): boolean;
+    function UnregisterExtension(const Extension: string): boolean;
+    function UnregisterType(const Extension: string): boolean;
+    procedure UpdateShell;
+    function AddHandler(const HandlerVerb, CommandLine: string;
+      HandlerDescription: string = ''): boolean; overload;
+    function DeleteHandler(const HandlerVerb: string): boolean;
+    function SetDefaultHandler: boolean; overload;
+    function SetDefaultHandler(const HandlerVerb: string): boolean; overload;
+    function GetInternalKey(const Extension: string): string;
+    function AddNewFileSupport(const Extension: string): boolean;
+    function RemoveNewFileSupport(const Extension: string): boolean;
+
+    property Extension: string read FExtension;
+    property InternalName: string read FInternalName;
+    property CurrentVerb: string read FVerb;
+  end;
+
+
+implementation
+
+(* *****************************************************************************
+
+  Beispiel #1: Einen neuen Dateityp registrieren
+  ----------------------------------------------
+
+  ftr := TFileTypeRegistration.Create;
+  if(ftr <> nil) then
+  try
+    // die Dateiendung ".foo" registrieren, der interne Schlüssel
+    // lautet "FooFile", eine Beschreibung und eine Symboldatei
+    // sind ebenfalls angegeben
+    if(ftr.RegisterType('.foo','FooFile','FOO Description',
+      'c:\folder\icon.ico')) then
+    begin
+      // fügt den Handler "open" hinzu und verknüpft ihn mit dem
+      // Programm "foo.exe"
+      ftr.AddHandler('open','"c:\folder\foo.exe" "%1"');
+
+      // setzt den zuletzt benutzten Handler ("open" in dem Fall)
+      // als Standard
+      ftr.SetDefaultHandler;
+    end;
+
+    if(ftr.RegisterType('.foo','ThisIsNotTheFOOKey')) then
+    // Das ist kein Fehler! Obwohl hier der interne Name
+    // "ThisIsNotTheFOOKey" verwendet wird, benutzt die Funktion
+    // intern den bereits vorhandenen Schlüssel "FooFile" (s. oben).
+    begin
+      // zwei neue Handler werden registriert, ...
+      ftr.AddHandler('print','"c:\folder\foo.exe" /p "%1"');
+      ftr.AddHandler('edit','notepad.exe "%1"');
+
+      // ... & dank der überladenen Funktion "SetDefaultHandler"
+      // kann diesmal auch "print" als Standardhandler gesetzt
+      // werden
+      ftr.SetDefaultHandler('print');
+    end;
+  finally
+    ftr.Free;
+  end;
+
+
+  Beispiel #2: Einen neuen Typ mit einem vorhandenen Schlüssel
+  verknüpfen
+  ------------------------------------------------------------
+
+  Das Beispiel registriert die Endung ".foo" auf die gleiche
+  Weise wie Textdateien (.txt). Es wird einfach der interne
+  Schlüsselname ermittelt und für die Endung ".foo" gesetzt
+
+  ftr := TFileTypeRegistration.Create;
+  if(ftr <> nil) then
+  try
+    strInternalTextFileKey := ftr.GetInternalKey('.txt');
+    if(strInternalTextFileKey <> '') then
+      ftr.RegisterType('.foo',strInternalTextFileKey);
+  finally
+    ftr.Free;
+  end;
+
+
+  Beispiel #3: Einen Handler entfernen
+  ------------------------------------
+
+  ftr := TFileTypeRegistration.Create;
+  if(ftr <> nil) then
+  try
+    // den internen Schlüsselnamen des Typs ".foo" ermitteln, ...
+    if(ftr.GetInternalKey('.foo') <> '') then
+    // ... wobei das Ergebnis in dem Fall unwichtig ist, weil
+    // intern auch die Eigenschaft "FInternalName" gesetzt
+    // wird
+    begin
+      // den "print"-Handler entfernen, ...
+      ftr.DeleteHandler('print');
+
+      // ... & den Standardhandler aktualisieren
+      ftr.SetDefaultHandler('open');
+    end;
+  finally
+    ftr.Free;
+  end;
+
+
+  Beispiel #4: Nur eine Dateiendung entfernen
+  -------------------------------------------
+
+  In diesem Fall wird lediglich die Endung ".foo" entfernt. Der
+  evtl. vorhandene interne Schlüssel bleibt bestehen. Das ist
+  für das Beispiel #2 nützlich, wenn die Endung ".foo" entfernt
+  werden soll, intern aber mit den Textdateien verlinkt ist, die
+  ja im Normalfall nicht entfernt werden dürfen/sollten.
+
+    ftr.UnregisterExtension('.foo');
+
+
+  Beispiel #5: Den kompletten Dateityp entfernen
+  ----------------------------------------------
+
+  Dieses Beispiel entfernt dagegen den kompletten Dateityp,
+  inkl. des evtl. vorhandenen internen Schlüssels (vgl. mit
+  Beispiel #4).
+
+    ftr.UnregisterType('.foo');
+
+  Bezogen auf Beispiel #2 wäre das die fatale Lösung, weil dadurch
+  zwar die Endung ".foo" deregistriert wird, gleichzeitig wird
+  aber auch der intern verwendete Schlüssel der Textdateien
+  gelöscht.
+
+  ALSO, VORSICHT!!!
+
+***************************************************************************** *)
+
+
+//
+// Admin-Rechte sind erforderlich (Funktion von NicoDE)
+//
+{$INCLUDE IsAdmin.inc}
+{$INCLUDE SysUtils.inc}
+
+
+// -----------------------------------------------------------------------------
+//
+// Registry
+//
+// -----------------------------------------------------------------------------
+
+function RegWriteSubKeyVal(const parent: HKEY; SubKeyName: string;
+  ValueName, Value: string): boolean;
+var
+  tmp    : HKEY;
+begin
+  Result := false;
+  if(parent = INVALID_HANDLE_VALUE) or
+    (SubKeyName = '') then exit;
+
+  if(RegCreateKeyEx(parent,pchar(SubKeyName),0,nil,0,KEY_READ or KEY_WRITE,
+    nil,tmp,nil) = ERROR_SUCCESS) then
+  try
+    Result := (RegSetValueEx(tmp,pchar(ValueName),0,REG_SZ,pchar(Value),
+      length(Value) + 1) = ERROR_SUCCESS);
+  finally
+    RegCloseKey(tmp);
+  end;
+end;
+
+function RegReadSubKeyStr(const parent: HKEY; SubKeyName: string;
+  ValueName: string): string;
+var
+  tmp     : HKEY;
+  lpData,
+  dwLen   : dword;
+begin
+  Result  := '';
+  if(parent = INVALID_HANDLE_VALUE) or
+    (SubKeyName = '') then exit;
+
+  if(RegOpenKeyEx(parent,pchar(SubKeyName),0,KEY_READ,
+    tmp) = ERROR_SUCCESS) then
+  try
+    lpData := REG_NONE;
+    dwLen  := 0;
+    if(RegQueryValueEx(tmp,pchar(ValueName),nil,@lpData,nil,
+         @dwLen) = ERROR_SUCCESS) and
+      (lpData in[REG_SZ,REG_EXPAND_SZ]) and
+      (dwLen > 0) then
+    begin
+      SetLength(Result,dwLen);
+
+      if(RegQueryValueEx(tmp,pchar(ValueName),nil,@lpData,
+           @Result[1],@dwLen) = ERROR_SUCCESS) then
+        SetLength(Result,dwLen - 1)
+      else
+        Result := '';
+    end;
+  finally
+    RegCloseKey(tmp);
+  end;
+end;
+
+function RegKeyExists(const parent: HKEY; KeyName: string): boolean;
+var
+  tmp    : HKEY;
+begin
+  Result := (RegOpenKeyEx(parent,pchar(KeyName),0,KEY_READ,tmp) =
+    ERROR_SUCCESS);
+  if(Result) then RegCloseKey(tmp);
+end;
+
+function RegDeleteWholeKey(parent: HKEY; KeyName: string): boolean;
+var
+  reg       : HKEY;
+  dwSubkeys : dword;
+  dwLen     : dword;
+  i         : integer;
+  buf       : array[0..MAX_PATH]of char;
+begin
+  if(RegOpenKeyEx(parent,pchar(KeyName),0,KEY_READ,reg) = ERROR_SUCCESS) then
+  try
+    if(RegQueryInfoKey(reg,nil,nil,nil,@dwSubKeys,nil,
+      nil,nil,nil,nil,nil,nil) = ERROR_SUCCESS) and
+      (dwSubKeys > 0) then
+    for i := 0 to dwSubKeys - 1 do begin
+      ZeroMemory(@buf,sizeof(buf));
+      dwLen   := MAX_PATH;
+
+      if(RegEnumKeyEx(reg,i,buf,dwLen,nil,nil,nil,nil) = ERROR_SUCCESS) and
+        (dwLen > 0) then
+      RegDeleteWholeKey(reg,buf);
+    end;
+  finally
+    RegCloseKey(reg);
+  end;
+
+  Result := (RegDeleteKey(parent,pchar(KeyName)) = ERROR_SUCCESS);
+end;
+
+
+// -----------------------------------------------------------------------------
+//
+// TFileTypeRegistration-Klasse
+//
+// -----------------------------------------------------------------------------
+
+constructor TFileTypeRegistration.Create;
+var
+  key: HKEY;
+  sub: PChar;
+begin
+  FExtension    := '';
+  FInternalName := '';
+  FVerb         := '';
+
+  // Zugriff auf die Registry, & HKEY_CLASSES_ROOT
+  // als Root setzen
+  if(WVersion='9X') or IsAdmin then begin
+    key:=HKEY_CLASSES_ROOT;
+    sub:=nil;
+  end else begin
+    key:=HKEY_CURRENT_USER;
+    sub:=PChar('SOFTWARE\Classes');
+  end;
+
+  if RegOpenKeyEx(key,sub,0,KEY_ALL_ACCESS, FRegConnector) <> ERROR_SUCCESS then
+    FRegConnector := INVALID_HANDLE_VALUE;
+end;
+
+destructor TFileTypeRegistration.Destroy;
+begin
+  if(FRegConnector <> INVALID_HANDLE_VALUE) then
+    RegCloseKey(FRegConnector);
+end;
+
+function TFileTypeRegistration.RegisterType(const Extension,
+  InternalName: string; Description: string = ''; IconFile: string = '';
+  IconIndex: integer = -1): boolean;
+var
+  strDummy : string;
+begin
+  // Standardergebnis
+  Result         := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // ist dieser Typ evtl. schon registriert?
+  strDummy := self.GetInternalKey(Extension);
+
+  // Nein. :o)
+  if(strDummy = '') then strDummy := InternalName;
+
+  // den Schlüssel mit der Dateiendung anlegen oder aktualisieren
+  Result := RegWriteSubKeyVal(FRegConnector,Extension,'',strDummy);
+  if(not Result) then exit;
+
+  // den internen Schlüssel öffnen
+  if(Result) then
+  begin
+    // Beschreibung anlegen
+    if(Description <> '') then
+      RegWriteSubKeyVal(FRegConnector,strDummy,'',Description);
+
+    // Symbol zuweisen (Datei muss existieren!)
+    if(IconFile <> '') and
+      (fileexists(IconFile)) then
+    begin
+      if(IconIndex <> -1) then
+        RegWriteSubKeyVal(FRegConnector,strDummy + '\DefaultIcon',
+          '',Format('%s,%d',[IconFile,IconIndex]))
+      else
+        RegWriteSubKeyVal(FRegConnector,strDummy + '\DefaultIcon',
+          '',IconFile);
+    end;
+  end;
+
+  // Systemsymbole aktualisieren
+  self.UpdateShell;
+
+  // Properties aktualisieren
+  if(Result) then
+  begin
+    FExtension    := Extension;
+    FInternalName := strDummy;
+  end;
+end;
+
+function TFileTypeRegistration.UnregisterExtension(const Extension: string):
+  boolean;
+begin
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // die Endung entfernen
+  Result := (RegKeyExists(FRegConnector,Extension)) and
+    (RegDeleteWholeKey(FRegConnector,Extension));
+
+  // Systemsymbole aktualisieren
+  self.UpdateShell;
+end;
+
+function TFileTypeRegistration.UnregisterType(const Extension: string):
+  boolean;
+var
+  strDummy : string;
+begin
+  Result   := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // den internen Namen der Endung ermitteln
+  strDummy := self.GetInternalKey(Extension);
+
+  // die Endung entfernen (s. "UnregisterExtension"), ...
+  Result   := (self.UnregisterExtension(Extension)) and
+  // ... & den internen Schlüssel löschen
+    (strDummy <> '') and
+    (RegKeyExists(FRegConnector,strDummy)) and
+    (RegDeleteWholeKey(FRegConnector,strDummy));
+
+  // Systemsymbole aktualisieren
+  self.UpdateShell;
+end;
+
+procedure TFileTypeRegistration.UpdateShell;
+begin
+  SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,nil,nil);
+end;
+
+
+const
+  ShellKey = '%s\shell\%s';
+
+function TFileTypeRegistration.AddHandler(const HandlerVerb,
+  CommandLine: string; HandlerDescription: string = ''): boolean;
+begin
+  // Standardergebnis
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (FInternalName = '') or
+    (HandlerVerb = '') or
+    (CommandLine = '') then exit;
+
+  // der interne Schlüssel muss existieren
+  if(RegKeyExists(FRegConnector,FInternalName)) then
+  begin
+    // den Handler (= Verb) erzeugen
+    Result := RegWriteSubKeyVal(FRegConnector,
+      Format(ShellKey + '\command',[FInternalName,HandlerVerb]),
+      '',
+      CommandLine);
+
+    // ggf. Beschreibung für Handler setzen
+    if(HandlerDescription <> '') then
+      RegWriteSubKeyVal(FRegConnector,
+        Format(ShellKey,[FInternalName,HandlerVerb]),
+        '',
+        HandlerDescription);
+  end;
+
+  // interne Eigenschaft anpassen (für "SetDefaultHandler")
+  if(Result) then
+    FVerb := HandlerVerb;
+end;
+
+function TFileTypeRegistration.DeleteHandler(const HandlerVerb: string):
+  boolean;
+begin
+  // Standardergebnis
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (FInternalName = '') or
+    (HandlerVerb = '') then exit;
+
+  // Handlerschlüssel entfernen (sofern vorhanden)
+  Result :=
+    (RegKeyExists(FRegConnector,
+       Format(ShellKey,[FInternalName,HandlerVerb]))) and
+    (RegDeleteWholeKey(FRegConnector,
+       Format(ShellKey,[FInternalName,HandlerVerb])));
+end;
+
+function TFileTypeRegistration.SetDefaultHandler: boolean;
+begin
+  if(FInternalName <> '') and (FVerb <> '') then
+    Result := self.SetDefaultHandler(FVerb)
+  else
+    Result := false;
+end;
+
+function TFileTypeRegistration.SetDefaultHandler(const HandlerVerb: string):
+  boolean;
+begin
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (FInternalName = '') or
+    (HandlerVerb = '') then exit;
+
+  // interner Schlüssel muss existieren, ...
+  if(RegKeyExists(FRegConnector,FInternalName)) and
+  // ... & Handler muss existieren, ...
+    (RegKeyExists(FRegConnector,
+       Format(ShellKey,[FInternalName,HandlerVerb]))) then
+  begin
+  // ... dann den Handler als Standard eintragen
+    Result := RegWriteSubKeyVal(FRegConnector,FInternalName + '\shell',
+      '',HandlerVerb);
+  end;
+end;
+
+function TFileTypeRegistration.GetInternalKey(const Extension: string): string;
+begin
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // einen evtl. eingestellten internen Namen zurücksetzen
+  FInternalName   := '';
+
+  // den Schlüssel der Dateiendung öffnen, ...
+  if(RegKeyExists(FRegConnector,Extension)) then
+    FInternalName := RegReadSubKeyStr(FRegConnector,Extension,'');
+
+  // ... als Funktionsergebnis zurückliefern
+  if(not RegKeyExists(FRegConnector,FInternalName)) then
+    FInternalName := '';
+
+  Result := FInternalName;
+end;
+
+
+function TFileTypeRegistration.AddNewFileSupport(const Extension: string):
+  boolean;
+var
+  Description : string;
+begin
+  Result      := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  // interne Beschreibung des Typs ermitteln
+  if(self.GetInternalKey(Extension) <> '') then
+    Description := RegReadSubKeyStr(FRegConnector,FInternalName,'')
+  else
+    Description := '';
+
+  // die Beschreibung darf keine Leerzeichen enthalten, weil sie
+  // als Referenz für den neuen Dateinamen verwendet wird, ...
+  if(pos(#32,Description) > 0) or
+  // ... & sie darf auch nicht leer sein
+    (Description = '') then exit;
+
+  Result := (RegKeyExists(FRegConnector,Extension)) and
+    (RegWriteSubKeyVal(FRegConnector,Extension + '\ShellNew','NullFile',''));
+end;
+
+function TFileTypeRegistration.RemoveNewFileSupport(const Extension: string):
+  boolean;
+begin
+  Result := false;
+  if(FRegConnector = INVALID_HANDLE_VALUE) or
+    (Extension = '') or
+    (Extension[1] <> '.') then exit;
+
+  Result := (RegKeyExists(FRegConnector,Extension + '\ShellNew')) and
+    (RegDeleteWholeKey(FRegConnector,Extension + '\ShellNew'));
+end;
+
+end.
Index: /oup/current/Unit10_leveldb.dfm
===================================================================
--- /oup/current/Unit10_leveldb.dfm	(revision 10)
+++ /oup/current/Unit10_leveldb.dfm	(revision 10)
@@ -0,0 +1,61 @@
+object Form10: TForm10
+  Left = 0
+  Top = 0
+  BorderStyle = bsNone
+  Caption = 'Creating DB'
+  ClientHeight = 89
+  ClientWidth = 400
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poScreenCenter
+  PixelsPerInch = 96
+  TextHeight = 13
+  object group_progress: TGroupBox
+    Left = 0
+    Top = 0
+    Width = 400
+    Height = 89
+    Caption = 'Progress ...'
+    TabOrder = 0
+    object lbl_progress: TLabel
+      Left = 2
+      Top = 32
+      Width = 396
+      Height = 17
+      Align = alTop
+      AutoSize = False
+    end
+    object lbl_estimation: TLabel
+      Left = 2
+      Top = 49
+      Width = 396
+      Height = 17
+      Align = alTop
+      AutoSize = False
+      Caption = 'Estimated finishing time:'
+    end
+    object progress: TProgressBar
+      Left = 2
+      Top = 15
+      Width = 396
+      Height = 17
+      Align = alTop
+      Smooth = True
+      TabOrder = 0
+    end
+    object btn_abortok: TButton
+      Left = 3
+      Top = 64
+      Width = 60
+      Height = 22
+      Caption = 'Abort...'
+      TabOrder = 1
+      OnClick = btn_abortokClick
+    end
+  end
+end
Index: /oup/current/Unit10_leveldb.pas
===================================================================
--- /oup/current/Unit10_leveldb.pas	(revision 10)
+++ /oup/current/Unit10_leveldb.pas	(revision 10)
@@ -0,0 +1,1185 @@
+UNIT Unit10_leveldb;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, ComCtrls, StdCtrls, StrUtils;
+
+TYPE
+  TForm10 = Class(TForm)
+    group_progress: TGroupBox;
+    progress: TProgressBar;
+    lbl_progress: TLabel;
+    btn_abortok: TButton;
+    lbl_estimation: TLabel;
+    PROCEDURE btn_abortokClick(Sender: TObject);
+  PRIVATE
+    PROCEDURE HandleFile(ext:String; fileid:LongWord; dir_dat2db:Boolean);
+    PROCEDURE stop_convert;
+  PUBLIC
+    PROCEDURE CreateDatabase(source,target:String);
+    PROCEDURE CreateLevel(source,target:String);
+  END;
+
+
+VAR
+  Form10: TForm10;
+
+IMPLEMENTATION
+{$R *.dfm}
+USES ABSMain, ABSDecUtil, Unit1_main, Unit2_functions, Unit3_data, Unit6_imgfuncs, Unit9_data_structures, Unit15_Classes;
+
+TYPE
+  THandler=PROCEDURE(fileid:LongWord; dir_dat2db:Boolean);
+  TConvertHandlers=RECORD
+    Ext:String[4];
+    needed:Boolean;
+    Handler:THandler;
+  END;
+VAR
+  ConvertHandlers:Array OF TConvertHandlers;
+  loaded_filename:String;
+  converting:Boolean=False;
+  abort:Boolean=False;
+  DataBase:TABSDatabase;
+  Query:TABSQuery;
+  MimeCoder: TStringFormat_MIME64;
+VAR
+  DatHeader:THeader;
+  FilesHeader:TFilesMap;
+  NamedFilesHeader:TNamedFilesMap;
+  ExtensionsHeader:TExtensionsMap;
+  Stream_Body,Stream_Names:TMemoryStream;
+  Stream_Dat,Stream_Raw,Stream_Sep:TFileStream;
+
+PROCEDURE TForm10.CreateLevel(source,target:String);
+  VAR
+    files:LongWord;
+    
+    i,j:LongWord;
+    temps,temps2:String;
+    data,rawdata:Tdata;
+    absolutebegintime,begintime:Double;
+    step:Byte;
+    rawlist:TRawList;
+    extlist:TExtensionsMap;
+    fileinfo:TFileInfo;
+    datlinks:TDatLinks;
+    OniImage:TOniImage;
+    levelid:LongWord;
+  CONST
+    steps:Byte=3;
+  PROCEDURE DoStep(stepname:String);
+    BEGIN
+      Inc(step);
+      IF stepname<>'FIN' THEN
+        group_progress.Caption:='Creating Dat (Step '+IntToStr(step)+'/'+IntToStr(steps)+': '+stepname+')'
+      ELSE
+        group_progress.Caption:='Creating Dat (FINISHED)';
+    END;
+  BEGIN
+
+//
+// FILE EXISTS CHECK FÜR DAT/RAW/SEP!!!
+//
+
+    IF NOT CreateDataConnection(source,ODB_ADB) THEN BEGIN
+      ShowMessage('Could not connect to .oldb-file');
+      Exit;
+    END;
+    levelid:=OniDataConnection.LevelInfo.LevelNumber;
+    levelid:=(levelid*2)*256*256*256 + $01;
+    OniImage:=TOniImage.Create;
+
+    absolutebegintime:=Time;
+
+    Form10.Visible:=True;
+    Form1.Visible:=False;
+    step:=0;
+    converting:=True;
+    abort:=False;
+    btn_abortok.Caption:='&Abort...';
+    btn_abortok.Default:=False;
+    absolutebegintime:=Time;
+
+    Stream_Body:=TMemoryStream.Create;
+    Stream_Names:=TMemoryStream.Create;
+    Stream_Dat:=TFileStream.Create(target,fmCreate);
+    Stream_Raw:=TFileStream.Create(AnsiReplaceStr(target,'.dat','.raw'),fmCreate);
+    IF OniDataConnection.OSisMac THEN
+      Stream_Sep:=TFileStream.Create(AnsiReplaceStr(target,'.dat','.sep'),fmCreate);
+
+    DoStep('Creating header');
+    progress.Position:=0;
+    lbl_progress.Caption:='';
+    lbl_estimation.Caption:='Estimated finishing time: unknown';
+    Application.ProcessMessages;
+
+    NamedFilesHeader:=TOniDataADB(OniDataConnection).GetNamedFilesMap;
+    extlist:=OniDataConnection.GetExtendedExtensionsList;
+    FOR i:=0 TO High(DatHeader.Ident) DO
+      DatHeader.Ident[i]:=OniDataConnection.LevelInfo.Ident[i];
+    DatHeader.Files:=OniDataConnection.GetFilesCount;
+    DatHeader.NamedFiles:=Length(NamedFilesHeader);
+    DatHeader.Extensions:=Length(extlist);
+    DatHeader.DataAddr:=0;
+    DatHeader.DataSize:=0;
+    DatHeader.NamesAddr:=0;
+    DatHeader.NamesSize:=0;
+    FOR i:=0 TO High(DatHeader.Ident2) DO
+      DatHeader.Ident2[i]:=0;
+    SetLength(FilesHeader, DatHeader.Files);
+    SetLength(ExtensionsHeader, DatHeader.Extensions);
+
+    DoStep('Writing extensions-header');
+    progress.Max:=Length(OniDataConnection.GetExtensionsList);
+    Application.ProcessMessages;
+
+    FOR i:=0 TO High(ExtensionsHeader) DO BEGIN
+      ExtensionsHeader[i].Ident:=extlist[i].Ident;
+      ExtensionsHeader[i].Extension:=extlist[i].Extension;
+      SetLength(temps,4);
+      FOR j:=0 TO 3 DO
+        temps[j+1]:=ExtensionsHeader[i].Extension[3-j];
+      ExtensionsHeader[i].ExtCount:=Length(OniDataConnection.GetFilesList(temps,'',False));
+      progress.Position:=i+1;
+      lbl_progress.Caption:='Extensions done: '+IntToStr(i+1)+'/'+IntToStr(Length(extlist));
+      Application.ProcessMessages;
+    END;
+
+    DoStep('Storing files-data');
+    progress.Position:=0;
+    progress.Max:=DatHeader.Files;
+    lbl_progress.Caption:='';
+    lbl_estimation.Caption:='Estimated finishing time: unknown';
+    Application.ProcessMessages;
+
+    begintime:=Time;
+    FOR i:=0 TO DatHeader.Files-1 DO BEGIN
+      fileinfo:=OniDataConnection.GetFileInfo(i);
+      FOR j:=0 TO 3 DO
+        FilesHeader[i].Extension[j]:=fileinfo.Extension[4-j];
+      IF fileinfo.Size>0 THEN BEGIN
+//        DatLinks:=;
+        FilesHeader[i].DataAddr:=Stream_Body.Size+8;
+        data:=OniDataConnection.LoadDatFile(i);
+        data[4]:=(levelid       ) AND $FF;
+        data[5]:=(levelid SHR  8) AND $FF;
+        data[6]:=(levelid SHR 16) AND $FF;
+        data[7]:=(levelid SHR 24) AND $FF;     
+
+        IF (Pos(UpperCase(fileinfo.Extension),UpperCase(raws)) MOD 4)=1 THEN BEGIN
+          rawlist:=OniDataConnection.GetRawList(i);
+          IF Length(rawlist)>0 THEN BEGIN
+            FOR j:=0 TO High(rawlist) DO BEGIN
+              IF rawlist[j].raw_size>0 THEN BEGIN
+                IF (UpperCase(fileinfo.Extension)='TXMP') AND ((data[$88] AND $01)>0) THEN BEGIN
+                  OniImage.LoadFromTXMP(i);
+                  OniImage.GetMipMappedImage(rawdata);
+                  rawlist[j].raw_size:=OniImage.GetImageDataSize(true);
+                  data[$90]:=$08;
+                  data[$89]:=32;
+{                  if data[$90]<>OniImage.StoreType then begin
+                    data[$90]:=OniImage.StoreType;
+                    data[$89]:=(data[$89] and $CF) or $20;
+                  end;
+}                END ELSE BEGIN
+                  SetLength(rawdata,rawlist[j].raw_size);
+                  OniDataConnection.LoadRawFile(i,rawlist[j].src_offset,@rawdata[0]);
+                END;
+//                data[$88]:=data[$88] and $FE;
+
+                IF rawlist[j].loc_sep THEN BEGIN
+                  rawlist[j].raw_addr:=Stream_Sep.Size;
+                  Stream_Sep.Write(rawdata[0],Length(rawdata));
+                END ELSE BEGIN
+                  rawlist[j].raw_addr:=Stream_Raw.Size;
+                  Stream_Raw.Write(rawdata[0],Length(rawdata));
+                END;
+              END ELSE rawlist[j].raw_addr:=0;
+              data[rawlist[j].src_offset+0]:=(rawlist[j].raw_addr       ) AND $FF;
+              data[rawlist[j].src_offset+1]:=(rawlist[j].raw_addr SHR  8) AND $FF;
+              data[rawlist[j].src_offset+2]:=(rawlist[j].raw_addr SHR 16) AND $FF;
+              data[rawlist[j].src_offset+3]:=(rawlist[j].raw_addr SHR 24) AND $FF;
+            END;
+          END;
+        END;
+
+        Stream_Body.Write(data[0],Length(data));
+//
+      END ELSE
+        FilesHeader[i].DataAddr:=0;
+      IF Length(fileinfo.Name)>0 THEN BEGIN
+        FilesHeader[i].NameAddr:=Stream_Names.Size;
+        temps:=fileinfo.Extension+fileinfo.Name+Chr(0);
+        Stream_Names.Write(temps[1],Length(temps)); 
+      END ELSE
+        FilesHeader[i].NameAddr:=0;
+      FilesHeader[i].FileSize:=fileinfo.Size;
+      FilesHeader[i].FileType:=fileinfo.FileType;
+
+      IF ( (i MOD 25)=0 ) AND (i>=100) THEN
+        lbl_estimation.Caption:='Estimated finishing time: '+TimeToStr((Time-begintime)/i*progress.Max+begintime);
+      progress.Position:=i+1;
+      lbl_progress.Caption:='Files done: '+IntToStr(i+1)+'/'+IntToStr(progress.Max);
+      Application.ProcessMessages;
+    END;
+
+    Stream_Dat.Write(DatHeader,SizeOf(DatHeader));
+    FOR i:=0 TO High(FilesHeader) DO
+      Stream_Dat.Write(FilesHeader[i],SizeOf(FilesHeader[i]));
+    FOR i:=0 TO High(NamedFilesHeader) DO
+      Stream_Dat.Write(NamedFilesHeader[i],SizeOf(NamedFilesHeader[i]));
+    FOR i:=0 TO High(ExtensionsHeader) DO
+      Stream_Dat.Write(ExtensionsHeader[i],SizeOf(ExtensionsHeader[i]));
+
+    DatHeader.DataSize:=Stream_Body.Size;
+    DatHeader.NamesSize:=Stream_Names.Size;
+    DatHeader.DataAddr:=Stream_Dat.Size;
+    Stream_Body.Seek(0,soFromBeginning);
+    Stream_Dat.CopyFrom(Stream_Body,Stream_Body.Size);
+    DatHeader.NamesAddr:=Stream_Dat.Size;
+    Stream_Names.Seek(0,soFromBeginning);
+    Stream_Dat.CopyFrom(Stream_Names,Stream_Names.Size);
+
+    Stream_Dat.Seek(0,soFromBeginning);
+    Stream_Dat.Write(DatHeader,SizeOf(DatHeader)); 
+
+    Stream_Dat.Free;
+    Stream_Body.Free;
+    Stream_Names.Free;
+    Stream_Raw.Free;
+    IF OniDataConnection.OSisMac THEN
+      Stream_Sep.Free;
+
+    progress.Position:=progress.Max;
+    lbl_progress.Caption:='Files done: '+IntToStr(progress.Max)+'/'+IntToStr(progress.Max);
+    lbl_estimation.Caption:='FINISHED (duration: '+TimeToStr(Time-absolutebegintime)+')';
+
+    DoStep('FIN');
+    btn_abortok.Caption:='&OK';
+    btn_abortok.Default:=True;
+
+    OniImage.Free;
+
+    converting:=False;
+
+    CloseDataConnection;
+  END;
+
+PROCEDURE TForm10.HandleFile;
+  VAR
+    i:Byte;
+  BEGIN
+    FOR i:=1 TO Length(ConvertHandlers) DO
+      IF UpperCase(ConvertHandlers[i].Ext)=UpperCase(ext) THEN
+        IF ConvertHandlers[i].needed THEN BEGIN
+          ConvertHandlers[i].Handler(fileid, dir_dat2db);
+          Break;
+        END ELSE
+          Break;
+  END;
+
+PROCEDURE TForm10.CreateDatabase(source,target:String);
+  VAR
+    i,j:LongWord;
+    temps,temps2:String;
+    data:Tdata;
+    absolutebegintime,begintime:Double;
+    step:Byte;
+    rawlist:TRawList;
+    extlist:TExtensionsMap;
+    fileinfo:TFileInfo;
+  CONST
+    steps:Byte=4;
+  PROCEDURE DoStep(stepname:String);
+    BEGIN
+      Inc(step);
+      IF stepname<>'FIN' THEN
+        group_progress.Caption:='Creating DB (Step '+IntToStr(step)+'/'+IntToStr(steps)+': '+stepname+')'
+      ELSE
+        group_progress.Caption:='Creating DB (FINISHED)';
+    END;
+  BEGIN
+    IF NOT CreateDataConnection(source,ODB_Dat) THEN BEGIN
+      ShowMessage('Could not connect to .dat-file');
+      Exit;
+    END ELSE BEGIN
+      TOniDataDat(OniDataConnection).UnloadWhenUnused:=False;
+    END;
+
+    Form10.Visible:=True;
+    Form1.Visible:=False;
+    step:=0;
+    converting:=True;
+    abort:=False;
+    btn_abortok.Caption:='&Abort...';
+    btn_abortok.Default:=False;
+    loaded_filename:=target;
+
+    absolutebegintime:=Time;
+
+    DataBase:=TABSDatabase.Create(Self);
+    DataBase.DatabaseName:='OLDB';
+    DataBase.DatabaseFileName:=target;
+    DataBase.CreateDatabase;
+
+    DoStep('Creating tables');
+    progress.Position:=0;
+    lbl_progress.Caption:='';
+    lbl_estimation.Caption:='Estimated finishing time: unknown';
+    Application.ProcessMessages;
+
+    Query:=TABSQuery.Create(Self);
+    Query.DatabaseName:='OLDB';
+    Query.SQL.Text:='CREATE TABLE globals  ( id AUTOINC PRIMARY KEY, name STRING(128), value STRING(128) );';
+    Query.ExecSQL;
+    Query.SQL.Text:='CREATE TABLE linkmap  ( id AUTOINC PRIMARY KEY, src_id INTEGER, src_link_offset INTEGER, target_id INTEGER );';
+    Query.ExecSQL;
+    Query.SQL.Text:='CREATE TABLE rawmap  ( id AUTOINC PRIMARY KEY, src_id INTEGER, src_link_offset INTEGER, sep BOOLEAN, size INTEGER, data BLOB BlobCompressionMode 9 BlobBlockSize 1024 BlobCompressionAlgorithm ZLib );';
+//    Query.SQL.Text:='CREATE TABLE rawmap  ( id AUTOINC PRIMARY KEY, src_id INTEGER, src_link_offset INTEGER, size INTEGER, data BLOB BlobCompressionAlgorithm None );';
+    Query.ExecSQL;
+    Query.SQL.Text:='CREATE TABLE datfiles  ( id INTEGER PRIMARY KEY, extension CHAR(4), name STRING(128), contenttype INTEGER, size INTEGER, data BLOB BlobCompressionMode 9 BlobBlockSize 1024 BlobCompressionAlgorithm ZLib );';
+//    Query.SQL.Text:='CREATE TABLE datfiles  ( id INTEGER PRIMARY KEY, extension CHAR(4), name STRING(128), contenttype INTEGER, size INTEGER, data BLOB BlobCompressionAlgorithm None );';
+    Query.ExecSQL;
+    Query.SQL.Text:='CREATE TABLE extlist  ( id AUTOINC PRIMARY KEY, ext CHAR(4), ident CHAR(16) );';
+    Query.ExecSQL;
+
+    Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("dbversion","'+dbversion+'");';
+    Query.ExecSQL;
+    SetLength(data,Length(OniDataConnection.LevelInfo.Ident));
+    FOR i:=0 TO High(OniDataConnection.LevelInfo.Ident) DO data[i]:=OniDataConnection.LevelInfo.Ident[i];
+    temps:=CreateHexString(data,True);
+    Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("ident","'+temps+'");';
+    Query.ExecSQL;
+    Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("lvl","'+IntToStr(OniDataConnection.LevelInfo.LevelNumber)+'");';
+    Query.ExecSQL;
+    IF OniDataConnection.OSisMAC THEN
+      Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("os","MAC");'
+    ELSE
+      Query.SQL.Text:='INSERT INTO globals (name,value) VALUES ("os","PC");';
+    Query.ExecSQL;
+
+    DoStep('Writing extensionslist');
+    progress.Max:=Length(OniDataConnection.GetExtensionsList);
+    Application.ProcessMessages;
+
+    extlist:=OniDataConnection.GetExtendedExtensionsList;
+    FOR i:=0 TO High(extlist) DO BEGIN
+      SetLength(data,Length(extlist[i].Ident));
+      FOR j:=0 TO High(extlist[i].Ident) DO data[j]:=extlist[i].Ident[j];
+      temps:=CreateHexString(data,True);
+      temps2:=extlist[i].Extension[3]+extlist[i].Extension[2]+extlist[i].Extension[1]+extlist[i].Extension[0];
+      Query.SQL.Text:='INSERT INTO extlist (ext,ident) VALUES ("'+temps2+'","'+temps+'");';
+      Query.ExecSQL;
+      progress.Position:=i;
+      lbl_progress.Caption:='Extensions done: '+IntToStr(i)+'/'+IntToStr(Length(extlist));
+      Application.ProcessMessages;
+      IF abort THEN BEGIN
+        stop_convert;
+        Exit;
+      END;
+    END;
+    lbl_progress.Caption:='';
+
+    progress.Position:=0;
+    lbl_progress.Caption:='Files done: '+IntToStr(0)+'/'+IntToStr(OniDataConnection.GetFilesCount);
+    lbl_estimation.Caption:='Estimated finishing time: unknown';
+
+    DoStep('Loading .dat into memory');
+    Application.ProcessMessages;
+
+    progress.Max:=OniDataConnection.GetFilesCount;
+    begintime:=Time;
+    DoStep('Writing .dat-fileslist');
+    Application.ProcessMessages;
+
+    Database.StartTransaction;
+    FOR i:=0 TO OniDataConnection.GetFilesCount-1 DO BEGIN
+      fileinfo:=OniDataConnection.GetFileInfo(i);
+      IF (fileinfo.FileType AND $02)=0 THEN BEGIN
+        mimecoder:=TStringFormat_MIME64.Create;
+        data:=OniDataConnection.LoadDatFile(i);
+        Query.SQL.Text:='INSERT INTO datfiles (id,extension,name,contenttype,size,data) VALUES ('+IntToStr(i)+',"'+fileinfo.Extension+'","'+fileinfo.Name+'","'+IntToHex(fileinfo.FileType,8)+'",'+IntToStr(fileinfo.Size)+',MimeToBin("'+MimeCoder.StrTo(@data[0], Length(data))+'") );';
+        Query.ExecSQL;
+        mimecoder.Free;
+
+        rawlist:=OniDataConnection.GetRawList(i);
+        IF Length(rawlist)>0 THEN BEGIN
+          FOR j:=0 TO High(rawlist) DO BEGIN
+            IF rawlist[j].raw_size>0 THEN BEGIN
+              SetLength(data, rawlist[j].raw_size);
+              OniDataConnection.LoadRawFile(i,rawlist[j].src_offset,data);
+              mimecoder:=TStringFormat_MIME64.Create;
+              Query.SQL.Text:='INSERT INTO rawmap (src_id,src_link_offset,sep,size,data) VALUES ('+IntToStr(i)+','+IntToStr(rawlist[j].src_offset)+','+BoolToStr(rawlist[j].loc_sep)+','+IntToStr(rawlist[j].raw_size)+',MimeToBin("'+MimeCoder.StrTo(@data[0], rawlist[j].raw_size)+'") );';
+              Query.ExecSQL;
+              mimecoder.Free;
+            END ELSE BEGIN
+              Query.SQL.Text:='INSERT INTO rawmap (src_id,src_link_offset,sep,size) VALUES ('+IntToStr(i)+','+IntToStr(rawlist[j].src_offset)+','+BoolToStr(rawlist[j].loc_sep)+',0);';
+              Query.ExecSQL;
+            END;
+          END;
+        END;
+
+        HandleFile(fileinfo.Extension,i,True);
+      END ELSE BEGIN
+        Query.SQL.Text:='INSERT INTO datfiles (id,extension,name,contenttype,size) VALUES ('+IntToStr(i)+',"'+fileinfo.Extension+'","'+fileinfo.Name+'","'+IntToHex(fileinfo.FileType,8)+'",0);';
+        Query.ExecSQL;
+      END;
+      IF ( (i MOD 100)=0 ) AND (i>0) THEN BEGIN
+        Database.Commit(False);
+        Database.StartTransaction;
+      END;
+      IF ( (i MOD 25)=0 ) AND (i>=100) THEN
+        lbl_estimation.Caption:='Estimated finishing time: '+TimeToStr((Time-begintime)/i*progress.Max+begintime);
+      progress.Position:=i;
+      lbl_progress.Caption:='Files done: '+IntToStr(i)+'/'+IntToStr(progress.Max);
+      Application.ProcessMessages;
+      IF abort THEN BEGIN
+        stop_convert;
+        Exit;
+      END;
+    END;
+    Database.Commit(False);
+    progress.Position:=progress.Max;
+    lbl_progress.Caption:='Files done: '+IntToStr(progress.Max)+'/'+IntToStr(progress.Max);
+    lbl_estimation.Caption:='FINISHED (duration: '+TimeToStr(Time-absolutebegintime)+')';
+
+    DoStep('FIN');
+    btn_abortok.Caption:='&OK';
+    btn_abortok.Default:=True;
+
+    converting:=False;
+
+    database.Close;
+    database.Free;
+
+    CloseDataConnection;
+  END;
+
+PROCEDURE TForm10.stop_convert;
+  BEGIN
+    btn_abortok.Caption:='&Close';
+    btn_abortok.Default:=True;
+    converting:=False;
+    lbl_estimation.Caption:='ABORTED';
+    group_progress.Caption:='Creating DB (ABORTED)';
+    DataBase.Close;
+    IF MessageBox(Self.Handle, PChar('Delete the unfinished DB-file?'), PChar('Delete file?'), MB_YESNO)=IDYES THEN BEGIN
+      DeleteFile(loaded_filename);
+    END;
+  END;
+
+PROCEDURE TForm10.btn_abortokClick(Sender: TObject);
+  BEGIN
+    IF converting THEN BEGIN
+      IF MessageBox(Self.Handle, PChar('Do you really want to cancel the convert-progress?'), PChar('Warning: Converting'), MB_YESNO)=IDYES THEN
+        abort:=True;
+    END ELSE BEGIN
+      Form10.Visible:=False;
+      Form1.Visible:=True;
+    END;
+  END;
+
+PROCEDURE InsertDatLinkToDB(fileid:LongWord; offset:LongWord);
+  VAR
+    link:LongWord;
+  BEGIN
+    OniDataConnection.LoadDatFilePart(fileid,offset,4,@link);
+    IF link=0 THEN
+      link:=$FFFFFFFF
+    ELSE
+      link:=link DIV 256;
+    Query.SQL.Text:='INSERT INTO linkmap (src_id,src_link_offset,target_id) VALUES ('+IntToStr(fileid)+','+IntToStr(offset)+','+IntToStr(link)+');';
+    Query.ExecSQL;
+  END;
+
+PROCEDURE AISA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN BEGIN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*$160+$28);
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*$160+$150);
+      END;
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE AKEV(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 16 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE AKOT(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 4 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CBPI(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 56 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CBPM(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 18 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CONS(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 1 DO InsertDatLinkToDB(fileid,$24+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CRSA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$14,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*1100+$A0);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE DOOR(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+      InsertDatLinkToDB(fileid,$10);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE DPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$40);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE HPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$0C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGHH(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$24);
+      InsertDatLinkToDB(fileid,$28);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGPA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
+      IF links>0 THEN
+        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGPG(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 1 DO InsertDatLinkToDB(fileid,$1C+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGSA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
+      IF links>0 THEN
+        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IMPT(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$10);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$0C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE KEYI(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 9 DO InsertDatLinkToDB(fileid,$08+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE M3GA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
+      IF links>0 THEN
+        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE M3GM(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 6 DO InsertDatLinkToDB(fileid,$0C+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE MTRL(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$10);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OBDC(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*$18+$4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OBOA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO BEGIN
+          InsertDatLinkToDB(fileid,$20+i*240+$0);
+          InsertDatLinkToDB(fileid,$20+i*240+$4);
+          InsertDatLinkToDB(fileid,$20+i*240+$8);
+        END;
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OFGA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*12+$04);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONCC(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$28);
+      InsertDatLinkToDB(fileid,$434);
+      InsertDatLinkToDB(fileid,$438);
+      InsertDatLinkToDB(fileid,$43C);
+      InsertDatLinkToDB(fileid,$C3C);
+      InsertDatLinkToDB(fileid,$C40);
+      InsertDatLinkToDB(fileid,$C44);
+      InsertDatLinkToDB(fileid,$C48);
+      InsertDatLinkToDB(fileid,$C88);
+      InsertDatLinkToDB(fileid,$C8C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONCV(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONLV(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 5 DO InsertDatLinkToDB(fileid,$48+i*4);
+      FOR i:=0 TO 5 DO InsertDatLinkToDB(fileid,$64+i*4);
+      InsertDatLinkToDB(fileid,$300);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONOA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*8+$04);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONSK(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+      InsertDatLinkToDB(fileid,$0C);
+      InsertDatLinkToDB(fileid,$10);
+      InsertDatLinkToDB(fileid,$14);
+      InsertDatLinkToDB(fileid,$18);
+      InsertDatLinkToDB(fileid,$20);
+      InsertDatLinkToDB(fileid,$44);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONVL(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONWC(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$28);
+      InsertDatLinkToDB(fileid,$34);
+      InsertDatLinkToDB(fileid,$40);
+      InsertDatLinkToDB(fileid,$54);
+      InsertDatLinkToDB(fileid,$58);
+      InsertDatLinkToDB(fileid,$5C);
+      InsertDatLinkToDB(fileid,$60);
+      InsertDatLinkToDB(fileid,$6FC);
+      InsertDatLinkToDB(fileid,$700);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$0C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE PSPC(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$50);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE PSPL(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*8+$4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE PSUI(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 43 DO InsertDatLinkToDB(fileid,$08+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE STNA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRAC(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$18);
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*12+8);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRAM(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$40);
+      InsertDatLinkToDB(fileid,$44);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRAS(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRBS(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 4 DO InsertDatLinkToDB(fileid,$08+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRCM(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 2 DO InsertDatLinkToDB(fileid,$5C+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRGA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:Word;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$20);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRIG(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$18);
+      InsertDatLinkToDB(fileid,$24);
+      InsertDatLinkToDB(fileid,$28);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRMA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:Word;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRSC(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:Word;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TSFF(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TSFT(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$1C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TURR(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$60);
+      InsertDatLinkToDB(fileid,$6C);
+      InsertDatLinkToDB(fileid,$74);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXAN(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXMA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXMB(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXMP(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$94);
+      InsertDatLinkToDB(fileid,$98);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXTC(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE WMCL(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*8+$4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE WMDD(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$11C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$120+i*$124+$114);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE WMMB(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE WPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+      InsertDatLinkToDB(fileid,$0C);
+    END ELSE BEGIN
+    END;
+  END;
+
+PROCEDURE InsertHandler(ext:String; needed:Boolean; handler:THandler);
+  BEGIN
+    SetLength(ConvertHandlers,Length(ConvertHandlers)+1);
+    ConvertHandlers[High(ConvertHandlers)].Ext:=ext;
+    ConvertHandlers[High(ConvertHandlers)].needed:=needed;
+    ConvertHandlers[High(ConvertHandlers)].handler:=handler;
+  END;
+
+BEGIN
+  InsertHandler('ABNA',False,NIL);
+//  InsertHandler('AGDB',True,AGDB);
+  InsertHandler('AGDB',False,NIL);
+  InsertHandler('AGQC',False,NIL);
+  InsertHandler('AGQG',False,NIL);
+  InsertHandler('AGQR',False,NIL);
+  InsertHandler('AISA',True,AISA);
+  InsertHandler('AITR',False,NIL);
+  InsertHandler('AKAA',False,NIL);
+  InsertHandler('AKBA',False,NIL);
+  InsertHandler('AKBP',False,NIL);
+  InsertHandler('AKDA',False,NIL);
+  InsertHandler('AKEV',True,AKEV);
+  InsertHandler('AKOT',True,AKOT);
+  InsertHandler('AKVA',False,NIL);
+  InsertHandler('BINA',False,NIL);
+  InsertHandler('CBPI',True,CBPI);
+  InsertHandler('CBPM',True,CBPM);
+  InsertHandler('CONS',True,CONS);
+  InsertHandler('CRSA',True,CRSA);
+  InsertHandler('DOOR',True,DOOR);
+  InsertHandler('DPGE',True,DPGE);
+  InsertHandler('ENVP',False,NIL);
+  InsertHandler('FILM',False,NIL);
+  InsertHandler('HPGE',True,HPGE);
+  InsertHandler('IDXA',False,NIL);
+  InsertHandler('IGHH',True,IGHH);
+  InsertHandler('IGPA',True,IGPA);
+  InsertHandler('IGPG',True,IGPG);
+  InsertHandler('IGSA',True,IGSA);
+  InsertHandler('IMPT',True,IMPT);
+  InsertHandler('IPGE',True,IPGE);
+  InsertHandler('KEYI',True,KEYI);
+  InsertHandler('M3GA',True,M3GA);
+  InsertHandler('M3GM',True,M3GM);
+  InsertHandler('MTRL',True,MTRL);
+  InsertHandler('OBAN',False,NIL);
+  InsertHandler('OBDC',True,OBDC);
+  InsertHandler('OBOA',True,OBOA);
+  InsertHandler('OFGA',True,OFGA);
+  InsertHandler('ONCC',True,ONCC);
+  InsertHandler('ONCP',False,NIL);
+  InsertHandler('ONCV',True,ONCV);
+  InsertHandler('ONFA',False,NIL);
+  InsertHandler('ONGS',False,NIL);
+  InsertHandler('ONIA',False,NIL);
+  InsertHandler('ONLD',False,NIL);
+  InsertHandler('ONLV',True,ONLV);
+  InsertHandler('ONMA',False,NIL);
+  InsertHandler('ONOA',True,ONOA);
+  InsertHandler('ONSA',False,NIL);
+  InsertHandler('ONSK',True,ONSK);
+  InsertHandler('ONTA',False,NIL);
+  InsertHandler('ONVL',True,ONVL);
+  InsertHandler('ONWC',True,ONWC);
+  InsertHandler('OPGE',True,OPGE);
+  InsertHandler('OSBD',False,NIL);
+  InsertHandler('OTIT',False,NIL);
+  InsertHandler('OTLF',False,NIL);
+  InsertHandler('PLEA',False,NIL);
+  InsertHandler('PNTA',False,NIL);
+  InsertHandler('PSPC',True,PSPC);
+  InsertHandler('PSPL',True,PSPL);
+  InsertHandler('PSUI',True,PSUI);
+  InsertHandler('QTNA',False,NIL);
+  InsertHandler('SNDD',False,NIL);
+  InsertHandler('STNA',True,STNA);
+  InsertHandler('SUBT',False,NIL);
+  InsertHandler('TRAC',True,TRAC);
+  InsertHandler('TRAM',True,TRAM);
+  InsertHandler('TRAS',True,TRAS);
+  InsertHandler('TRBS',True,TRBS);
+  InsertHandler('TRCM',True,TRCM);
+  InsertHandler('TRGA',True,TRGA);
+  InsertHandler('TRGE',True,TRGE);
+  InsertHandler('TRIA',False,NIL);
+  InsertHandler('TRIG',True,TRIG);
+  InsertHandler('TRMA',True,TRMA);
+  InsertHandler('TRSC',True,TRSC);
+  InsertHandler('TRTA',False,NIL);
+  InsertHandler('TSFF',True,TSFF);
+  InsertHandler('TSFL',False,NIL);
+  InsertHandler('TSFT',True,TSFT);
+  InsertHandler('TSGA',False,NIL);
+  InsertHandler('TSTR',False,NIL);
+  InsertHandler('TURR',True,TURR);
+  InsertHandler('TXAN',True,TXAN);
+  InsertHandler('TXCA',False,NIL);
+  InsertHandler('TXMA',True,TXMA);
+  InsertHandler('TXMB',True,TXMB);
+  InsertHandler('TXMP',True,TXMP);
+  InsertHandler('TXTC',True,TXTC);
+  InsertHandler('VCRA',False,NIL);
+  InsertHandler('WMCL',True,WMCL);
+  InsertHandler('WMDD',True,WMDD);
+  InsertHandler('WMM_',False,NIL);
+  InsertHandler('WMMB',True,WMMB);
+  InsertHandler('WPGE',True,WPGE);   
+END.
Index: /oup/current/Unit11_extractor.dfm
===================================================================
--- /oup/current/Unit11_extractor.dfm	(revision 10)
+++ /oup/current/Unit11_extractor.dfm	(revision 10)
@@ -0,0 +1,257 @@
+object Form11: TForm11
+  Left = 0
+  Top = 0
+  Caption = 'Extractor'
+  ClientHeight = 398
+  ClientWidth = 487
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIChild
+  OldCreateOrder = False
+  Visible = True
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCreate = FormCreate
+  OnResize = FormResize
+  PixelsPerInch = 96
+  TextHeight = 13
+  object group_select: TGroupBox
+    Left = 0
+    Top = 0
+    Width = 191
+    Height = 398
+    Align = alClient
+    Caption = '1. Select file(s)'
+    TabOrder = 0
+    object panel_extension: TPanel
+      Left = 2
+      Top = 293
+      Width = 187
+      Height = 103
+      Align = alBottom
+      BevelOuter = bvNone
+      TabOrder = 0
+      OnResize = panel_extensionResize
+      object lbl_filter: TLabel
+        Left = 2
+        Top = 62
+        Width = 100
+        Height = 17
+        AutoSize = False
+        Caption = 'Filter by &extension:'
+        FocusControl = combo_extension
+      end
+      object combo_extension: TComboBox
+        Left = 2
+        Top = 76
+        Width = 145
+        Height = 21
+        Style = csDropDownList
+        DropDownCount = 12
+        Font.Charset = DEFAULT_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -11
+        Font.Name = 'Tahoma'
+        Font.Style = []
+        ItemHeight = 13
+        ParentFont = False
+        Sorted = True
+        TabOrder = 3
+        OnClick = combo_extensionClick
+      end
+      object check_zerobyte: TCheckBox
+        Left = 2
+        Top = 44
+        Width = 130
+        Height = 13
+        Caption = 'Show &zero-byte files'
+        TabOrder = 2
+        OnClick = check_zerobyteClick
+      end
+      object edit_filtername: TEdit
+        Left = 2
+        Top = 20
+        Width = 145
+        Height = 18
+        AutoSize = False
+        TabOrder = 1
+      end
+      object check_filtername: TCheckBox
+        Left = 2
+        Top = 5
+        Width = 130
+        Height = 15
+        Caption = 'Filter by file&name:'
+        TabOrder = 0
+        OnClick = check_filternameClick
+      end
+    end
+    object list: TListBox
+      Left = 2
+      Top = 15
+      Width = 187
+      Height = 278
+      Align = alClient
+      ItemHeight = 13
+      MultiSelect = True
+      TabOrder = 1
+    end
+  end
+  object group_extract: TGroupBox
+    Left = 191
+    Top = 0
+    Width = 296
+    Height = 398
+    Align = alRight
+    Caption = '2. Select extract-method'
+    TabOrder = 1
+    object group_singlefiles: TGroupBox
+      Left = 8
+      Top = 16
+      Width = 281
+      Height = 185
+      Caption = 'Write data into single files'
+      TabOrder = 0
+      object btn_sel_dat: TButton
+        Left = 8
+        Top = 16
+        Width = 129
+        Height = 49
+        Caption = 'Selected files (dat contents only)'
+        TabOrder = 0
+        WordWrap = True
+        OnClick = Extract
+      end
+      object btn_sel_datraw: TButton
+        Left = 8
+        Top = 72
+        Width = 129
+        Height = 49
+        Caption = 'Selected files (dat+raw)'
+        TabOrder = 1
+        WordWrap = True
+        OnClick = Extract
+      end
+      object btn_sel_datraw_convert: TButton
+        Left = 8
+        Top = 128
+        Width = 129
+        Height = 49
+        Caption = 'Selected files (dat+raw) (with convert if possible)'
+        TabOrder = 2
+        WordWrap = True
+        OnClick = Extract
+      end
+      object btn_all_dat: TButton
+        Left = 144
+        Top = 16
+        Width = 129
+        Height = 49
+        Caption = 'All files in list (dat contents only)'
+        TabOrder = 3
+        WordWrap = True
+        OnClick = Extract
+      end
+      object btn_all_datraw: TButton
+        Left = 144
+        Top = 72
+        Width = 129
+        Height = 49
+        Caption = 'All files in list (dat+raw)'
+        TabOrder = 4
+        WordWrap = True
+        OnClick = Extract
+      end
+      object btn_all_datraw_convert: TButton
+        Left = 144
+        Top = 128
+        Width = 129
+        Height = 49
+        BiDiMode = bdLeftToRight
+        Caption = 'All files in list (dat+raw) (with convert if possible)'
+        ParentBiDiMode = False
+        TabOrder = 5
+        WordWrap = True
+        OnClick = Extract
+      end
+    end
+    object group_onefile: TGroupBox
+      Left = 8
+      Top = 208
+      Width = 281
+      Height = 73
+      Caption = 'Write data into one file'
+      TabOrder = 1
+      object btn_sel_files_toone: TButton
+        Left = 8
+        Top = 16
+        Width = 129
+        Height = 49
+        Caption = 'Selected files (dat contents only)'
+        TabOrder = 0
+        WordWrap = True
+        OnClick = Extract
+      end
+      object btn_all_files_toone: TButton
+        Left = 144
+        Top = 16
+        Width = 129
+        Height = 49
+        Caption = 'All files in list (dat contents only)'
+        TabOrder = 1
+        WordWrap = True
+        OnClick = Extract
+      end
+    end
+    object group_progress: TGroupBox
+      Left = 8
+      Top = 288
+      Width = 281
+      Height = 105
+      Caption = 'Progress ...'
+      TabOrder = 2
+      Visible = False
+      object lbl_progress: TLabel
+        Left = 8
+        Top = 40
+        Width = 265
+        Height = 17
+        AutoSize = False
+        Caption = 'Files done: 0/0'
+      end
+      object lbl_estimated: TLabel
+        Left = 8
+        Top = 56
+        Width = 265
+        Height = 17
+        AutoSize = False
+        Caption = 'Estimated finishing time: 00:00:00'
+      end
+      object progress: TProgressBar
+        Left = 8
+        Top = 16
+        Width = 265
+        Height = 17
+        Smooth = True
+        TabOrder = 0
+      end
+      object btn_abort: TButton
+        Left = 8
+        Top = 72
+        Width = 97
+        Height = 23
+        Caption = 'Abort'
+        Enabled = False
+        TabOrder = 1
+      end
+    end
+  end
+  object saved: TSaveDialog
+    Left = 448
+    Top = 328
+  end
+end
Index: /oup/current/Unit11_extractor.pas
===================================================================
--- /oup/current/Unit11_extractor.pas	(revision 10)
+++ /oup/current/Unit11_extractor.pas	(revision 10)
@@ -0,0 +1,235 @@
+UNIT Unit11_extractor;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, ExtCtrls, StrUtils, ComCtrls;
+TYPE
+  TForm11 = Class(TForm)
+    group_select: TGroupBox;
+    group_extract: TGroupBox;
+    group_singlefiles: TGroupBox;
+    btn_sel_dat: TButton;
+    btn_sel_datraw: TButton;
+    btn_sel_datraw_convert: TButton;
+    btn_all_dat: TButton;
+    btn_all_datraw: TButton;
+    btn_all_datraw_convert: TButton;
+    group_onefile: TGroupBox;
+    btn_sel_files_toone: TButton;
+    btn_all_files_toone: TButton;
+    group_progress: TGroupBox;
+    progress: TProgressBar;
+    lbl_progress: TLabel;
+    lbl_estimated: TLabel;
+    btn_abort: TButton;
+    saved: TSaveDialog;
+    panel_extension: TPanel;
+    lbl_filter: TLabel;
+    combo_extension: TComboBox;
+    check_zerobyte: TCheckBox;
+    edit_filtername: TEdit;
+    check_filtername: TCheckBox;
+    list: TListBox;
+    PROCEDURE LoadFileNames;
+    PROCEDURE check_filternameClick(Sender: TObject);
+    PROCEDURE check_zerobyteClick(Sender: TObject);
+    PROCEDURE combo_extensionClick(Sender: TObject);
+    PROCEDURE panel_extensionResize(Sender: TObject);
+    PROCEDURE Recreatelist;
+
+    PROCEDURE FormCreate(Sender: TObject);
+    PROCEDURE FormClose(Sender: TObject; var Action: TCloseAction);
+    PROCEDURE FormResize(Sender: TObject);
+    PROCEDURE Extract(Sender: TObject);
+  PRIVATE
+  PUBLIC
+  END;
+
+VAR
+  Form11: TForm11;
+
+IMPLEMENTATION
+{$R *.dfm}
+USES Unit1_main, Unit2_functions, Unit3_data, Unit15_Classes;
+
+
+PROCEDURE TForm11.Recreatelist;
+  VAR
+    i:LongWord;
+    exts:TStringArray;
+  BEGIN
+    combo_extension.Items.Clear;
+    combo_extension.Items.Add('_All files_ ('+IntToStr(OniDataConnection.GetFilesCount)+')');
+    exts:=OniDataConnection.GetExtensionsList;
+    FOR i:=0 TO High(exts) DO
+      combo_extension.Items.Add(exts[i]);
+    combo_extension.ItemIndex:=0;
+    combo_extensionClick(Self);
+  END;
+
+PROCEDURE TForm11.LoadFileNames;
+  VAR
+    Extension:String[4];
+    no_zero_bytes:Boolean;
+    pattern:String;
+    files:TStringArray;
+    i:LongWord;
+  BEGIN
+    Extension:=MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex],1,4);
+    no_zero_bytes:=NOT check_zerobyte.Checked;
+    pattern:='';
+    IF check_filtername.Checked THEN pattern:=edit_filtername.Text;
+    IF Extension='_All' THEN Extension:='';
+
+    files:=OniDataConnection.GetFilesList(extension,pattern,no_zero_bytes);
+    list.Items.Clear;
+    IF Length(files)>0 THEN
+      FOR i:=0 TO High(files) DO
+        list.Items.Add(files[i]);
+  END;
+
+PROCEDURE TForm11.panel_extensionResize(Sender: TObject);
+  BEGIN
+    combo_extension.Width:=panel_extension.Width-5;
+    edit_filtername.Width:=panel_extension.Width-5;
+  END;
+
+PROCEDURE TForm11.combo_extensionClick(Sender: TObject);
+  BEGIN
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm11.check_zerobyteClick(Sender: TObject);
+  VAR
+    i:Byte;
+  BEGIN
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm11.check_filternameClick(Sender: TObject);
+  BEGIN
+    edit_filtername.Enabled:=NOT check_filtername.Checked;
+    LoadFileNames;
+  END;
+
+
+
+PROCEDURE TForm11.FormResize(Sender: TObject);
+  BEGIN
+    IF Self.Width>=450 THEN BEGIN
+    END ELSE Self.Width:=450;
+    IF Self.Height>=400 THEN BEGIN
+      group_progress.Height:=group_extract.Height-293;
+    END ELSE Self.Height:=400;
+  END;
+
+PROCEDURE TForm11.FormClose(Sender: TObject; var Action: TCloseAction);
+  BEGIN
+    Action:=caFree;
+  END;
+
+PROCEDURE TForm11.FormCreate(Sender: TObject);
+  BEGIN
+    btn_sel_dat.Caption:=           'Selected files'+CrLf+'(dat contents only)';
+    btn_sel_datraw.Caption:=        'Selected files'+CrLf+'(dat+raw contents)';
+    btn_sel_datraw_convert.Caption:='Selected files'+CrLf+'(dat+raw contents)'+CrLf+'(with convert if possible)';
+    btn_all_dat.Caption:=           'All files in list'+CrLf+'(dat contents only)';
+    btn_all_datraw.Caption:=        'All files in list'+CrLf+'(dat+raw contents)';
+    btn_all_datraw_convert.Caption:='All files in list'+CrLf+'(dat+raw contents)'+CrLf+'(with convert if possible)';
+    btn_sel_files_toone.Caption:=   'Selected files'+CrLf+'(dat contents only)';
+    btn_all_files_toone.Caption:=   'All files in list'+CrLf+'(dat contents only)';
+  END;
+
+PROCEDURE TForm11.Extract(Sender: TObject);
+  VAR
+    sel_only:Boolean;
+    dat_only:Boolean;
+    convert:Boolean;
+    one_file:Boolean;
+    settings:TExportSet;
+    files:LongWord;
+    i,done:LongWord;
+    begintime:Double;
+  BEGIN
+    sel_only:=Pos('sel',TButton(Sender).Name)>0;
+    dat_only:=NOT (Pos('datraw',TButton(Sender).Name)>0);
+    convert:=Pos('convert',TButton(Sender).Name)>0;
+    one_file:=Pos('toone',TButton(Sender).Name)>0;
+    IF dat_only THEN settings:=[DO_dat]
+    ELSE settings:=[DO_dat,DO_raw];
+    IF convert THEN settings:=settings+[DO_convert];
+    IF one_file THEN settings:=settings+[DO_toone];
+    progress.Position:=0;
+
+    IF saved.Execute THEN BEGIN
+      begintime:=Time;
+      group_progress.Visible:=True;
+      group_select.Enabled:=False;
+      group_singlefiles.Enabled:=False;
+      group_onefile.Enabled:=False;
+      lbl_estimated.Caption:='Estimated finishing time: unknown';
+      IF one_file THEN BEGIN
+        IF FileExists(saved.FileName) THEN BEGIN
+          IF MessageBox(Self.Handle,PChar('File already exists. Do you want to overwrite it?'),PChar('Warning!'),MB_YESNO)=ID_YES THEN BEGIN
+            DeleteFile(saved.FileName);
+          END ELSE BEGIN
+            group_progress.Visible:=False;
+            group_select.Enabled:=True;
+            group_singlefiles.Enabled:=True;
+            group_onefile.Enabled:=True;
+            Exit;
+          END;
+        END;
+        i:=FileCreate(saved.FileName);
+        FileClose(i);
+        i:=0;
+      END;
+      IF sel_only THEN BEGIN
+        files:=list.SelCount;
+        lbl_progress.Caption:='Files done: 0/'+IntToStr(files);
+        progress.Max:=files;
+        done:=0;
+        FOR i:=0 TO list.Count-1 DO BEGIN
+          IF list.Selected[i] THEN BEGIN
+            IF one_file THEN BEGIN
+              ExportFile(OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]),ExtractFileName(saved.FileName),settings,ExtractFileDir(saved.FileName));
+            END ELSE BEGIN
+              ExportFile(OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]),list.Items.Strings[i],settings,'D:');
+            END;
+            Inc(done);
+          END;
+          IF ((done MOD 10)=0) AND (done>=50) THEN
+            lbl_estimated.Caption:='Estimated finishing time: '+TimeToStr((Time-begintime)/done*files+begintime);
+          IF (i MOD 10)=0 THEN BEGIN
+            progress.Position:=done;
+            lbl_progress.Caption:='Files done: '+IntToStr(done)+'/'+IntToStr(files);
+            Application.ProcessMessages;
+          END;
+        END;
+      END ELSE BEGIN
+        files:=list.Count;
+        lbl_progress.Caption:='Files done: 0/'+IntToStr(files);
+        progress.Max:=files;
+        FOR i:=0 TO list.Count-1 DO BEGIN
+          IF one_file THEN BEGIN
+            ExportFile(OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]),ExtractFileName(saved.FileName),settings,ExtractFileDir(saved.FileName));
+          END ELSE BEGIN
+            ExportFile(OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]),list.Items.Strings[i],settings,'D:');
+          END;
+          IF ((i MOD 10)=0) AND (i>=50) THEN
+            lbl_estimated.Caption:='Estimated finishing time: '+TimeToStr((Time-begintime)/i*files+begintime);
+          IF (i MOD 5)=0 THEN BEGIN
+            progress.Position:=i;
+            lbl_progress.Caption:='Files done: '+IntToStr(i)+'/'+IntToStr(files);
+            Application.ProcessMessages;
+          END;
+        END;
+      END;
+      group_progress.Visible:=False;
+      group_select.Enabled:=True;
+      group_singlefiles.Enabled:=True;
+      group_onefile.Enabled:=True;
+    END;
+  END;
+
+END.
Index: /oup/current/Unit12_ValueEdit.dfm
===================================================================
--- /oup/current/Unit12_ValueEdit.dfm	(revision 10)
+++ /oup/current/Unit12_ValueEdit.dfm	(revision 10)
@@ -0,0 +1,157 @@
+object Form12: TForm12
+  Left = 0
+  Top = 0
+  BorderStyle = bsNone
+  BorderWidth = 1
+  Caption = 'Value Edit'
+  ClientHeight = 145
+  ClientWidth = 298
+  Color = clBtnFace
+  Constraints.MaxHeight = 147
+  Constraints.MaxWidth = 700
+  Constraints.MinHeight = 147
+  Constraints.MinWidth = 300
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poMainFormCenter
+  PixelsPerInch = 96
+  TextHeight = 13
+  object group: TGroupBox
+    Left = 0
+    Top = 0
+    Width = 298
+    Height = 145
+    Align = alClient
+    Caption = '---'
+    TabOrder = 0
+    DesignSize = (
+      298
+      145)
+    object lbl_current: TLabel
+      Left = 8
+      Top = 64
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'Current value:'
+    end
+    object lbl_new: TLabel
+      Left = 8
+      Top = 88
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'New value:'
+    end
+    object lbl_offset: TLabel
+      Left = 8
+      Top = 16
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'Offset:'
+    end
+    object lbl_datatype: TLabel
+      Left = 8
+      Top = 40
+      Width = 73
+      Height = 17
+      AutoSize = False
+      Caption = 'Datatype:'
+    end
+    object btn_ok: TButton
+      Left = 153
+      Top = 112
+      Width = 65
+      Height = 25
+      Anchors = [akTop, akRight]
+      Caption = 'OK'
+      Default = True
+      TabOrder = 0
+      OnClick = btn_okClick
+    end
+    object btn_cancel: TButton
+      Left = 225
+      Top = 112
+      Width = 65
+      Height = 25
+      Anchors = [akTop, akRight]
+      Cancel = True
+      Caption = 'Cancel'
+      TabOrder = 1
+      OnClick = btn_cancelClick
+    end
+    object edit_current: TEdit
+      Left = 88
+      Top = 64
+      Width = 203
+      Height = 18
+      Anchors = [akLeft, akTop, akRight]
+      AutoSize = False
+      Color = clInfoBk
+      ReadOnly = True
+      TabOrder = 2
+    end
+    object edit_offset: TEdit
+      Left = 87
+      Top = 16
+      Width = 203
+      Height = 18
+      Anchors = [akLeft, akTop, akRight]
+      AutoSize = False
+      Color = clInfoBk
+      ReadOnly = True
+      TabOrder = 3
+    end
+    object edit_datatype: TEdit
+      Left = 87
+      Top = 40
+      Width = 203
+      Height = 18
+      Anchors = [akLeft, akTop, akRight]
+      AutoSize = False
+      Color = clInfoBk
+      ReadOnly = True
+      TabOrder = 4
+    end
+    object edit_new: TCrossEdit
+      Left = 88
+      Top = 88
+      Width = 203
+      Height = 18
+      Anchors = [akLeft, akTop, akRight]
+      AutoSize = False
+      BorderStyle = bsNone
+      Color = clWhite
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -11
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      HideSelection = False
+      ParentFont = False
+      TabOrder = 5
+      Text = '0000'
+      FocusAlignment = taLeftJustify
+      NoFocusAlignment = taLeftJustify
+      Precision = 15
+      Decimals = 4
+      FocusWidthInc = 0
+      EditType = etHex
+      NextDialogOnEnter = True
+      DialogOnCursorKeys = True
+      NextPriorStep = 1
+      AutoFocus = False
+      LimitCheck = True
+      Max = 2147483647.000000000000000000
+      FocusColor = clWhite
+      NoFocusColor = clWhite
+      ErrorColor = clRed
+      StringCharSet = scFull
+    end
+  end
+end
Index: /oup/current/Unit12_ValueEdit.pas
===================================================================
--- /oup/current/Unit12_ValueEdit.pas	(revision 10)
+++ /oup/current/Unit12_ValueEdit.pas	(revision 10)
@@ -0,0 +1,119 @@
+UNIT Unit12_ValueEdit;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, CrossEdit, Math;
+TYPE
+  TForm12 = Class(TForm)
+    group: TGroupBox;
+    btn_ok: TButton;
+    btn_cancel: TButton;
+    lbl_current: TLabel;
+    edit_current: TEdit;
+    lbl_new: TLabel;
+    lbl_offset: TLabel;
+    lbl_datatype: TLabel;
+    edit_offset: TEdit;
+    edit_datatype: TEdit;
+    edit_new: TCrossEdit;
+    PROCEDURE btn_cancelClick(Sender: TObject);
+    PROCEDURE btn_okClick(Sender: TObject);
+    PROCEDURE MakeVarInput(objectname:String; offset:LongWord; datatype:Word; current:String; caller:TObject);
+  PRIVATE
+  PUBLIC
+  END;
+
+VAR
+  Form12: TForm12;
+
+
+IMPLEMENTATION
+USES Unit8_binedit, Unit13_rawedit,Unit9_data_structures, Unit1_main;
+{$R *.dfm}
+VAR
+  caller_win_dat:TForm8;
+  caller_win_raw:TForm13;
+  _datatype:Word;
+  _offset:LongWord;
+
+
+PROCEDURE TForm12.MakeVarInput(objectname:String; offset:LongWord; datatype:Word; current:String; caller:TObject);
+  BEGIN
+    caller_win_dat:=NIL;
+    caller_win_raw:=NIL;
+    IF Pos('rawedit',TComponent(caller).Name)>0 THEN
+      caller_win_raw:=TForm13(caller)
+    ELSE
+      caller_win_dat:=TForm8(caller);
+    Form1.Enabled:=False;
+    Self.Visible:=True;
+    group.Caption:='Edit value';
+    _datatype:=datatype;
+    _offset:=offset;
+    IF Length(objectname)>0 THEN group.Caption:=group.Caption+' for '+objectname;
+    edit_offset.Text:='0x'+IntToHex(offset,8);
+    edit_datatype.Text:=GetDataType(datatype);
+    edit_current.Text:=current;
+    edit_new.EditType:=etString;
+    edit_new.Text:='';
+    edit_new.LimitCheck:=False;
+    edit_new.MaxLength:=0;
+    edit_new.Max:=0;
+    edit_new.BorderStyle:=bsSingle;
+    Form12.Width:=300;
+    CASE datatype OF
+      1..4: BEGIN
+              edit_new.EditType:=etUnsignedInt;
+              edit_new.LimitCheck:=True;
+              edit_new.Max:=Int(Power(256,datatype))-1;
+            END;
+      5..8: BEGIN
+              edit_new.MaxLength:=2*(datatype-4);
+              edit_new.EditType:=etHex;
+            END;
+      9:    BEGIN
+              edit_new.EditType:=etFloat;
+              edit_new.LimitCheck:=False;
+            END;
+      10:   BEGIN
+              edit_new.EditType:=etBinary;
+              edit_new.LimitCheck:=False;
+              edit_new.MaxLength:=8;
+            END;
+      13..16: BEGIN
+              Exit;
+              edit_new.EditType:=etInteger;
+              edit_new.LimitCheck:=True;
+              edit_new.Max:=Int((Power(256,datatype-13)) / 2)-1;
+              edit_new.Min:=1-Int((Power(256,datatype-13)) / 2)-1;
+            END;
+      10000..65535: BEGIN
+              edit_new.EditType:=etString;
+              edit_new.LimitCheck:=False;
+              edit_new.MaxLength:=datatype-10000;
+              Form12.Width:=700;
+            END;
+    END;
+    edit_new.SetFocus;
+    edit_new.SelectAll;
+  END;
+
+PROCEDURE TForm12.btn_okClick(Sender: TObject);
+  BEGIN
+    IF NOT edit_new.NoValidValue THEN BEGIN
+      Form1.Enabled:=True;
+      Self.Visible:=False;
+      IF caller_win_dat=NIL THEN
+        caller_win_raw.SetNewValue(_datatype,_offset,edit_new.Text)
+      ELSE
+        caller_win_dat.SetNewValue(_datatype,_offset,edit_new.Text);
+    END;
+  END;
+
+PROCEDURE TForm12.btn_cancelClick(Sender: TObject);
+  BEGIN
+    Form1.Enabled:=True;
+    Self.Visible:=False;
+  END;
+
+END.
Index: /oup/current/Unit13_rawedit.dfm
===================================================================
--- /oup/current/Unit13_rawedit.dfm	(revision 10)
+++ /oup/current/Unit13_rawedit.dfm	(revision 10)
@@ -0,0 +1,301 @@
+object Form13: TForm13
+  Left = 0
+  Top = 0
+  BorderIcons = [biSystemMenu, biMaximize]
+  Caption = 'Binary .raw-Editor'
+  ClientHeight = 640
+  ClientWidth = 642
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIChild
+  KeyPreview = True
+  OldCreateOrder = False
+  Visible = True
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCloseQuery = FormCloseQuery
+  OnCreate = FormCreate
+  OnKeyUp = FormKeyUp
+  OnResize = FormResize
+  PixelsPerInch = 96
+  TextHeight = 13
+  object Splitter1: TSplitter
+    Left = 150
+    Top = 0
+    Width = 9
+    Height = 640
+    AutoSnap = False
+    Beveled = True
+    MinSize = 150
+  end
+  object panel_data: TPanel
+    Left = 159
+    Top = 0
+    Width = 483
+    Height = 640
+    Align = alClient
+    BevelOuter = bvNone
+    TabOrder = 0
+    OnResize = panel_dataResize
+    object Splitter2: TSplitter
+      Left = 0
+      Top = 450
+      Width = 483
+      Height = 9
+      Cursor = crVSplit
+      Align = alTop
+      AutoSnap = False
+      Beveled = True
+      MinSize = 40
+      ExplicitTop = 209
+    end
+    object hex: TMPHexEditor
+      Left = 0
+      Top = 0
+      Width = 483
+      Height = 450
+      Cursor = crIBeam
+      Align = alTop
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -16
+      Font.Name = 'Courier'
+      Font.Style = []
+      OnKeyUp = hexKeyUp
+      ParentFont = False
+      TabOrder = 0
+      BytesPerRow = 16
+      Translation = tkAsIs
+      OffsetFormat = '6!10:0x|'
+      Colors.Background = clWindow
+      Colors.ChangedBackground = clWindow
+      Colors.ChangedText = clRed
+      Colors.CursorFrame = clNavy
+      Colors.Offset = clBlack
+      Colors.OddColumn = clBlue
+      Colors.EvenColumn = clNavy
+      Colors.CurrentOffsetBackground = clBtnShadow
+      Colors.OffsetBackGround = clBtnFace
+      Colors.CurrentOffset = clBtnHighlight
+      Colors.Grid = clBtnFace
+      Colors.NonFocusCursorFrame = clAqua
+      Colors.ActiveFieldBackground = clWindow
+      FocusFrame = True
+      NoSizeChange = True
+      AllowInsertMode = False
+      DrawGridLines = False
+      Version = 'May 23, 2005; '#169' markus stephany, vcl[at]mirkes[dot]de'
+      OnChange = hexChange
+      ShowPositionIfNotFocused = True
+      OnSelectionChanged = hexSelectionChanged
+    end
+    object value_viewer: TWrapGrid
+      Left = 0
+      Top = 459
+      Width = 483
+      Height = 181
+      Align = alClient
+      ColCount = 1
+      DefaultColWidth = 80
+      DefaultRowHeight = 18
+      FixedCols = 0
+      RowCount = 8
+      FixedRows = 0
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -11
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing]
+      ParentFont = False
+      PopupMenu = value_viewer_context
+      TabOrder = 1
+      OnDblClick = value_viewerDblClick
+      OnMouseDown = value_viewerMouseDown
+    end
+  end
+  object panel_files: TPanel
+    Left = 0
+    Top = 0
+    Width = 150
+    Height = 640
+    Align = alLeft
+    BevelOuter = bvNone
+    TabOrder = 1
+    object Splitter4: TSplitter
+      Left = 0
+      Top = 442
+      Width = 150
+      Height = 9
+      Cursor = crVSplit
+      Align = alBottom
+      AutoSnap = False
+      Beveled = True
+      MinSize = 150
+    end
+    object panel_imexport: TPanel
+      Left = 0
+      Top = 580
+      Width = 150
+      Height = 60
+      Align = alBottom
+      BevelOuter = bvNone
+      TabOrder = 0
+      OnResize = panel_imexportResize
+      object btn_export: TButton
+        Left = 4
+        Top = 4
+        Width = 142
+        Height = 25
+        Caption = 'Export to file...'
+        TabOrder = 0
+        OnClick = btn_exportClick
+      end
+      object btn_import: TButton
+        Left = 4
+        Top = 32
+        Width = 142
+        Height = 25
+        Caption = 'Import from file...'
+        TabOrder = 1
+        OnClick = btn_importClick
+      end
+    end
+    object group_file: TGroupBox
+      Left = 0
+      Top = 0
+      Width = 150
+      Height = 442
+      Align = alClient
+      Caption = '1. Select file'
+      TabOrder = 1
+      object list: TListBox
+        Left = 2
+        Top = 15
+        Width = 146
+        Height = 337
+        Align = alClient
+        ItemHeight = 13
+        TabOrder = 0
+        OnClick = listClick
+      end
+      object panel_extension: TPanel
+        Left = 2
+        Top = 352
+        Width = 146
+        Height = 88
+        Align = alBottom
+        BevelOuter = bvNone
+        TabOrder = 1
+        OnResize = panel_extensionResize
+        object lbl_filter: TLabel
+          Left = 2
+          Top = 46
+          Width = 100
+          Height = 17
+          AutoSize = False
+          Caption = 'Filter by &extension:'
+          FocusControl = combo_extension
+        end
+        object combo_extension: TComboBox
+          Left = 2
+          Top = 60
+          Width = 145
+          Height = 21
+          Style = csDropDownList
+          DropDownCount = 12
+          Font.Charset = DEFAULT_CHARSET
+          Font.Color = clWindowText
+          Font.Height = -11
+          Font.Name = 'Tahoma'
+          Font.Style = []
+          ItemHeight = 13
+          ParentFont = False
+          Sorted = True
+          TabOrder = 2
+          OnClick = combo_extensionClick
+        end
+        object edit_filtername: TEdit
+          Left = 2
+          Top = 20
+          Width = 145
+          Height = 18
+          AutoSize = False
+          TabOrder = 1
+        end
+        object check_filtername: TCheckBox
+          Left = 2
+          Top = 5
+          Width = 130
+          Height = 15
+          Caption = 'Filter by file&name:'
+          TabOrder = 0
+          OnClick = check_filternameClick
+        end
+      end
+    end
+    object GroupBox1: TGroupBox
+      Left = 0
+      Top = 451
+      Width = 150
+      Height = 129
+      Align = alBottom
+      Caption = '2. Select .dat-link-offset'
+      TabOrder = 2
+      object list_offset: TListBox
+        Left = 2
+        Top = 15
+        Width = 146
+        Height = 112
+        Align = alClient
+        ItemHeight = 13
+        TabOrder = 0
+        OnClick = list_offsetClick
+      end
+    end
+  end
+  object value_viewer_context: TPopupMenu
+    AutoHotkeys = maManual
+    OnPopup = value_viewer_contextPopup
+    Left = 368
+    Top = 264
+    object value_viewer_context_copy: TMenuItem
+      Caption = 'Copy to &clipboard'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasdec: TMenuItem
+      Caption = 'Copy to clipboard (as &dec)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasfloat: TMenuItem
+      Caption = 'Copy to clipboard (as &float)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasbitset: TMenuItem
+      Caption = 'Copy to clipboard (as &bitset)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasstring: TMenuItem
+      Caption = 'Copy to clipboard (as &string)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyashex: TMenuItem
+      Caption = 'Copy to clipboard (as &hex)'
+      OnClick = value_viewer_context_copyClick
+    end
+  end
+  object opend: TOpenDialog
+    Options = [ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 120
+    Top = 584
+  end
+  object saved: TSaveDialog
+    Options = [ofOverwritePrompt, ofPathMustExist, ofEnableSizing]
+    Left = 120
+    Top = 608
+  end
+end
Index: /oup/current/Unit13_rawedit.pas
===================================================================
--- /oup/current/Unit13_rawedit.pas	(revision 10)
+++ /oup/current/Unit13_rawedit.pas	(revision 10)
@@ -0,0 +1,723 @@
+UNIT Unit13_rawedit;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Wrapgrid, StdCtrls, Grids, StrUtils, MPHexEditor, ExtCtrls, Clipbrd,
+  Unit3_data, Unit2_functions, Unit9_data_structures, Unit4_exporters, Unit15_Classes,
+  Menus, Math;
+
+TYPE
+  TForm13 = Class(TForm)
+    Splitter1: TSplitter;
+    panel_data: TPanel;
+    hex: TMPHexEditor;
+    Splitter2: TSplitter;
+    value_viewer: TWrapGrid;
+    value_viewer_context: TPopupMenu;
+    value_viewer_context_copy: TMenuItem;
+    value_viewer_context_copyashex: TMenuItem;
+    value_viewer_context_copyasdec: TMenuItem;
+    value_viewer_context_copyasfloat: TMenuItem;
+    value_viewer_context_copyasbitset: TMenuItem;
+    value_viewer_context_copyasstring: TMenuItem;
+    panel_files: TPanel;
+    opend: TOpenDialog;
+    saved: TSaveDialog;
+    panel_imexport: TPanel;
+    btn_export: TButton;
+    btn_import: TButton;
+    group_file: TGroupBox;
+    list: TListBox;
+    panel_extension: TPanel;
+    lbl_filter: TLabel;
+    combo_extension: TComboBox;
+    edit_filtername: TEdit;
+    check_filtername: TCheckBox;
+    GroupBox1: TGroupBox;
+    list_offset: TListBox;
+    Splitter4: TSplitter;
+    procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    PROCEDURE list_offsetClick(Sender: TObject);
+    PROCEDURE LoadRaw(raw_info:TRawInfo);
+    PROCEDURE LoadFileNames;
+    PROCEDURE check_filternameClick(Sender: TObject);
+    PROCEDURE combo_extensionClick(Sender: TObject);
+    PROCEDURE panel_extensionResize(Sender: TObject);
+    PROCEDURE listClick(Sender: TObject);
+    PROCEDURE Recreatelist;
+
+    PROCEDURE FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    PROCEDURE value_viewerDblClick(Sender: TObject);
+    PROCEDURE value_viewer_context_copyClick(Sender: TObject);
+    PROCEDURE value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+    PROCEDURE value_viewer_contextPopup(Sender: TObject);
+    PROCEDURE btn_importClick(Sender: TObject);
+    PROCEDURE btn_exportClick(Sender: TObject);
+    PROCEDURE panel_imexportResize(Sender: TObject);
+    FUNCTION Save:Boolean;
+    PROCEDURE FormClose(Sender: TObject; var Action: TCloseAction);
+    FUNCTION GetValue(datatype:Word; offset:LongWord):String;
+    PROCEDURE hexSelectionChanged(Sender: TObject);
+    PROCEDURE hexChange(Sender: TObject);
+    PROCEDURE panel_dataResize(Sender: TObject);
+    PROCEDURE FormResize(Sender: TObject);
+    PROCEDURE FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+    PROCEDURE FormCreate(Sender: TObject);
+    PROCEDURE ClearValues;
+    PROCEDURE WriteValues;
+    PROCEDURE SetNewValue(datatype:Word; offset:LongWord; value:String);
+  PRIVATE
+    fileid:LongWord;
+    dat_offset:LongWord;
+    fileid_opened,dat_offset_opened:LongWord;
+  PUBLIC
+  END;
+
+VAR
+  Form13: TForm13;
+
+IMPLEMENTATION
+{$R *.dfm}
+USES Unit1_main, Unit12_ValueEdit;
+
+
+PROCEDURE TForm13.LoadRaw(raw_info:TRawInfo);
+  VAR
+    i:LongWord;
+    data:Tdata;
+    mem:TMemoryStream;
+  BEGIN
+    IF hex.Modified THEN BEGIN
+      IF NOT Save THEN BEGIN
+        Exit;
+      END;
+    END;
+    IF list_offset.Count=0 THEN BEGIN
+      FOR i:=0 TO list.Count-1 DO BEGIN
+        IF OniDataConnection.ExtractFileID(list.Items.Strings[i])=raw_info.src_id THEN BEGIN
+          list.ItemIndex:=i;
+          listClick(Self);
+          Break;
+        END;
+      END;
+      FOR i:=0 TO list_offset.Count-1 DO BEGIN
+        IF MidStr(list_offset.Items.Strings[i],3,8)=IntToHex(raw_info.src_offset,8) THEN BEGIN
+          list_offset.ItemIndex:=i;
+          Break;
+        END;
+      END;
+    END;
+    SetLength(data,raw_info.raw_size);
+    OniDataConnection.LoadRawFile(raw_info.src_id,raw_info.src_offset,@data[0]);
+    IF Length(data)>0 THEN BEGIN
+      hex.DataSize:=0;
+      hex.DataSize:=raw_info.raw_size;
+      FOR i:=0 TO High(data) DO
+        hex.Data[i]:=data[i];
+      //WriteStructureInfos(GetStructureInfoId(GetFileInfo(fileid).Extension));
+//      structs.Height:=structs.RowCount*20;
+//      IF structs.Height>120 THEN structs.Height:=120;
+      hexSelectionChanged(Self);
+      fileid_opened:=raw_info.src_id;
+      dat_offset_opened:=raw_info.src_offset;
+      hex.Modified:=False;
+    END ELSE BEGIN
+      ClearValues;
+      hex.DataSize:=0;
+    END;
+  END;
+
+PROCEDURE TForm13.Recreatelist;
+  VAR
+    i:LongWord;
+    exts:TStringArray;
+    count:LongWord;
+  BEGIN
+    combo_extension.Items.Clear;
+    combo_extension.Items.Add('_All files_ ('{+IntToStr(dat_header.Files)}+')');
+    exts:=OniDataConnection.GetExtensionsList;
+    FOR i:=0 TO High(RawListHandlers) DO BEGIN
+      count:=Length(OniDataConnection.GetFilesList(RawListHandlers[i].Ext,'',True));
+      combo_extension.Items.Add(RawListHandlers[i].ext+' ('+IntToStr(count)+')');
+    END;
+//    FOR i:=0 TO High(exts) DO
+//      combo_extension.Items.Add(exts[i]);
+    combo_extension.ItemIndex:=0;
+    combo_extensionClick(Self);
+  END;
+
+PROCEDURE TForm13.LoadFileNames;
+  VAR
+    Extension:String;
+    no_zero_bytes:Boolean;
+    pattern:String;
+    files:TStringArray;
+    i:LongWord;
+  BEGIN
+    Extension:=MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex],1,4);
+    pattern:='';
+    IF check_filtername.Checked THEN pattern:=edit_filtername.Text;
+    IF Extension='_All' THEN BEGIN
+      Extension:='';
+      FOR i:=0 TO High(RawListHandlers) DO BEGIN
+        IF Length(Extension)>0 THEN Extension:=Extension+',';
+        Extension:=Extension+RawListHandlers[i].Ext;
+      END;
+    END;
+
+    files:=OniDataConnection.GetFilesList(extension,pattern,TRUE);
+    list.Items.Clear;
+    IF Length(files)>0 THEN
+      FOR i:=0 TO High(files) DO
+        list.Items.Add(files[i]);
+    list_offset.Items.Clear;
+  END;
+
+PROCEDURE TForm13.panel_extensionResize(Sender: TObject);
+  BEGIN
+    combo_extension.Width:=panel_extension.Width-5;
+    edit_filtername.Width:=panel_extension.Width-5;
+  END;
+
+PROCEDURE TForm13.combo_extensionClick(Sender: TObject);
+  BEGIN
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm13.check_filternameClick(Sender: TObject);
+  BEGIN
+    edit_filtername.Enabled:=NOT check_filtername.Checked;
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm13.listClick(Sender: TObject);
+  VAR
+    mem:TMemoryStream;
+    data:Tdata;
+    i:LongWord;
+    offsets:TRawList;
+  BEGIN
+    IF hex.Modified THEN BEGIN
+      IF NOT Save THEN BEGIN
+        Exit;
+      END;
+    END;
+    ClearValues;
+    hex.DataSize:=0;
+    fileid:=OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]);
+    list_offset.Enabled:=True;
+    IF OniDataConnection.GetFileInfo(fileid).size>0 THEN BEGIN
+      offsets:=OniDataConnection.GetRawList(fileid);
+      list_offset.Items.Clear;
+      IF Length(offsets)>0 THEN BEGIN
+        FOR i:=0 TO High(offsets) DO BEGIN
+          list_offset.Items.Add('0x'+IntToHex(offsets[i].src_offset,8)+', '+IntToStr(offsets[i].raw_size)+' bytes');
+        END;
+      END ELSE BEGIN
+        list_offset.Enabled:=False;
+      END;
+    END ELSE BEGIN
+      list_offset.Enabled:=False;
+    END;
+  END;
+
+PROCEDURE TForm13.list_offsetClick(Sender: TObject);
+  VAR
+    i:LongWord;
+    raw_info:TRawInfo;
+  BEGIN
+    ClearValues;
+    dat_offset:=StrToInt('$'+MidStr(list_offset.Items.Strings[list_offset.ItemIndex],3,8));
+    LoadRaw(OniDataConnection.GetRawInfo(fileid,dat_offset));
+  END;
+
+
+
+
+FUNCTION IntToBin(value:Byte):String;
+  VAR i:Byte;
+  BEGIN
+    Result:='';
+    FOR i:=7 DOWNTO 0 DO BEGIN
+      Result:=Result+IntToStr((value SHR i) AND $01);
+    END;
+  END;
+
+FUNCTION TForm13.GetValue(datatype:Word; offset:LongWord):String;
+  VAR
+    data:Tdata;
+    i:Word;
+  BEGIN
+    CASE datatype OF
+      1: Result:=IntToStr(hex.data[offset]);
+      2: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256);
+      3: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256);
+      4: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256+hex.data[offset+3]*256*256*256);
+      5: Result:='0x'+IntToHex(hex.data[offset],2);
+      6: Result:='0x'+IntToHex(hex.data[offset]+hex.data[offset+1]*256,4);
+      7: Result:='0x'+IntToHex(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256,6);
+      8: Result:='0x'+IntToHex(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256+hex.data[offset+3]*256*256*256,8);
+      9: BEGIN
+          SetLength(data,4);
+          data[0]:=hex.data[offset];
+          data[1]:=hex.data[offset+1];
+          data[2]:=hex.data[offset+2];
+          data[3]:=hex.data[offset+3];
+          Result:=FloatToStr(Decode_Float(data));
+        END;
+      10: Result:=IntToBin(hex.data[offset]);
+      11: Result:='0x'+IntToHex(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256+hex.data[offset+3]*256*256*256,8);
+      10000..65535: BEGIN
+          Result:='';
+          FOR i:=1 TO datatype-10000 DO BEGIN
+            IF hex.Data[offset+i-1]>=32 THEN
+              Result:=Result+Chr(hex.Data[offset+i-1])
+            ELSE
+              Result:=Result+'.';
+          END;
+        END;
+    END;
+  END;
+
+PROCEDURE TForm13.ClearValues;
+  VAR
+    i:Byte;
+  BEGIN
+    FOR i:=1 TO value_viewer.RowCount-1 DO BEGIN
+      value_viewer.Cells[1,i]:='';
+    END;
+  END;
+
+PROCEDURE TForm13.WriteValues;
+  VAR
+    i,j:Byte;
+    data:Tdata;
+    str:String;
+    value:LongWord;
+  BEGIN
+    FOR i:=1 TO value_viewer.RowCount-1 DO BEGIN
+      IF value_viewer.Cells[0,i]='1 byte, unsigned' THEN BEGIN
+        IF ((hex.SelCount=1) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+1)>hex.DataSize) THEN BEGIN
+          value:=hex.Data[hex.SelStart];
+          value_viewer.Cells[1,i]:=IntToStr( value )+' / 0x'+IntToHex( value , 2 );
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='2 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=2) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+2)>hex.DataSize) THEN BEGIN
+          value:=hex.Data[hex.SelStart] + hex.Data[hex.SelStart+1]*256;
+          value_viewer.Cells[1,i]:=IntToStr( value )+' / 0x'+IntToHex( value , 4 );
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='4 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=4) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+4)>hex.DataSize) THEN BEGIN
+          value:=hex.Data[hex.SelStart]+hex.Data[hex.SelStart+1]*256+hex.Data[hex.SelStart+2]*256*256+hex.Data[hex.SelStart+3]*256*256*256;
+          value_viewer.Cells[1,i]:=IntToStr( value )+' / 0x'+IntToHex( value , 8 );
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='Bitset' THEN BEGIN
+        IF (hex.SelCount<=8) THEN BEGIN
+          IF hex.SelCount=0 THEN BEGIN
+            SetLength(data,1);
+            data[0]:=hex.Data[hex.SelStart];
+          END ELSE BEGIN
+            SetLength(data,hex.SelCount);
+            FOR j:=0 TO hex.SelCount-1 DO
+              data[j]:=hex.Data[hex.SelStart+j];
+          END;
+          value_viewer.Cells[1,i]:=DataToBin(data);
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='Float' THEN BEGIN
+        IF ((hex.SelCount=4) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+4)>hex.DataSize) THEN BEGIN
+          SetLength(data,4);
+          FOR j:=0 TO 3 DO
+            data[j]:=hex.Data[hex.SelStart+j];
+          value_viewer.Cells[1,i]:=FloatToStr(Decode_Float(data));
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='Selected length' THEN BEGIN
+        value_viewer.Cells[1,i]:=IntToStr(hex.SelCount)+' bytes';
+      END;
+      IF value_viewer.Cells[0,i]='String' THEN BEGIN
+        j:=0;
+        str:='';
+        IF hex.SelCount=0 THEN BEGIN
+          WHILE (hex.Data[hex.SelStart+j]>0) AND ((hex.SelStart+j)<hex.DataSize) DO BEGIN
+            IF hex.Data[hex.selstart+j]>=32 THEN
+              str:=str+Char(hex.Data[hex.SelStart+j])
+            ELSE
+              str:=str+'.';
+            Inc(j);
+          END;
+        END ELSE BEGIN
+          FOR j:=0 TO hex.SelCount-1 DO
+            IF hex.Data[hex.selstart+j]>=32 THEN
+              str:=str+Char(hex.Data[hex.SelStart+j])
+            ELSE
+              IF hex.Data[hex.selstart+j]>0 THEN
+                str:=str+'.'
+              ELSE
+                Break;
+        END;
+        value_viewer.Cells[1,i]:=str;
+      END;
+    END;
+  END;
+
+PROCEDURE TForm13.FormCreate(Sender: TObject);
+  BEGIN
+    Self.Caption:='';
+    fileid:=0;
+    value_viewer.ColCount:=2;
+    value_viewer.RowCount:=8;
+    value_viewer.FixedRows:=1;
+    value_viewer.Cells[0,0]:='Type';
+    value_viewer.Cells[1,0]:='Value';
+    value_viewer.Cells[0,1]:='1 byte, unsigned';
+    value_viewer.Cells[0,2]:='2 bytes, unsigned';
+    value_viewer.Cells[0,3]:='4 bytes, unsigned';
+    value_viewer.Cells[0,4]:='Bitset';
+    value_viewer.Cells[0,5]:='Float';
+    value_viewer.Cells[0,6]:='String';
+    value_viewer.Cells[0,7]:='Selected length';
+    value_viewer.ColWidths[0]:=100;
+    hex.Height:=panel_data.Height-190;
+    Self.panel_dataResize(Self);
+//
+    value_viewer.Font.Charset:=AppSettings.CharSet;
+//
+  END;
+
+FUNCTION TForm13.Save:Boolean;
+  VAR
+    mem:TMemoryStream;
+    data:Tdata;
+    i:LongWord;
+  BEGIN
+    CASE MessageBox(Self.Handle,PChar('Save changes to .raw-part of file '+OniDataConnection.GetFileInfo(fileid).FileName+'?'),PChar('Data changed...'),MB_YESNOCANCEL) OF
+      IDYES: BEGIN
+          mem:=TMemoryStream.Create;
+          hex.SaveToStream(mem);
+          mem.Seek(0,soFromBeginning);
+          SetLength(data,mem.Size);
+          mem.Read(data[0],mem.Size);
+          mem.Free;
+          OniDataConnection.UpdateRawFile(fileid_opened,dat_offset_opened,Length(data),@data[0]);
+          hex.Modified:=False;
+          FOR i:=0 TO hex.Datasize-1 DO hex.ByteChanged[i]:=False;
+          Result:=True;
+        END;
+      IDNO: Result:=True;
+      IDCANCEL: BEGIN
+          Result:=False;
+        END;
+    END;
+  END;
+
+PROCEDURE TForm13.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+  BEGIN
+    IF hex.Modified THEN BEGIN
+      IF NOT Save THEN CanClose:=False;
+    END;
+  END;
+
+PROCEDURE TForm13.FormResize(Sender: TObject);
+  BEGIN
+    IF Self.Width>=650 THEN BEGIN
+    END ELSE Self.Width:=650;
+    IF Self.Height>=450 THEN BEGIN
+    END ELSE Self.Height:=450;
+  END;
+
+PROCEDURE TForm13.panel_dataResize(Sender: TObject);
+  BEGIN
+    value_viewer.ColWidths[1]:=value_viewer.Width-value_viewer.ColWidths[0]-28;
+  END;
+
+PROCEDURE TForm13.hexChange(Sender: TObject);
+  BEGIN
+    ClearValues;
+    IF hex.DataSize>0 THEN BEGIN
+{      WriteStructureInfos(GetStructureInfoId(GetFileInfo(fileid).Extension));
+      WriteValues;
+}    END;
+  END;
+
+PROCEDURE TForm13.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+  VAR
+    temps: String;
+  BEGIN
+    IF (Shift=[ssCtrl]) AND (Key=Ord('C')) THEN BEGIN
+      IF hex.SelCount>0 THEN BEGIN
+        IF hex.InCharField THEN
+          Clipboard.AsText:=hex.SelectionAsText
+        ELSE
+          Clipboard.AsText:=hex.SelectionAsHex;
+      END;
+    END;
+    IF (Shift=[ssCtrl]) AND (Key=Ord('V')) THEN BEGIN
+{      temps:=Clipboard.AsText;
+      IF hex.SelStart+Length(temps)>hex.DataSize THEN
+        SetLength(temps, hex.DataSize-hex.SelStart);
+      hex.Sel
+      hex.SelCount:=Length(temps);
+      hex.ReplaceSelection(temps,Length(temps));
+}    END;
+  END;
+
+PROCEDURE TForm13.hexSelectionChanged(Sender: TObject);
+  VAR
+    selstart:Integer;
+    i,j:Word;
+  BEGIN
+{    FOR i:=1 TO structs.RowCount-1 DO BEGIN
+      FOR j:=0 TO structs.ColCount-1 DO BEGIN
+        structs.CellColors[j,i]:=clWhite;
+        structs.CellFontColors[j,i]:=clBlack;
+      END;
+    END;
+}    IF hex.DataSize>0 THEN BEGIN
+{      selstart:=hex.SelStart;
+      IF GetStructureInfoId(GetFileInfo(fileid).Extension)>=0 THEN BEGIN
+        WITH structure_infos[GetStructureInfoId(GetFileInfo(fileid).Extension)] DO BEGIN
+          FOR i:=0 TO High(entries) DO BEGIN
+            IF ((selstart-entries[i].offset)<GetTypeDataLength(entries[i].datatype)) AND ((selstart-entries[i].offset)>=0) THEN BEGIN
+              FOR j:=0 TO structs.ColCount-1 DO BEGIN
+                structs.CellColors[j,i+1]:=clBlue;
+                structs.CellFontColors[j,i+1]:=clWhite;
+              END;
+              structs.Row:=i+1;
+            END;
+          END;
+        END;
+      END;
+}      WriteValues;
+    END;
+  END;
+
+PROCEDURE TForm13.FormClose(Sender: TObject; var Action: TCloseAction);
+  BEGIN
+    Action:=caFree;
+  END;
+
+PROCEDURE TForm13.panel_imexportResize(Sender: TObject);
+  BEGIN
+    btn_import.Width:=panel_imexport.Width-8;
+    btn_export.Width:=panel_imexport.Width-8;
+  END;
+
+PROCEDURE TForm13.btn_exportClick(Sender: TObject);
+  VAR
+    fs:TFileStream;
+  BEGIN
+    saved.Filter:='Files of matching extension (*.'+OniDataConnection.GetFileInfo(fileid).Extension+')|*.'+OniDataConnection.GetFileInfo(fileid).Extension+'|All files|*.*';
+    saved.DefaultExt:=OniDataConnection.GetFileInfo(fileid).Extension;
+    IF saved.Execute THEN BEGIN
+      fs:=TFileStream.Create(saved.FileName,fmCreate);
+      hex.SaveToStream(fs);
+      fs.Free;
+    END;
+  END;
+
+PROCEDURE TForm13.btn_importClick(Sender: TObject);
+  VAR
+    data:Tdata;
+    fs:TFileStream;
+  BEGIN
+    opend.Filter:='Files of matching extension (*.'+OniDataConnection.GetFileInfo(fileid).Extension+')|*.'+OniDataConnection.GetFileInfo(fileid).Extension+'|All files|*.*';
+    IF opend.Execute THEN BEGIN
+      fs:=TFileStream.Create(opend.FileName,fmOpenRead);
+      IF fs.Size<>hex.DataSize THEN BEGIN
+        ShowMessage('Can''t import '+ExtractFilename(opend.FileName)+
+                    ', file has to have same size as file in .dat.'+CrLf+
+                    'Size of file in .dat: '+FormatFileSize(hex.datasize)+CrLf+
+                    'Size of chosen file: '+FormatFileSize(fs.Size));
+      END ELSE BEGIN
+        hex.LoadFromStream(fs);
+        hex.Modified:=True;
+      END;
+      fs.Free;
+    END;
+  END;
+
+PROCEDURE TForm13.value_viewer_contextPopup(Sender: TObject);
+  VAR
+    i:Byte;
+  BEGIN
+    FOR i:=0 TO value_viewer_context.Items.Count-1 DO
+      value_viewer_context.Items.Items[i].Visible:=False;
+    WITH value_viewer DO BEGIN
+      IF (Col=1) AND (Row>0) AND (Length(Cells[Col,Row])>0) THEN BEGIN
+        IF Pos(' byte',Cells[0,Row])=2 THEN BEGIN
+          value_viewer_context.Items.Find('Copy to &clipboard').Visible:=True;
+          value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible:=True;
+          value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible:=True;
+        END;
+        IF Pos('Float',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible:=True;
+        IF Pos('Bitset',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to clipboard (as &bitset)').Visible:=True;
+        IF Pos('String',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to clipboard (as &string)').Visible:=True;
+        IF Pos('Selected length',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to &clipboard').Visible:=True;
+      END;
+    END;
+  END;
+
+PROCEDURE TForm13.value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+  VAR
+    ACol,ARow:Integer;
+  BEGIN
+    IF Button=mbRight THEN BEGIN
+      value_viewer.MouseToCell(x,y,ACol,ARow);
+      IF ARow>0 THEN BEGIN
+        value_viewer.Col:=ACol;
+        value_viewer.Row:=ARow;
+      END;
+    END;
+  END;
+
+PROCEDURE TForm13.value_viewer_context_copyClick(Sender: TObject);
+  VAR
+    i:Byte;
+    name:String;
+    value:LongWord;
+  BEGIN
+    name:=TMenuItem(Sender).Name;
+    IF Pos('asstring',name)>0 THEN BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END ELSE
+    IF Pos('asfloat',name)>0 THEN BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END ELSE
+    IF Pos('asbitset',name)>0 THEN BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END ELSE
+    IF (Pos('ashex',name)>0) OR (Pos('asdec',name)>0) THEN BEGIN
+      IF value_viewer.Cells[0,value_viewer.Row]='1 byte, unsigned' THEN BEGIN
+        IF ((hex.SelCount=1) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+1)>hex.DataSize) THEN
+          value:=hex.Data[hex.SelStart];
+      END;
+      IF value_viewer.Cells[0,value_viewer.Row]='2 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=2) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+2)>hex.DataSize) THEN
+          value:=hex.Data[hex.SelStart] + hex.Data[hex.SelStart+1]*256;
+      END;
+      IF value_viewer.Cells[0,value_viewer.Row]='4 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=4) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+4)>hex.DataSize) THEN
+          value:=hex.Data[hex.SelStart]+hex.Data[hex.SelStart+1]*256+hex.Data[hex.SelStart+2]*256*256+hex.Data[hex.SelStart+3]*256*256*256;
+      END;
+      IF Pos('asdec',name)>0 THEN BEGIN
+        Clipboard.AsText:=IntToStr(value);
+      END ELSE BEGIN
+        IF value_viewer.Cells[0,value_viewer.Row]='1 byte, unsigned' THEN
+          Clipboard.AsText:='0x'+IntToHex(value,2);
+        IF value_viewer.Cells[0,value_viewer.Row]='2 bytes, unsigned' THEN
+          Clipboard.AsText:='0x'+IntToHex(value,4);
+        IF value_viewer.Cells[0,value_viewer.Row]='4 bytes, unsigned' THEN
+          Clipboard.AsText:='0x'+IntToHex(value,8);
+      END;
+    END ELSE BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END;
+  END;
+
+PROCEDURE TForm13.SetNewValue(datatype:Word; offset:LongWord; value:String);
+  VAR
+    data:Tdata;
+    value_int:LongWord;
+    value_float:Single;
+    i:Word;
+  BEGIN
+    CASE datatype OF
+      1..4: BEGIN
+              value_int:=StrToInt(value);
+              SetLength(data,datatype);
+              FOR i:=0 TO datatype-1 DO BEGIN
+                data[i]:=value_int MOD 256;
+                value_int:=value_int DIV 256;
+              END;
+            END;
+      5..8: BEGIN
+              value_int:=StrToInt('$'+value);
+              SetLength(data,datatype-4);
+              FOR i:=0 TO datatype-5 DO BEGIN
+                data[i]:=value_int MOD 256;
+                value_int:=value_int DIV 256;
+              END;
+            END;
+      9:    BEGIN
+              value_float:=StrToFloat(value);
+              data:=Encode_Float(value_float);
+            END;
+      10:   BEGIN
+              value_int:=BinToInt(value);
+              SetLength(data,1);
+              data[0]:=value_int;
+            END;
+      10000..65535: BEGIN
+              SetLength(data,datatype-10000);
+              FOR i:=1 TO datatype-10000 DO BEGIN
+                IF i<=Length(value) THEN
+                  data[i-1]:=Ord(value[i])
+                ELSE
+                  data[i-1]:=0;
+              END;
+            END;
+    END;
+    FOR i:=0 TO High(data) DO BEGIN
+      IF hex.Data[offset+i]<>data[i] THEN hex.ByteChanged[offset+i]:=True;
+      hex.Data[offset+i]:=data[i];
+    END;
+    hex.Modified:=True;
+    hexChange(Self);
+    hex.Repaint;
+  END;
+
+PROCEDURE TForm13.value_viewerDblClick(Sender: TObject);
+  VAR
+    offset:LongWord;
+    datatype:Word;
+    objectname:String;
+    value:String;
+  BEGIN
+    IF (value_viewer.Col=1) AND (Length(value_viewer.Cells[1,value_viewer.Row])>0) THEN BEGIN
+      offset:=hex.SelStart;
+      IF value_viewer.Cells[0,value_viewer.Row]='1 byte, unsigned' THEN
+        datatype:=1;
+      IF value_viewer.Cells[0,value_viewer.Row]='2 bytes, unsigned' THEN
+        datatype:=2;
+      IF value_viewer.Cells[0,value_viewer.Row]='4 bytes, unsigned' THEN
+        datatype:=4;
+      IF value_viewer.Cells[0,value_viewer.Row]='Bitset' THEN
+        datatype:=10;
+      IF value_viewer.Cells[0,value_viewer.Row]='Float' THEN
+        datatype:=9;
+      IF value_viewer.Cells[0,value_viewer.Row]='Selected length' THEN
+        Exit;
+      IF value_viewer.Cells[0,value_viewer.Row]='String' THEN BEGIN
+        IF hex.SelCount>0 THEN
+          datatype:=10000+hex.SelCount
+        ELSE
+          datatype:=10000+Length(value_viewer.Cells[1,value_viewer.Row]);
+      END;
+      objectname:='';
+      value:=GetValue(datatype,offset);
+      Form12.MakeVarInput(objectname,offset,datatype,value,Self);
+    END;
+  END;
+
+PROCEDURE TForm13.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+  BEGIN
+    IF (Shift=[ssCtrl]) AND (Key=83) THEN
+      IF hex.Modified THEN
+        IF NOT Save THEN
+          Exit;
+  END;
+
+END.
Index: /oup/current/Unit14_settings.dfm
===================================================================
--- /oup/current/Unit14_settings.dfm	(revision 10)
+++ /oup/current/Unit14_settings.dfm	(revision 10)
@@ -0,0 +1,113 @@
+object Form14: TForm14
+  Left = 0
+  Top = 0
+  BorderStyle = bsToolWindow
+  Caption = 'Settings'
+  ClientHeight = 357
+  ClientWidth = 321
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poMainFormCenter
+  OnCloseQuery = FormCloseQuery
+  OnShow = FormShow
+  PixelsPerInch = 96
+  TextHeight = 13
+  object label_charset: TLabel
+    Left = 8
+    Top = 39
+    Width = 145
+    Height = 26
+    AutoSize = False
+    Caption = 'CharSet for displaying strings in ValueViewer/StructViewer:'
+    WordWrap = True
+  end
+  object check_filesashex: TCheckBox
+    Left = 8
+    Top = 8
+    Width = 145
+    Height = 17
+    Caption = 'Show filenumbers as Hex'
+    TabOrder = 0
+  end
+  object btn_ok: TButton
+    Left = 8
+    Top = 319
+    Width = 57
+    Height = 23
+    Caption = 'OK'
+    Default = True
+    TabOrder = 1
+    OnClick = btn_okClick
+  end
+  object btn_cancel: TButton
+    Left = 120
+    Top = 319
+    Width = 57
+    Height = 23
+    Cancel = True
+    Caption = 'Cancel'
+    TabOrder = 2
+    OnClick = btn_cancelClick
+  end
+  object btn_register_oldb: TButton
+    Left = 8
+    Top = 184
+    Width = 169
+    Height = 25
+    Caption = 'Register .oldb files with OUP'
+    TabOrder = 3
+    OnClick = btn_register_oldbClick
+  end
+  object btn_register_opf: TButton
+    Left = 8
+    Top = 215
+    Width = 169
+    Height = 25
+    Caption = 'Register .opf files with OUP'
+    TabOrder = 4
+    OnClick = btn_register_opfClick
+  end
+  object btn_register_dat: TButton
+    Left = 8
+    Top = 153
+    Width = 169
+    Height = 25
+    Caption = 'Register .dat files with OUP'
+    TabOrder = 5
+    OnClick = btn_register_datClick
+  end
+  object combo_charset: TComboBox
+    Left = 160
+    Top = 40
+    Width = 156
+    Height = 21
+    Style = csDropDownList
+    ItemHeight = 13
+    ItemIndex = 0
+    TabOrder = 6
+    Text = 'default - 1'
+    Items.Strings = (
+      'default - 1'
+      'Arabic - 178'
+      'Baltic - 186'
+      'ChineseBig5 - 136'
+      'EastEurope - 238'
+      'Greek - 161'
+      'Russian - 204'
+      'Thai - 222'
+      'Turkish - 162')
+  end
+  object check_hideunused: TCheckBox
+    Left = 8
+    Top = 79
+    Width = 209
+    Height = 17
+    Caption = 'Hide "Unused" data in StructureViewer'
+    TabOrder = 7
+  end
+end
Index: /oup/current/Unit14_settings.pas
===================================================================
--- /oup/current/Unit14_settings.pas	(revision 10)
+++ /oup/current/Unit14_settings.pas	(revision 10)
@@ -0,0 +1,167 @@
+unit Unit14_settings;
+interface
+uses
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, StrUtils, Grids, Wrapgrid;
+
+type
+  TForm14 = class(TForm)
+    check_filesashex: TCheckBox;
+    btn_ok: TButton;
+    btn_cancel: TButton;
+    btn_register_oldb: TButton;
+    btn_register_opf: TButton;
+    btn_register_dat: TButton;
+    label_charset: TLabel;
+    combo_charset: TComboBox;
+    check_hideunused: TCheckBox;
+    procedure btn_register_opfClick(Sender: TObject);
+    procedure btn_register_oldbClick(Sender: TObject);
+    procedure btn_register_datClick(Sender: TObject);
+    procedure btn_cancelClick(Sender: TObject);
+    procedure btn_okClick(Sender: TObject);
+    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+    procedure FormShow(Sender: TObject);
+    function RegisterExtension(ext:String):Integer;
+  private
+  public
+  end;
+
+var
+  Form14: TForm14;
+
+implementation
+{$R *.dfm}
+uses
+  Unit1_main, Unit3_data, ftypesAPI;
+
+function ExtensionRegistered(ext:String; var RegisteredAs:String):Boolean;
+  var
+    ftr:TFileTypeRegistration;
+  begin
+    ftr:=TFileTypeRegistration.Create;
+    if(ftr <> nil) then begin
+      try
+        RegisteredAs:=ftr.GetInternalKey(ext);
+        if RegisteredAs<>'' then
+          Result:=True
+        else
+          Result:=False;
+      finally
+        ftr.Free;
+      end;
+    end;
+  end;
+
+function TForm14.RegisterExtension(ext:String):Integer;
+  var
+    ftr:TFileTypeRegistration;
+    temps:String;
+    warnmsg:String;
+  begin
+    Result:=-1;
+    if ExtensionRegistered(ext,temps) then begin
+      if temps<>'ONI'+ext then begin
+        warnmsg:=ext+'-files are not registered to OUP but as "'+temps+'"-files.'+#13+#10+
+                 'Do you really want to unregister'+ext+'-files?';
+        if MessageBox(Self.Handle, PChar(warnmsg),PChar('Warning'),MB_YESNO)=ID_NO then
+          Exit;
+      end;
+      ftr:=TFileTypeRegistration.Create;
+      if ftr<>nil then
+        try
+          if not ftr.UnregisterExtension(ext) then
+            ShowMessage('Could not unregister '+ext+'-files')
+          else
+            Result:=2;
+        finally
+          ftr.Free;
+        end;
+    end else begin
+      ftr:=TFileTypeRegistration.Create;
+      if ftr<>nil then begin
+        try
+          if ftr.RegisterType(ext,'ONI'+ext,'ONI '+ext+'-file',Application.EXEname+',1') then begin
+            ftr.AddHandler('open','"'+Application.EXEname+'" '+MidStr(ext,2,Length(ext)-1)+' "%1"');
+            ftr.SetDefaultHandler;
+            Result:=1;
+          end;
+        finally
+          ftr.Free;
+        end;
+      end;
+    end;
+  end;
+
+procedure TForm14.btn_cancelClick(Sender: TObject);
+  begin
+    Self.Close;
+  end;
+
+procedure TForm14.btn_okClick(Sender: TObject);
+  begin
+    AppSettings.FilenumbersAsHex:=check_filesashex.Checked;
+    AppSettings.CharSet:=StrToInt(MidStr(combo_charset.Items.Strings[combo_charset.ItemIndex],Pos(' ',combo_charset.Items.Strings[combo_charset.ItemIndex])+3,Length(combo_charset.Items.Strings[combo_charset.ItemIndex])-Pos(' ',combo_charset.Items.Strings[combo_charset.ItemIndex])-2));
+    AppSettings.HideUnusedData:=check_hideunused.Checked;
+
+    Self.Close;
+  end;
+
+procedure TForm14.btn_register_datClick(Sender: TObject);
+  begin
+    case RegisterExtension('.dat') of
+      2: btn_register_dat.Caption:='Register .dat files with OUP';
+      1: btn_register_dat.Caption:='Unregister .dat files';
+    end;
+  end;
+
+procedure TForm14.btn_register_oldbClick(Sender: TObject);
+  begin
+    case RegisterExtension('.oldb') of
+      2: btn_register_oldb.Caption:='Register .oldb files with OUP';
+      1: btn_register_oldb.Caption:='Unregister .oldb files';
+    end;
+  end;
+
+procedure TForm14.btn_register_opfClick(Sender: TObject);
+  begin
+    case RegisterExtension('.opf') of
+      2: btn_register_opf.Caption:='Register .opf files with OUP';
+      1: btn_register_opf.Caption:='Unregister .opf files';
+    end;
+  end;
+
+procedure TForm14.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+  begin
+    CanClose:=False;
+    Self.Visible:=False;
+    Form1.Enabled:=True;
+    Form1.SetFocus;
+  end;
+
+procedure TForm14.FormShow(Sender: TObject);
+  var
+    temps:String;
+    i:Byte;
+  begin
+    if ExtensionRegistered('.dat',temps) then
+      btn_register_dat.Caption:='Unregister .dat files'
+    else
+      btn_register_dat.Caption:='Register .dat files with OUP';
+    if ExtensionRegistered('.oldb',temps) then
+      btn_register_oldb.Caption:='Unregister .oldb files'
+    else
+      btn_register_oldb.Caption:='Register .oldb files with OUP';
+    if ExtensionRegistered('.opf',temps) then
+      btn_register_opf.Caption:='Unregister .opf files'
+    else
+      btn_register_opf.Caption:='Register .opf files with OUP';
+    check_filesashex.Checked:=AppSettings.FilenumbersAsHex;
+    check_hideunused.Checked:=AppSettings.HideUnusedData;
+
+    for i:=0 to combo_charset.Items.Count-1 do
+      if StrToInt(MidStr(combo_charset.Items.Strings[i],Pos(' ',combo_charset.Items.Strings[i])+3,Length(combo_charset.Items.Strings[i])-Pos(' ',combo_charset.Items.Strings[i])-2))=AppSettings.CharSet then
+        combo_charset.ItemIndex:=i;
+  end;
+
+end.
Index: /oup/current/Unit15_Classes.pas
===================================================================
--- /oup/current/Unit15_Classes.pas	(revision 10)
+++ /oup/current/Unit15_Classes.pas	(revision 10)
@@ -0,0 +1,1058 @@
+unit Unit15_Classes;
+interface
+uses Unit3_data, Unit9_data_structures, Classes, SysUtils, StrUtils, Dialogs, ABSDecUtil, ABSMain, DB;
+
+
+type
+  TOniData = class
+    private
+      FFileName:String;
+      FLevelInfo:TLevelInfo;
+      FBackend:Integer;
+      Fos_mac:Boolean;
+    protected
+    public
+      property FileName:String read FFileName write FFileName;
+      property Backend:Integer read FBackend write FBackend;
+      property OSisMac:Boolean read Fos_mac write Fos_mac;
+      property LevelInfo:TLevelinfo read FLevelInfo write FLevelInfo;
+
+      constructor Create(filename:String; var Result:Boolean); virtual; abstract;
+      procedure Close; virtual; abstract;
+
+      function GetFileInfo(fileid:LongWord):TFileInfo; virtual; abstract;
+      function GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray; virtual; abstract;
+      function GetFilesCount:LongWord; virtual; abstract;
+      function GetExtensionsList:TStringArray; virtual; abstract;
+      function GetExtendedExtensionsList:TExtensionsMap; virtual; abstract;
+      function ExtractFileID(name:String):Integer;
+      function GetFileIDByName(name:String):Integer;
+
+      function LoadDatFile(fileid:LongWord):Tdata; virtual; abstract;
+      procedure UpdateDatFile(fileid:LongWord; data:Tdata); virtual; abstract;
+      procedure LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer); virtual; abstract;
+      procedure UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer); virtual; abstract;
+
+      function GetRawList(fileid:LongWord):TRawList; virtual; abstract;
+      function GetRawInfo(fileid,dat_offset:LongWord):TRawInfo;
+      procedure LoadRawFile(fileid,dat_offset:LongWord; target:Pointer); virtual; abstract;
+      procedure UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer); virtual; abstract;
+      procedure LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); virtual; abstract;
+      procedure UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); virtual; abstract;
+      function AppendRawFile(loc_sep:Boolean; size:LongWord; target:Pointer):LongWord; virtual; abstract;//Returns new Address
+    published
+  end;
+
+  TOniDataDat = class(TOniData)
+    private
+      Fdat_file:TFileStream;
+      Fraw_file:TFileStream;
+      Fsep_file:TFileStream;
+      Fdat_header:THeader;
+      Fdat_filesmap:TFilesMap;
+      Fdat_files:TFiles;
+      Fdat_namedfilesmap:TNamedFilesMap;
+      Fdat_extensionsmap:TExtensionsMap;
+      FUnloadWhenUnused:Boolean;
+      FDatOpened:Boolean;
+      FRawOpened:Boolean;
+      FSepOpened:Boolean;
+    protected
+    public
+      property UnloadWhenUnused:Boolean read FUnloadWhenUnused write FUnloadWhenUnused;
+
+      constructor Create(DatFilename:String; var Result:Boolean); override;
+      procedure Close; override;
+
+      function GetFileInfo(fileid:LongWord):TFileInfo; override;
+      function GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray; override;
+      function GetFilesCount:LongWord; override;
+      function GetExtensionsList:TStringArray; override;
+      function GetExtendedExtensionsList:TExtensionsMap; override;
+
+      function LoadDatFile(fileid:LongWord):Tdata; override;
+      procedure UpdateDatFile(fileid:LongWord; data:Tdata); override;
+      procedure LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
+      procedure UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
+
+      procedure LoadRawOffset(loc_sep:Boolean; raw_addr,size:LongWord; target:Pointer);
+      function GetRawList(fileid:LongWord):TRawList; override;
+      procedure LoadRawFile(fileid,dat_offset:LongWord; target:Pointer); override;
+      procedure UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer); override;
+      procedure LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
+      procedure UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
+      function AppendRawFile(loc_sep:Boolean; size:LongWord; target:Pointer):LongWord; override;//Returns new Address
+    published
+  end;
+
+  TOniDataADB = class(TOniData)
+    private
+      FDatabase:TABSDatabase;
+      FQuery:TABSQuery;
+    protected
+    public
+      constructor Create(OLDBFilename:String; var Result:Boolean); override;
+      procedure Close; override;
+
+//      function GetDatLinks(srcid:LongWord):TDatLinks;
+      function GetFileInfo(fileid:LongWord):TFileInfo; override;
+      function GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray; override;
+      function GetFilesCount:LongWord; override;
+      function GetExtensionsList:TStringArray; override;
+      function GetExtendedExtensionsList:TExtensionsMap; override;
+      function GetNamedFilesMap:TNamedFilesMap;
+
+      function LoadDatFile(fileid:LongWord):Tdata; override;
+      procedure UpdateDatFile(fileid:LongWord; data:Tdata); override;
+      procedure LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
+      procedure UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer); override;
+
+      function GetRawList(fileid:LongWord):TRawList; override;
+      procedure LoadRawFile(fileid,dat_offset:LongWord; target:Pointer); override;
+      procedure UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer); override;
+      procedure LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
+      procedure UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer); override;
+    published
+  end;
+
+
+const
+  ODB_None=-1;
+  ODB_Dat=0;
+  ODB_ADB=1;
+
+var
+  OniDataConnection:TOniData;
+
+function CreateDataConnection(filename:String; backend:Integer):Boolean;
+procedure CloseDataConnection;
+
+
+
+
+implementation
+uses Unit2_Functions;
+
+
+
+(*
+  Implementation of  TOniData
+*)
+
+function TOniData.GetFileIDByName(name:String):Integer;
+  var
+    files:TStringArray;
+    i: Integer;
+  begin
+    Result:=-1;
+    files:=Self.GetFilesList('',name,false);
+    if Length(files)>0 then
+      for i:=0 to High(files) do
+        if Pos(name,files[i])=Pos('-',files[i])+1 then begin
+//        if MidStr(files[i],Pos('-',files[i])+1,Length(files[i])-Pos('-',files[i])-5)=name then begin
+          Result:=Self.ExtractFileID(files[i]);
+          Break;
+        end;
+  end;
+
+function TOniData.ExtractFileID(name:String):Integer;
+  begin
+    if name[5]='-' then
+      Result:=HexToLong(MidStr(name,1,4))
+    else
+      Result:=StrToInt(MidStr(name,1,5));
+  end;
+
+function TOniData.GetRawInfo(fileid,dat_offset:LongWord):TRawInfo;
+  var
+    i:LongWord;
+    raw_list:TRawList;
+  begin
+    raw_list:=Self.GetRawList(fileid);
+    Result.src_id:=0;
+    Result.src_offset:=0;
+    Result.raw_addr:=0;
+    Result.raw_size:=0;
+    for i:=0 to High(raw_list) do begin
+      if raw_list[i].src_offset=dat_offset then begin
+        Result.src_id:=fileid;
+        Result.src_offset:=raw_list[i].src_offset;
+        Result.raw_addr:=raw_list[i].raw_addr;
+        Result.raw_size:=raw_list[i].raw_size;
+        Result.loc_sep:=raw_list[i].loc_sep;
+        Break;
+      end;
+    end;
+  end;
+
+
+
+
+
+
+
+(*
+================================================================================
+                      Implementation of  TOniDataDat
+*)
+
+constructor TOniDataDat.Create(DatFilename:String; var Result:Boolean);
+  const
+    header_ident1_pc:Array[0..$13] of Byte=
+        ($1F,$27,$DC, $33,  $DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
+    header_ident1_mac:Array[0..$13] of Byte=
+        ($61,$30,$C1, $23,  $DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
+    header_ident1_macbeta:Array[0..$13] of Byte=
+        ($81,$11,$8D, $23,  $DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
+    header_ident2:Array[0..$F] of Byte=
+        ($99,$CF,$40,$00,$90,$4F,$63,$00,$F4,$55,$5F,$00,$90,$4F,$63,$00);
+  var
+    i:LongWord;
+    header_pc,header_mac:Boolean;
+  begin
+    FUnloadWhenUnused:=True;
+    FDatOpened:=False;
+    FRawOpened:=False;
+    if not FileExists(DatFilename) then begin
+      ShowMessage('File doesn''t exist!!!');
+      Result:=False;
+      Exit;
+    end;
+    FFileName:=DatFilename;
+    Fdat_file:=TFileStream.Create(FFileName, fmOpenRead);
+    Fdat_file.Read(Fdat_header,SizeOf(Fdat_header));
+    header_pc:=True;
+    header_mac:=True;
+    for i:=0 to High(Fdat_header.Ident) do begin
+      FLevelInfo.Ident[i]:=Fdat_header.Ident[i];
+      if Fdat_header.Ident[i]<>header_ident1_pc[i] then
+        header_pc:=False;
+      if Fdat_header.Ident[i]<>header_ident1_mac[i] then
+        header_mac:=False;
+    end;
+    if not (header_pc xor header_mac) then begin
+      Result:=False;
+      Exit;
+    end else begin
+      if (header_pc and not header_mac) then
+        Fos_mac:=False
+      else
+        Fos_mac:=True;
+    end;
+    SetLength(Fdat_filesmap,Fdat_header.Files);
+    SetLength(Fdat_files,Fdat_header.Files);
+    for i:=0 to Fdat_header.Files-1 do
+      Fdat_file.Read(Fdat_filesmap[i],SizeOf(Fdat_filesmap[i]));
+    for i:=0 to Fdat_header.Files-1 do begin
+      Fdat_files[i].Extension:=Fdat_filesmap[i].Extension;
+      Fdat_files[i].Extension:=ReverseString(Fdat_files[i].Extension);
+      Fdat_files[i].Size:=Fdat_filesmap[i].FileSize;
+      Fdat_files[i].FileType:=Fdat_filesmap[i].FileType;
+      Fdat_files[i].DatAddr:=Fdat_filesmap[i].DataAddr-8+Fdat_header.DataAddr;
+      if (Fdat_filesmap[i].FileType and $01)=0 then begin
+        Fdat_file.Seek(Fdat_filesmap[i].NameAddr+Fdat_header.NamesAddr,soFromBeginning);
+        SetLength(Fdat_files[i].Name,100);
+        Fdat_file.Read(Fdat_files[i].Name[1],100);
+        Fdat_files[i].Name:=MidStr(Fdat_files[i].Name,1+4,Pos(#0,Fdat_files[i].Name)-1-4);
+      end else begin
+        Fdat_files[i].Name:='';
+      end;
+      Fdat_files[i].FileName:=FormatNumber(i,5,'0')+'-'+Fdat_files[i].Name+'.'+Fdat_files[i].Extension;
+      Fdat_files[i].FileNameHex:=IntToHex(i,4)+'-'+Fdat_files[i].Name+'.'+Fdat_files[i].Extension;
+    end;
+    Fdat_file.Seek($40+Fdat_header.Files*$14,soFromBeginning);
+    SetLength(Fdat_namedfilesmap,Fdat_header.NamedFiles);
+    for i:=0 to Fdat_header.NamedFiles-1 do
+      Fdat_file.Read(Fdat_namedfilesmap[i],SizeOf(Fdat_namedfilesmap[i]));
+
+    Fdat_file.Seek($40+Fdat_header.Files*$14+Fdat_header.NamedFiles*$8,soFromBeginning);
+    SetLength(Fdat_extensionsmap,Fdat_header.Extensions);
+    for i:=0 to Fdat_header.Extensions-1 do
+      Fdat_file.Read(Fdat_extensionsmap[i],SizeOf(Fdat_extensionsmap[i]));
+
+    Fdat_file.Seek(Fdat_files[0].DatAddr+7,soFromBeginning);
+    Fdat_file.Read(FLevelInfo.LevelNumber,1);
+    FLevelInfo.LevelNumber:=FLevelInfo.LevelNumber DIV 2;
+
+    Fdat_file.Free;
+
+    Result:=True;
+    FBackend:=ODB_Dat;
+  end;
+
+procedure TOniDataDat.Close;
+  begin
+    if not FUnloadWhenUnused and FDatOpened then
+      Fdat_file.Free;
+    if not FUnloadWhenUnused and FRawOpened then
+      Fraw_file.Free;
+    if not FUnloadWhenUnused and FSepOpened then
+      Fsep_file.Free;
+    Self.Free;
+  end;
+
+
+
+function TOniDataDat.GetFileInfo(fileid:LongWord):TFileInfo;
+  begin
+    if fileid<Self.GetFilesCount then
+      Result:=Fdat_files[fileid]
+    else
+      Result.ID:=-1;
+  end;
+
+function TOniDataDat.GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray;
+  var
+    i:LongWord;
+  begin
+    SetLength(Result,0);
+    for i:=0 to Fdat_header.Files-1 do begin
+      if ( (Length(ext)=0) or (Pos(Fdat_files[i].Extension,ext)>0) ) and
+          ( (Length(pattern)=0) or (Pos(UpperCase(pattern),UpperCase(Fdat_files[i].Name))>0) ) then begin
+          if (NoEmptyFiles=false) or ((Fdat_files[i].FileType and $02)=0) then begin
+            SetLength(Result,Length(Result)+1);
+            if AppSettings.FilenumbersAsHex then
+              Result[High(Result)]:=Fdat_files[i].FileNameHex
+            else
+              Result[High(Result)]:=Fdat_files[i].FileName;
+          end;
+      end;
+    end;
+  end;
+
+function TOniDataDat.GetFilesCount:LongWord;
+  begin
+    Result:=Fdat_header.Files;
+  end;
+
+function TOniDataDat.GetExtensionsList:TStringArray;
+  var
+    i:LongWord;
+  begin
+    SetLength(Result,Fdat_header.Extensions);
+    for i:=0 to Fdat_header.Extensions-1 do begin
+      with Fdat_extensionsmap[i] do begin
+        Result[i]:=Extension[3]+Extension[2]+Extension[1]+Extension[0]+' ('+IntToStr(ExtCount)+')';
+      end;
+    end;
+  end;
+
+function TOniDataDat.GetExtendedExtensionsList:TExtensionsMap;
+  var
+    i:LongWord;
+  begin
+    SetLength(Result,Fdat_header.Extensions);
+    for i:=0 to Fdat_header.Extensions-1 do begin
+      Result[i]:=Fdat_extensionsmap[i];
+    end;
+  end;
+
+
+function TOniDataDat.LoadDatFile(fileid:LongWord):Tdata;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      if FUnloadWhenUnused or not FDatOpened then
+        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
+      Fdat_file.Seek(Fdat_files[fileid].DatAddr,soFromBeginning);
+      SetLength(Result,Fdat_files[fileid].Size);
+      Fdat_file.Read(Result[0],Fdat_files[fileid].Size);
+      if UnloadWhenUnused then
+        Fdat_file.Free
+      else
+        FDatOpened:=True;
+    end;
+  end;
+
+procedure TOniDataDat.UpdateDatFile(fileid:LongWord; data:Tdata);
+  begin
+    if fileid<Self.GetFilesCount then begin
+      if FUnloadWhenUnused or not FDatOpened then
+        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
+      Fdat_file.Seek(Fdat_files[fileid].DatAddr,soFromBeginning);
+      Fdat_file.Write(data[0],Length(data));
+      if UnloadWhenUnused then
+        Fdat_file.Free
+      else
+        FDatOpened:=True;
+    end;
+  end;
+
+procedure TOniDataDat.LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer);
+  begin
+    if fileid<Self.GetFilesCount then begin
+      if FUnloadWhenUnused or not FDatOpened then
+        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
+      Fdat_file.Seek(Fdat_files[fileid].DatAddr+offset,soFromBeginning);
+      Fdat_file.Read(target^,size);
+      if UnloadWhenUnused then
+        Fdat_file.Free
+      else
+        FDatOpened:=True;
+    end;
+  end;
+
+procedure TOniDataDat.UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer);
+  begin
+    if fileid<Self.GetFilesCount then begin
+      if FUnloadWhenUnused or not FDatOpened then
+        Fdat_file:=TFileStream.Create(FFileName, fmOpenReadWrite);
+      Fdat_file.Seek(Fdat_files[fileid].DatAddr+offset,soFromBeginning);
+      Fdat_file.Write(target^,size);
+      if UnloadWhenUnused then
+        Fdat_file.Free
+      else
+        FDatOpened:=True;
+    end;
+  end;
+
+
+
+function TOniDataDat.GetRawList(fileid:LongWord):TRawList;
+  var
+    i:LongWord;
+  begin
+    SetLength(Result,0);
+    for i:=0 to High(RawListHandlers) do
+      if UpperCase(RawListHandlers[i].Ext)=UpperCase(Fdat_files[fileid].extension) then
+        if RawListHandlers[i].needed then begin
+          Result:=RawListHandlers[i].Handler(fileid);
+          Break;
+        end else
+          Break;
+  end;
+
+procedure TOniDataDat.LoadRawOffset(loc_sep:Boolean; raw_addr,size:LongWord; target:Pointer);
+  begin
+    if not loc_sep then begin
+      if FUnloadWhenUnused or not FRawOpened then
+        Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
+      if raw_addr<=Fraw_file.Size then begin
+        Fraw_file.Seek(raw_addr,soFromBeginning);
+        Fraw_file.Read(target^,size);
+      end;
+      if UnloadWhenUnused then
+        Fraw_file.Free
+      else
+        FRawOpened:=True
+    end else begin
+      if FUnloadWhenUnused or not FSepOpened then
+        Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
+      if raw_addr<=Fsep_file.Size then begin
+        Fsep_file.Seek(raw_addr,soFromBeginning);
+        Fsep_file.Read(target^,size);
+      end;
+      if UnloadWhenUnused then
+        Fsep_file.Free
+      else
+        FSepOpened:=True;
+    end;
+  end;
+
+procedure TOniDataDat.LoadRawFile(fileid,dat_offset:LongWord; target:Pointer);
+  var
+    raw_info:TRawInfo;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      raw_info:=Self.GetRawInfo(fileid,dat_offset);
+      if not raw_info.loc_sep then begin
+        if FUnloadWhenUnused or not FRawOpened then
+          Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
+        Fraw_file.Seek(raw_info.raw_addr,soFromBeginning);
+        Fraw_file.Read(target^,raw_info.raw_size);
+        if UnloadWhenUnused then
+          Fraw_file.Free
+        else
+          FRawOpened:=True
+      end else begin
+        if FUnloadWhenUnused or not FSepOpened then
+          Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
+        Fsep_file.Seek(raw_info.raw_addr,soFromBeginning);
+        Fsep_file.Read(target^,raw_info.raw_size);
+        if UnloadWhenUnused then
+          Fsep_file.Free
+        else
+          FSepOpened:=True;
+      end;
+    end;
+  end;
+
+procedure TOniDataDat.UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer);
+  var
+    raw_info:TRawInfo;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      raw_info:=Self.GetRawInfo(fileid,dat_offset);
+      if not raw_info.loc_sep then begin
+        if FUnloadWhenUnused or not FRawOpened then
+          Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
+        Fraw_file.Seek(raw_info.raw_addr,soFromBeginning);
+        Fraw_file.Write(target^,raw_info.raw_size);
+        if UnloadWhenUnused then
+          Fraw_file.Free
+        else
+          FRawOpened:=True
+      end else begin
+        if FUnloadWhenUnused or not FSepOpened then
+          Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
+        Fsep_file.Seek(raw_info.raw_addr,soFromBeginning);
+        Fsep_file.Write(target^,raw_info.raw_size);
+        if UnloadWhenUnused then
+          Fsep_file.Free
+        else
+          FSepOpened:=True;
+      end;
+    end;
+  end;
+
+procedure TOniDataDat.LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
+  var
+    raw_info:TRawInfo;
+    data:Tdata;
+    mem:TMemoryStream;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      raw_info:=Self.GetRawInfo(fileid,dat_offset);
+      SetLength(data, raw_info.raw_size);
+      Self.LoadRawFile(fileid,dat_offset,@data[0]);
+      mem:=TMemoryStream.Create;
+      mem.Write(data[offset],size);
+      mem.Read(target^,size);
+      mem.Free;
+    end;
+  end;
+
+procedure TOniDataDat.UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
+  var
+    raw_info:TRawInfo;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      raw_info:=Self.GetRawInfo(fileid,dat_offset);
+      if not raw_info.loc_sep then begin
+        if FUnloadWhenUnused or not FRawOpened then
+          Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
+        Fraw_file.Seek(raw_info.raw_addr+offset,soFromBeginning);
+        Fraw_file.Write(target^,raw_info.raw_size);
+        if UnloadWhenUnused then
+          Fraw_file.Free
+        else
+          FRawOpened:=True
+      end else begin
+        if FUnloadWhenUnused or not FSepOpened then
+          Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
+        Fsep_file.Seek(raw_info.raw_addr+offset,soFromBeginning);
+        Fsep_file.Write(target^,raw_info.raw_size);
+        if UnloadWhenUnused then
+          Fsep_file.Free
+        else
+          FSepOpened:=True;
+      end;
+    end;
+  end;
+
+function TOniDataDat.AppendRawFile(loc_sep:Boolean; size:LongWord; target:Pointer):LongWord; //Returns new Address
+  begin
+    if not loc_sep then begin
+      if FUnloadWhenUnused or not FRawOpened then
+        Fraw_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.raw'),fmOpenReadWrite);
+      Result:=Fraw_file.Size;
+      Fraw_file.Seek(0,soFromEnd);
+      Fraw_file.Write(target^,size);
+      if UnloadWhenUnused then
+        Fraw_file.Free
+      else
+        FRawOpened:=True
+    end else begin
+      if FUnloadWhenUnused or not FSepOpened then
+        Fsep_file:=TFileStream.Create(AnsiReplaceStr(FFileName,'.dat','.sep'),fmOpenReadWrite);
+      Result:=Fsep_file.Size;
+      Fsep_file.Seek(0,soFromEnd);
+      Fsep_file.Write(target^,size);
+      if UnloadWhenUnused then
+        Fsep_file.Free
+      else
+        FSepOpened:=True;
+    end;
+  end;
+
+
+
+
+
+
+
+
+
+
+
+(*
+================================================================================
+                     Implementation of  TOniDataADB
+*)
+
+constructor TOniDataADB.Create(OLDBFilename:String; var Result:Boolean);
+  var
+    i,j:Byte;
+    temps:String;
+  begin
+    if not FileExists(OLDBFilename) then begin
+      ShowMessage('File doesn''t exist!!!');
+      Result:=False;
+      Exit;
+    end;
+    FFileName:=OLDBFilename;
+    FDatabase:=TABSDatabase.Create(nil);
+    FDatabase.DatabaseName:='OLDBcon';
+    FDatabase.DatabaseFileName:=OLDBFilename;
+    FDatabase.Open;
+    FQuery:=TABSQuery.Create(FDatabase);
+    FQuery.DatabaseName:='OLDBcon';
+    FQuery.SQL.Text:='SELECT [name],[value] FROM globals ORDER BY [name] ASC';
+    FQuery.Open;
+    FQuery.First;
+    repeat
+      if FQuery.FieldByName('name').AsString='dbversion' then begin
+        if FQuery.FieldByName('value').AsString<>DBversion then begin
+          ShowMessage('Database-file '+#13+#10+
+                      '"'+OLDBFilename+'"'+#13+#10+
+                      'has wrong version. (Required: '+DBversion+'; found: '+
+                        FQuery.FieldByName('value').AsString+')');
+          FQuery.Close;
+          Result:=False;
+          Exit;
+        end;
+      end;
+      if FQuery.FieldByName('name').AsString='lvl' then begin
+        FLevelInfo.LevelNumber:=StrToInt(FQuery.FieldByName('value').AsString);
+      end;
+      if FQuery.FieldByName('name').AsString='ident' then begin
+        temps:=FQuery.FieldByName('value').AsString;
+        for i:=0 to High(FLevelInfo.Ident) do begin
+          j:=i*2+1;
+          case temps[j] of
+            '0'..'9': FLevelInfo.Ident[i]:=Ord(temps[j])-48;
+            'A'..'F': FLevelInfo.Ident[i]:=Ord(temps[j])-55;
+          end;
+          FLevelInfo.Ident[i]:=FLevelInfo.Ident[i]*16;
+          case temps[j+1] of
+            '0'..'9': FLevelInfo.Ident[i]:=FLevelInfo.Ident[i]+Ord(temps[j+1])-48;
+            'A'..'F': FLevelInfo.Ident[i]:=FLevelInfo.Ident[i]+Ord(temps[j+1])-55;
+          end;
+        end;
+      end;
+      if FQuery.FieldByName('name').AsString='ident' then begin
+        temps:=FQuery.FieldByName('value').AsString;
+        Fos_mac:=temps='MAC';
+      end;
+      FQuery.Next;
+    until FQuery.EoF;
+    FQuery.Close;
+
+    Result:=True;
+    FBackend:=ODB_ADB;
+  end;
+
+procedure TOniDataADB.Close;
+  begin
+    FDatabase.Close;
+    FDatabase.Free;
+    Self.Free;
+  end;
+
+
+
+function TOniDataADB.GetFileInfo(fileid:LongWord):TFileInfo;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      FQuery.SQL.Text:='SELECT * FROM datfiles WHERE id='+IntToStr(fileid)+' ORDER BY id ASC;';
+      FQuery.Open;
+      if FQuery.RecordCount=1 then begin
+        FQuery.First;
+        Result.ID:=FQuery.FieldByName('id').AsInteger;
+        Result.Name:=FQuery.FieldByName('name').AsString;
+        Result.Extension:=FQuery.FieldByName('extension').AsString;
+        Result.FileName:=FormatNumber(Result.ID,5,'0')+'-'+Result.Name+'.'+Result.Extension;
+        Result.Size:=FQuery.FieldByName('size').AsInteger;
+        Result.FileType:=HexToLong(FQuery.FieldByName('contenttype').AsString);
+        Result.DatAddr:=0;
+        Result.opened:=False;
+      end;
+      FQuery.Close;
+    end else begin
+      Result.ID:=-1;
+    end;
+  end;
+
+function TOniDataADB.GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringArray;
+  var
+    i:LongWord;
+    where:String;
+    where_ext:String;
+  begin
+    where:='';
+    if Length(ext)>0 then begin
+      if Length(where)>0 then
+        where:=where+' AND ';
+      if Pos(',',ext)>0 then begin
+        i:=1;
+        where_ext:='';
+        while i<Length(ext) do begin
+          if Length(where_ext)>0 then
+            where_ext:=where_ext+' OR ';
+          where_ext:=where_ext+'(extension="'+MidStr(ext,i,4)+'")';
+          i:=i+5;
+        end;
+        where:=where+'('+where_ext+')';
+      end else begin
+        where:=where+'(extension="'+ext+'")';
+      end;
+    end;
+    if Length(pattern)>0 then begin
+      if Length(where)>0 then
+        where:=where+' AND ';
+      where:=where+'(name LIKE "%'+pattern+'%")';
+    end;
+    if NoEmptyFiles then begin
+      if Length(where)>0 then
+        where:=where+' AND ';
+      where:=where+'(contenttype<>2)';
+    end;
+    if Length(where)>0 then
+      where:=' WHERE '+where;
+    FQuery.SQL.Text:='SELECT id,name,extension FROM datfiles'+where+' ORDER BY id ASC;';
+    FQuery.Open;
+    if FQuery.RecordCount>0 then begin
+      FQuery.First;
+      SetLength(Result,FQuery.RecordCount);
+      i:=0;
+      repeat
+        Result[i]:=FormatNumber(FQuery.FieldByName('id').AsInteger,5,'0')+'-'+FQuery.FieldByName('name').AsString+'.'+FQuery.FieldByName('extension').AsString;
+        Inc(i);
+        FQuery.Next;
+      until FQuery.EOF;
+    end;
+    FQuery.Close;
+  end;
+
+function TOniDataADB.GetFilesCount:LongWord;
+  begin
+    FQuery.SQL.Text:='SELECT Count(*) AS cnumber FROM datfiles;';
+    FQuery.Open;
+    if FQuery.RecordCount>0 then begin
+      FQuery.First;
+      Result:=FQuery.FieldByName('cnumber').AsInteger;
+    end else Result:=0;
+    FQuery.Close;
+  end;
+
+function TOniDataADB.GetExtensionsList:TStringArray;
+  var
+    i:LongWord;
+  begin
+    SetLength(Result,0);
+    FQuery.SQL.Text:='SELECT extension,count(extension) AS x FROM datfiles GROUP BY extension ORDER BY extension ASC;';
+    FQuery.Open;
+    if FQuery.RecordCount>0 then begin
+      SetLength(Result,FQuery.RecordCount);
+      i:=0;
+      repeat
+        Result[i]:=FQuery.FieldByName('extension').AsString+' ('+IntToStr(FQuery.FieldByName('x').AsInteger)+')';
+        Inc(i);
+        FQuery.Next;
+      until FQuery.EOF;
+    end;
+    FQuery.Close;
+  end;
+
+function TOniDataADB.GetExtendedExtensionsList:TExtensionsMap;
+  var
+    i,j:LongWord;
+    temps:String;
+    data:Tdata;
+  begin
+    SetLength(Result,0);
+    FQuery.SQL.Text:='SELECT ext,ident FROM extlist ORDER BY ext ASC;';
+    FQuery.Open;
+    if FQuery.RecordCount>0 then begin
+      SetLength(Result,FQuery.RecordCount);
+      i:=0;
+      repeat
+        temps:=FQuery.FieldByName('ext').AsString;
+        for j:=0 to 3 do Result[i].Extension[j]:=temps[4-j];
+        data:=DecodeHexString(FQuery.FieldByName('ident').AsString);
+        for j:=0 to 7 do Result[i].Ident[j]:=data[j];
+        Inc(i);
+        FQuery.Next;
+      until FQuery.EOF;
+    end;
+    FQuery.Close;
+  end;
+
+function TOniDataADB.GetNamedFilesMap:TNamedFilesMap;
+  var
+    i:LongWord;
+    temp:Integer;
+    temps:String;
+    temparray:Array of Record
+        id:Integer;
+        fullname:String[50];
+      end;
+  begin
+    SetLength(temparray,0);
+    FQuery.SQL.Text:='SELECT id,(extension+name) AS xname FROM datfiles WHERE Length(name)>0 ORDER BY extension,name ASC;';
+    FQuery.Open;
+    if FQuery.RecordCount>0 then begin
+      repeat
+        temp:=FQuery.FieldByName('id').AsInteger;
+        temps:=FQuery.FieldByName('xname').AsString;
+
+        SetLength(temparray,Length(temparray)+1);
+        if Length(temparray)>1 then begin
+          for i:=High(temparray)-1 downto 0 do begin
+            if StringSmaller(temps,temparray[i].fullname) then begin
+              temparray[i+1]:=temparray[i];
+              if i=0 then begin
+                temparray[i].id:=temp;
+                temparray[i].fullname:=temps;
+              end;
+            end else begin
+              temparray[i+1].id:=temp;
+              temparray[i+1].fullname:=temps;
+              Break;
+            end;
+          end;
+        end else begin
+          temparray[0].id:=temp;
+          temparray[0].fullname:=temps;
+        end;
+        FQuery.Next;
+      until FQuery.Eof;
+    end;
+    FQuery.Close;
+    SetLength(Result,Length(temparray));
+    for i:=0 to High(temparray) do begin
+      Result[i].FileNumber:=temparray[i].id;
+      Result[i].blubb:=0;
+    end;
+  end;
+
+
+
+function TOniDataADB.LoadDatFile(fileid:LongWord):Tdata;
+  var
+    mem:TStream;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      FQuery.SQL.Text:='SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';';
+      FQuery.Open;
+      if FQuery.RecordCount>0 then begin
+        mem:=FQuery.CreateBlobStream(FQuery.FieldByName('data'),bmRead);
+        SetLength(Result,mem.Size);
+        mem.Seek(0,soFromBeginning);
+        mem.Read(Result[0],mem.Size);
+        mem.Free;
+      end;
+      FQuery.Close;
+    end;
+  end;
+
+procedure TOniDataADB.UpdateDatFile(fileid:LongWord; data:Tdata);
+  var
+    MimeCoder: TStringFormat_MIME64;
+    mem:TMemoryStream;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      mimecoder:=TStringFormat_MIME64.Create;
+      mem:=TMemoryStream.Create;
+      mem.Write(data[0],Length(data));
+      mem.Seek(0,soFromBeginning);
+      FQuery.SQL.Text:='UPDATE datfiles SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE id='+IntToStr(fileid)+';';
+      FQuery.ExecSQL;
+      mem.Free;
+      mimecoder.Free;
+    end;
+  end;
+
+procedure TOniDataADB.LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer);
+  var
+    mem:TStream;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      FQuery.SQL.Text:='SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';';
+      FQuery.Open;
+      IF FQuery.RecordCount>0 THEN BEGIN
+        mem:=FQuery.CreateBlobStream(FQuery.FieldByName('data'),bmRead);
+        mem.Seek(offset,soFromBeginning);
+        mem.Read(target^,size);
+        mem.Free;
+      END;
+      FQuery.Close;
+    END;
+  END;
+
+procedure TOniDataADB.UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer);
+  var
+    MimeCoder: TStringFormat_MIME64;
+    mem:TMemoryStream;
+    data:Tdata;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      data:=Self.LoadDatFile(fileid);
+      mimecoder:=TStringFormat_MIME64.Create;
+      mem:=TMemoryStream.Create;
+      mem.Write(data[0],Length(data));
+      mem.Seek(offset,soFromBeginning);
+      mem.Write(target^,size);
+      mem.Seek(0,soFromBeginning);
+      FQuery.SQL.Text:='UPDATE datfiles SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE id='+IntToStr(fileid)+';';
+      FQuery.ExecSQL;
+      mem.Free;
+      mimecoder.Free;
+    end;
+  end;
+
+
+
+function TOniDataADB.GetRawList(fileid:LongWord):TRawList;
+  var
+    i:LongWord;
+  begin
+    SetLength(Result,0);
+    FQuery.SQL.Text:='SELECT [src_link_offset],[size],[sep] FROM rawmap WHERE [src_id]='+IntToStr(fileid)+' ORDER BY src_link_offset ASC;';
+    FQuery.Open;
+    if FQuery.RecordCount>0 then begin
+      FQuery.First;
+      SetLength(Result,FQuery.RecordCount);
+      i:=0;
+      repeat
+        Result[i].src_id:=fileid;
+        Result[i].src_offset:=FQuery.FieldByName('src_link_offset').AsInteger;
+        Result[i].raw_addr:=0;
+        Result[i].raw_size:=FQuery.FieldByName('size').AsInteger;
+        Result[i].loc_sep:=FQuery.FieldByName('sep').AsBoolean;
+        Inc(i);
+        FQuery.Next;
+      until FQuery.EOF;
+    end;
+    FQuery.Close;
+  end;
+
+procedure TOniDataADB.LoadRawFile(fileid,dat_offset:LongWord; target:Pointer);
+  var
+    mem:TStream;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      FQuery.SQL.Text:='SELECT data FROM rawmap WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(dat_offset)+');';
+      FQuery.Open;
+      if FQuery.RecordCount>0 then begin
+        mem:=FQuery.CreateBlobStream(FQuery.FieldByName('data'),bmRead);
+        mem.Seek(0,soFromBeginning);
+        mem.Read(target^,mem.size);
+        mem.Free;
+      end;
+      FQuery.Close;
+    end;
+  end;
+
+procedure TOniDataADB.UpdateRawFile(fileid,dat_offset:LongWord; size:LongWord; target:Pointer);
+  var
+    MimeCoder: TStringFormat_MIME64;
+    mem:TMemoryStream;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      mimecoder:=TStringFormat_MIME64.Create;
+      mem:=TMemoryStream.Create;
+      mem.Write(target^,size);
+      mem.Seek(0,soFromBeginning);
+      FQuery.SQL.Text:='UPDATE rawmap SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(dat_offset)+');';
+      FQuery.ExecSQL;
+      mem.Free;
+      mimecoder.Free;
+    end;
+  end;
+
+procedure TOniDataADB.LoadRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
+  var
+    data:Tdata;
+    mem:TMemoryStream;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      SetLength(data, Self.GetRawInfo(fileid,dat_offset).raw_size);
+      Self.LoadRawFile(fileid,dat_offset,@data[0]);
+      mem:=TMemoryStream.Create;
+      mem.Write(data[offset],size);
+      mem.Read(target^,size);
+      mem.Free;
+    end;
+  end;
+
+procedure TOniDataADB.UpdateRawFilePart(fileid,dat_offset:LongWord; offset,size:LongWord; target:Pointer);
+  var
+    MimeCoder: TStringFormat_MIME64;
+    mem:TMemoryStream;
+    data:Tdata;
+  begin
+    if fileid<Self.GetFilesCount then begin
+      SetLength(data, Self.GetRawInfo(fileid,offset).raw_size);
+      Self.LoadRawFile(fileid,offset,@data[0]);
+      mimecoder:=TStringFormat_MIME64.Create;
+      mem:=TMemoryStream.Create;
+      mem.Write(data[0],Length(data));
+      mem.Seek(offset,soFromBeginning);
+      mem.Write(target^,size);
+      mem.Seek(0,soFromBeginning);
+      FQuery.SQL.Text:='UPDATE rawmap SET data=MimeToBin("'+MimeCoder.StrTo(mem.Memory, mem.Size)+'") WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(dat_offset)+');';
+      FQuery.ExecSQL;
+      mem.Free;
+      mimecoder.Free;
+    end;
+  end;
+
+
+
+
+
+
+
+
+
+
+
+function CreateDataConnection(filename:String; backend:Integer):Boolean;
+  var
+    answer:Boolean;
+  begin
+    if Assigned(OniDataConnection) then begin
+      OniDataConnection.Close;
+      OniDataConnection.Free;
+      OniDataConnection:=Nil;
+    end;
+    case backend of
+      ODB_Dat: OniDataConnection:=TOniDataDat.Create(filename, answer);
+      ODB_ADB: OniDataConnection:=TOniDataADB.Create(filename, answer);
+    else
+      ShowMessage('Unknown Backend');
+      Result:=False;
+      Exit;
+    end;
+
+    if answer then begin
+//      ShowMessage('file loaded');
+//      ShowMessage('Files: '+IntToStr(OniDataConnection.GetFilesCount));
+      Result:=True;
+    end else begin
+      ShowMessage('File not loaded');
+      OniDataConnection.Close;
+      OniDataConnection.Free;
+      Result:=False;
+    end;
+  end;
+
+procedure CloseDataConnection;
+  begin
+    if Assigned(OniDataConnection) then begin
+      OniDataConnection.Close;
+      OniDataConnection:=Nil;
+    end;
+  end;
+
+end.
Index: /oup/current/Unit1_main.dfm
===================================================================
--- /oup/current/Unit1_main.dfm	(revision 10)
+++ /oup/current/Unit1_main.dfm	(revision 10)
@@ -0,0 +1,450 @@
+object Form1: TForm1
+  Left = 0
+  Top = 0
+  HorzScrollBar.Visible = False
+  VertScrollBar.Visible = False
+  Caption = 'Form1'
+  ClientHeight = 571
+  ClientWidth = 577
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIForm
+  OldCreateOrder = False
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCreate = FormCreate
+  OnResize = FormResize
+  PixelsPerInch = 96
+  TextHeight = 13
+  object statbar: TStatusBar
+    Left = 0
+    Top = 554
+    Width = 577
+    Height = 17
+    BiDiMode = bdLeftToRight
+    Panels = <
+      item
+        Text = 'Nothing loaded'
+        Width = 500
+      end
+      item
+        Text = 'Files: -'
+        Width = 90
+      end
+      item
+        Text = 'Extensions: -'
+        Width = 100
+      end>
+    ParentBiDiMode = False
+    ExplicitTop = 535
+  end
+  object DockTop: TTBDock
+    Left = 0
+    Top = 0
+    Width = 577
+    Height = 75
+    object MainMenu: TTBToolbar
+      Left = 0
+      Top = 0
+      Caption = 'MainMenu'
+      CloseButton = False
+      FullSize = True
+      Images = MenuImages
+      MenuBar = True
+      ProcessShortCuts = True
+      ShrinkMode = tbsmWrap
+      TabOrder = 0
+      object menu_main: TTBSubmenuItem
+        Caption = '&Main'
+        object menu_loaddat: TTBItem
+          Caption = '&Select .dat-file ...'
+          ImageIndex = 1
+          ShortCut = 16463
+          OnClick = menu_loaddatClick
+        end
+        object menu_lvldb: TTBItem
+          Caption = 'Open OUP-Level-&DB ...'
+          ImageIndex = 1
+          ShortCut = 16452
+          OnClick = menu_lvldbClick
+        end
+        object menu_CloseFileDB: TTBItem
+          Caption = '&Close file/DB'
+          ImageIndex = 0
+          OnClick = menu_CloseFileDBClick
+        end
+        object menu_sep1: TTBSeparatorItem
+        end
+        object menu_settings: TTBItem
+          Caption = 'Se&ttings...'
+          OnClick = menu_settingsClick
+        end
+        object menu_sep4: TTBSeparatorItem
+        end
+        object menu_exit: TTBItem
+          Caption = '&Exit'
+          OnClick = menu_exitClick
+        end
+      end
+      object menu_convert: TTBSubmenuItem
+        Caption = '&Convert'
+        object menu_createdb: TTBItem
+          Caption = 'Create level-database ...'
+          OnClick = menu_createdbClick
+        end
+        object menu_createlvl: TTBItem
+          Caption = 'Create level-files ...'
+          OnClick = menu_createlvlClick
+        end
+      end
+      object menu_tools: TTBSubmenuItem
+        Caption = '&Tools'
+        Enabled = False
+        object menu_preview: TTBItem
+          Caption = '&Preview Window ...'
+          ShortCut = 16464
+          OnClick = menu_previewClick
+        end
+        object menu_binedit: TTBItem
+          Caption = '&Binary .dat editor ...'
+          ShortCut = 16450
+          OnClick = menu_bineditClick
+        end
+        object menu_rawedit: TTBItem
+          Caption = 'Binary .&raw editor ...'
+          ShortCut = 16466
+          OnClick = menu_raweditClick
+        end
+        object menu_txmpreplace: TTBItem
+          Caption = '&TXMP replacer ...'
+          ShortCut = 16468
+          OnClick = menu_txmpreplaceClick
+        end
+        object menu_extractor: TTBItem
+          Caption = 'File &extractor ...'
+          ShortCut = 16453
+          OnClick = menu_extractorClick
+        end
+        object menu_filecompare: TTBItem
+          Caption = '&File compare ...'
+          Enabled = False
+          ShortCut = 16454
+          OnClick = menu_filecompareClick
+        end
+        object menu_levelstructedit: TTBItem
+          Caption = 'Levelfile structure editor ...'
+          Enabled = False
+          ShortCut = 16460
+        end
+      end
+      object menu_view: TTBSubmenuItem
+        Caption = '&View'
+        object menu_view_toolbar: TTBItem
+          AutoCheck = True
+          Caption = '&Toolbar'
+          Checked = True
+          OnClick = menu_view_toolbarClick
+        end
+        object menu_view_statusbar: TTBItem
+          Caption = '&Status bar'
+          Checked = True
+          OnClick = menu_view_statusbarClick
+        end
+        object menu_view_mdibar: TTBItem
+          Caption = '&Window list'
+          Checked = True
+          OnClick = menu_view_mdibarClick
+        end
+      end
+      object menu_windows: TTBSubmenuItem
+        Caption = '&Windows'
+        object menu_windows_cascade: TTBItem
+          Caption = 'Cascade'
+          OnClick = menu_windows_cascadeClick
+        end
+        object menu_windows_tile: TTBItem
+          Caption = 'Tile'
+          OnClick = menu_windows_tileClick
+        end
+        object menu_windows_closeall: TTBItem
+          Caption = '&Close all'
+          OnClick = menu_windows_closeallClick
+        end
+        object menu_sep3: TTBSeparatorItem
+        end
+        object menu_windows_next: TTBItem
+          Caption = 'Next window'
+          ShortCut = 16417
+          OnClick = menu_windows_nextClick
+        end
+        object menu_windows_previous: TTBItem
+          Caption = 'Previous window'
+          ShortCut = 16418
+          OnClick = menu_windows_previousClick
+        end
+        object menu_sep2: TTBSeparatorItem
+        end
+      end
+      object menu_About: TTBItem
+        Caption = '&About'
+        OnClick = menu_AboutClick
+      end
+    end
+    object Toolbar: TTBToolbar
+      Left = 0
+      Top = 23
+      Caption = 'Toolbar'
+      Images = MenuImages
+      TabOrder = 1
+      object tbOpen: TTBItem
+        Caption = 'x'
+        ImageIndex = 1
+      end
+    end
+    object MDIToolbar: TTBToolbar
+      Left = 0
+      Top = 49
+      Caption = 'MDIToolbar'
+      DockPos = 0
+      DockRow = 2
+      TabOrder = 2
+      OnResize = MDIToolbarResize
+      object TBControlItem1: TTBControlItem
+        Control = MDITab
+      end
+      object MDITab: TMDITab
+        Left = 0
+        Top = 0
+        Width = 562
+        Height = 22
+        Cursor = crHandPoint
+        About = 'MDI Tab Control 1.4 - Copyright '#169' 1999,2002 MichaL MutL'
+        Align = alTop
+        DragKind = dkDock
+        HotTrack = True
+        Images = MenuImages
+        Style = tsFlatButtons
+        OnGetImageIndex = MDITabGetImageIndex
+        MultiLine = True
+        ParentShowHint = False
+        PopupMenu = MDITabPopUp
+        ShowHint = True
+        ShowOnChange = True
+        TabOrder = 0
+      end
+    end
+    object toolbar_mdi: TTBToolbar
+      Left = 88
+      Top = 23
+      Caption = 'Window list'
+      DockPos = 88
+      Images = MenuImages
+      TabOrder = 3
+      object TBItem2: TTBItem
+        Caption = 'test'
+        DisplayMode = nbdmImageAndText
+      end
+      object TBItem1: TTBItem
+        Caption = 'test2'
+        DisplayMode = nbdmImageAndText
+        ImageIndex = 0
+      end
+    end
+  end
+  object DockLeft: TTBDock
+    Left = 0
+    Top = 75
+    Width = 9
+    Height = 470
+    Position = dpLeft
+    ExplicitHeight = 577
+  end
+  object DockRight: TTBDock
+    Left = 568
+    Top = 75
+    Width = 9
+    Height = 470
+    Position = dpRight
+    ExplicitLeft = 0
+    ExplicitHeight = 577
+  end
+  object DockBottom: TTBDock
+    Left = 0
+    Top = 545
+    Width = 577
+    Height = 9
+    Position = dpBottom
+    ExplicitTop = 75
+  end
+  object opend: TOpenDialog
+    Options = [ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 32
+    Top = 64
+  end
+  object saved: TSaveDialog
+    Options = [ofOverwritePrompt, ofPathMustExist, ofEnableSizing]
+    Left = 32
+    Top = 88
+  end
+  object MenuImages: TImageList
+    Left = 168
+    Top = 112
+    Bitmap = {
+      494C010102000400040010001000FFFFFFFFFF10FFFFFFFFFFFFFFFF424D3600
+      0000000000003600000028000000400000001000000001002000000000000010
+      00000000000000000000000000000000000000000000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB400000000000000000000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB40000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000A4A4A400A4A4A400A4A4
+      A400A4A4A40000000000EEB40000EEB40000EEB40000EEB4000000000000A4A4
+      A400A4A4A400A4A4A400A4A4A400EEB4000000000000A4A4A400A4A4A400A4A4
+      A400A4A4A40000000000EEB40000EEB40000EEB40000EEB4000000000000A4A4
+      A400A4A4A400A4A4A400A4A4A400EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000004A4A4A004A4A4A004A4A
+      4A00A4A4A40014007F00944131009441310094413100EEB400000E0E0E004A4A
+      4A004A4A4A004A4A4A00A4A4A400EEB40000000000004A4A4A004A4A4A004A4A
+      4A00A4A4A40018800000944131009441310094413100EEB400000E0E0E004A4A
+      4A004A4A4A004A4A4A00A4A4A400EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000004A4A4A004A4A4A004A4A
+      4A00A4A4A40018009400944131009441310094413100EEB40000180094004A4A
+      4A004A4A4A004A4A4A00A4A4A400EEB40000000000004A4A4A004A4A4A004A4A
+      4A00A4A4A40018920000944131009441310094413100EEB40000189200004A4A
+      4A004A4A4A004A4A4A00A4A4A400EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000004A4A4A00000000000000
+      0000A4A4A40000000000944131000000000000000000EEB40000020202004A4A
+      4A000000000000000000A4A4A400EEB40000000000004A4A4A00000000000000
+      0000A4A4A40000000000944131000000000000000000EEB40000020202004A4A
+      4A000000000000000000A4A4A400EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000A4A4A4004A4A4A00A4A4
+      A400A4A4A40000000000EEB4000094413100EEB40000EEB4000000000000A4A4
+      A4004A4A4A00A4A4A400A4A4A400EEB4000000000000A4A4A4004A4A4A00A4A4
+      A400A4A4A40000000000EEB4000094413100EEB40000EEB4000000000000A4A4
+      A4004A4A4A00A4A4A400A4A4A400EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000000000014007F000000
+      0000000000000000000000000000180094000000000014007F00000000000000
+      000014007F0014007F0000000000EEB40000000000000000000014007F000000
+      0000000000000000000000000000180094000000000000000000000000000000
+      000014007F001880000000000000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000014007F0014007F000000
+      00000000000000000000180094000000000014007F0014007F00000000000000
+      0000000000001800940000000000EEB400000000000018800000188000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000001892000000000000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000014007F0014007F000000
+      00000000000000000000000000001800940014007F0000000000000000000000
+      0000000000001800940000000000EEB400000000000018800000188000000000
+      0000000000000000000018920000189200000000000000000000000000000000
+      0000000000001892000000000000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000014007F0014007F000000
+      0000000000000000000014007F0014007F001800940000000000000000000000
+      0000000000001800940000000000EEB400000000000018800000188000000000
+      0000000000000000000000000000000000001892000000000000000000000000
+      0000000000001892000000000000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000014007F00180094000000
+      00000000000014007F0014007F00180094000000000018009400000000000000
+      000014007F001800940000000000EEB400000000000018800000189200000000
+      0000000000000000000000000000180094000000000018920000000000000000
+      0000188000001892000000000000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000000000000E0E0E00180094000202
+      0200000000000000000000000000A4A4A4000000000000000000000000000000
+      000014007F0014007F0000000000EEB40000000000000E0E0E00189200000202
+      0200000000000000000000000000A4A4A4000000000000000000000000000000
+      0000188000001880000000000000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000A4A4A400A4A4A400A4A4
+      A400A4A4A400A4A4A400A4A4A40094413100A4A4A400A4A4A400A4A4A400A4A4
+      A400A4A4A400A4A4A400EEB40000EEB4000000000000A4A4A400A4A4A400A4A4
+      A400A4A4A400A4A4A400A4A4A40094413100A4A4A400A4A4A400A4A4A400A4A4
+      A400A4A4A400A4A4A400EEB40000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000000000000000000000000000000000000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB40000EEB4000000000000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB40000EEB4
+      0000EEB40000EEB40000EEB40000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      00000000000014007F001800940018009400180094001800940014007F000000
+      0000000000000000000000000000EEB400000000000000000000000000000000
+      0000000000001880000018920000189200001892000018920000188000000000
+      0000000000000000000000000000EEB400000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000EEB4000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000EEB4000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      000000000000000000000000000000000000424D3E000000000000003E000000
+      2800000040000000100000000100010000000000800000000000000000000000
+      000000000000000000000000FFFFFF0080018001000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000000000000000000000000000000000000000000000000
+      0000000000000000000100010000000000000000000000000000000000000000
+      000000000000}
+  end
+  object MDITabPopUp: TPopupMenu
+    AutoHotkeys = maManual
+    AutoLineReduction = maManual
+    Left = 232
+    Top = 112
+    object mdi_close: TMenuItem
+      Caption = 'Close tab'
+    end
+  end
+  object MDIHandler: TTBMDIHandler
+    Toolbar = MainMenu
+    Left = 200
+    Top = 112
+  end
+end
Index: /oup/current/Unit1_main.pas
===================================================================
--- /oup/current/Unit1_main.pas	(revision 10)
+++ /oup/current/Unit1_main.pas	(revision 10)
@@ -0,0 +1,537 @@
+UNIT Unit1_main;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, StdCtrls, StrUtils, Clipbrd, ExtCtrls, ComCtrls, Menus, Grids,
+  MPHexEditor, ToolWin, ImgList, Tabs,
+  Unit2_functions, Unit3_data, Unit9_data_structures,
+  Unit10_leveldb, Unit4_exporters, Unit14_settings,
+  Unit5_preview, Unit7_txmpreplace, Unit8_binedit, Unit11_extractor, Unit13_rawedit,
+  Unit15_Classes, MDITab, TB2Item, TB2Dock, TB2Toolbar, TB2MDI;
+
+TYPE
+  TForm1 = Class(TForm)
+    saved: TSaveDialog;
+    opend: TOpenDialog;
+    statbar: TStatusBar;
+    MenuImages: TImageList;
+    MDITabPopUp: TPopupMenu;
+    mdi_close: TMenuItem;
+    DockTop: TTBDock;
+    MainMenu: TTBToolbar;
+    menu_main: TTBSubmenuItem;
+    menu_loaddat: TTBItem;
+    menu_lvldb: TTBItem;
+    menu_CloseFileDB: TTBItem;
+    menu_sep1: TTBSeparatorItem;
+    menu_settings: TTBItem;
+    menu_sep4: TTBSeparatorItem;
+    menu_exit: TTBItem;
+    menu_convert: TTBSubmenuItem;
+    menu_createdb: TTBItem;
+    menu_createlvl: TTBItem;
+    menu_tools: TTBSubmenuItem;
+    menu_preview: TTBItem;
+    menu_binedit: TTBItem;
+    menu_rawedit: TTBItem;
+    menu_txmpreplace: TTBItem;
+    menu_extractor: TTBItem;
+    menu_filecompare: TTBItem;
+    menu_levelstructedit: TTBItem;
+    menu_windows: TTBSubmenuItem;
+    menu_windows_cascade: TTBItem;
+    menu_windows_tile: TTBItem;
+    menu_windows_closeall: TTBItem;
+    menu_sep3: TTBSeparatorItem;
+    menu_windows_next: TTBItem;
+    menu_windows_previous: TTBItem;
+    menu_sep2: TTBSeparatorItem;
+    menu_About: TTBItem;
+    Toolbar: TTBToolbar;
+    tbOpen: TTBItem;
+    DockLeft: TTBDock;
+    DockRight: TTBDock;
+    DockBottom: TTBDock;
+    MDIHandler: TTBMDIHandler;
+    MDIToolbar: TTBToolbar;
+    TBControlItem1: TTBControlItem;
+    MDITab: TMDITab;
+    menu_view: TTBSubmenuItem;
+    menu_view_mdibar: TTBItem;
+    menu_view_statusbar: TTBItem;
+    menu_view_toolbar: TTBItem;
+    toolbar_mdi: TTBToolbar;
+    TBItem1: TTBItem;
+    TBItem2: TTBItem;
+    FUNCTION TryCloseAll:Boolean;
+    procedure menu_AboutClick(Sender: TObject);
+    PROCEDURE menu_settingsClick(Sender: TObject);
+    PROCEDURE menu_CloseFileDBClick(Sender: TObject);
+    PROCEDURE menu_filecompareClick(Sender: TObject);
+    PROCEDURE menu_raweditClick(Sender: TObject);
+    PROCEDURE menu_createlvlClick(Sender: TObject);
+    PROCEDURE menu_extractorClick(Sender: TObject);
+    PROCEDURE menu_lvldbClick(Sender: TObject);
+    PROCEDURE menu_createdbClick(Sender: TObject);
+    PROCEDURE close_window(window_name:String);
+    PROCEDURE menu_windows_previousClick(Sender: TObject);
+    PROCEDURE menu_windows_nextClick(Sender: TObject);
+    PROCEDURE menu_windows_tileClick(Sender: TObject);
+    FUNCTION open_child(window_context:String):Boolean;
+    PROCEDURE menu_windows_closeallClick(Sender: TObject);
+    PROCEDURE menu_windows_cascadeClick(Sender: TObject);
+    PROCEDURE menu_window_entryClick(Sender: TObject);
+    PROCEDURE menu_bineditClick(Sender: TObject);
+    PROCEDURE menu_loaddatClick(Sender: TObject);
+    PROCEDURE menu_txmpreplaceClick(Sender: TObject);
+    PROCEDURE menu_exitClick(Sender: TObject);
+    PROCEDURE menu_previewClick(Sender: TObject);
+    PROCEDURE FormClose(Sender: TObject; var Action: TCloseAction);
+    PROCEDURE FormResize(Sender: TObject);
+    PROCEDURE FormCreate(Sender: TObject);
+    PROCEDURE UpdateStatBar;
+    procedure MDITabGetImageIndex(Sender: TObject; TabIndex: Integer;
+      var ImageIndex: Integer);
+    procedure MDIToolbarResize(Sender: TObject);
+    procedure menu_view_mdibarClick(Sender: TObject);
+    procedure menu_view_statusbarClick(Sender: TObject);
+    procedure menu_view_toolbarClick(Sender: TObject);
+  PRIVATE
+  PUBLIC
+  END;
+
+VAR
+  Form1: TForm1;
+
+IMPLEMENTATION
+{$R *.dfm}
+
+PROCEDURE TForm1.FormCreate(Sender: TObject);
+  BEGIN
+    Form1.Caption:='Oni Un/Packer '+version;
+    Form1.FormResize(Form1);
+
+    IF FileExists(ExtractFilepath(Application.EXEname)+'\oniunpacker.ini') THEN BEGIN
+      AssignFile(AppSettingsFile,ExtractFilepath(Application.EXEname)+'\oniunpacker.ini');
+      Reset(AppSettingsFile);
+      Read(AppSettingsFile,AppSettings);
+      CloseFile(AppSettingsFile);
+    END ELSE BEGIN
+      AppSettings.DatPath:='D:\Spiele\Oni\GameDataFolder';
+      AppSettings.ExtractPath:='C:\Dokumente und Einstellungen\Administrator\Desktop';
+      AppSettings.FilenumbersAsHex:=False;
+      AppSettings.CharSet:=DEFAULT_CHARSET;
+      AppSettings.HideUnusedData:=False;
+    END;
+
+    IF MidStr(ParamStr(1),1,3)='opf' THEN BEGIN
+      ShowMessage('Load OPF-File: '+ParamStr(2));
+    END ELSE IF MidStr(ParamStr(1),1,4)='oldb' THEN BEGIN
+      IF NOT CreateDataConnection(ParamStr(2), ODB_ADB) THEN
+        ShowMessage('Error while loading the file:'+CrLf+ParamStr(2)+CrLf+'Perhaps not an OniUnPacker-LevelDatabase-file?');
+    END ELSE IF MidStr(ParamStr(1),1,3)='dat' THEN BEGIN
+      IF NOT CreateDataConnection(ParamStr(2), ODB_Dat) THEN
+        ShowMessage('Error while loading the file:'+CrLf+ParamStr(2)+CrLf+'Perhaps not an Oni-.dat-file?');
+    END;
+    UpdateStatBar;
+  END;
+
+PROCEDURE TForm1.FormResize(Sender: TObject);
+  CONST
+    MinWidth:Integer=750;
+    MinHeight:Integer=500;
+  BEGIN
+    IF Form1.Width<MinWidth THEN Form1.Width:=MinWidth;
+    IF Form1.Height<MinHeight THEN Form1.Height:=MinHeight;
+    Form1.statbar.Panels.Items[0].Width:=Form1.Width-200;
+  END;
+
+procedure TForm1.MDITabGetImageIndex(Sender: TObject; TabIndex: Integer; var ImageIndex: Integer);
+  begin
+//    if Pos('binedit',MDITab.MDIChildren[TabIndex].Name)>0 then
+//      ImageIndex:=0
+//    else
+      ImageIndex:=-1;
+  end;
+
+procedure TForm1.MDIToolbarResize(Sender: TObject);
+  begin
+{    if MDIToolbar.Width>100 then
+      MDITab.Width:=MDIToolbar.Width-10
+    else
+      MDIToolbar.Width:=100;
+}  end;
+
+PROCEDURE TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
+  BEGIN
+    AssignFile(AppSettingsFile,ExtractFilepath(Application.EXEname)+'\oniunpacker.ini');
+    IF FileExists(ExtractFilepath(Application.EXEname)+'\oniunpacker.ini') THEN
+      Reset(AppSettingsFile)
+    ELSE
+      Rewrite(AppSettingsFile);
+    Write(AppSettingsFile,AppSettings);
+    CloseFile(AppSettingsFile);
+    Action:=caFree;
+  END;
+
+
+PROCEDURE TForm1.UpdateStatBar;
+  BEGIN
+    IF Assigned(OniDataConnection) THEN BEGIN
+      Form1.Caption:='Oni Un/Packer '+version+' ('+ExtractFileName(OniDataConnection.FileName)+')';
+      menu_tools.Enabled:=True;
+      menu_convert.Enabled:=False;
+      statbar.Panels.Items[1].Text:='Files: '+IntToStr(OniDataConnection.GetFilesCount);
+      statbar.Panels.Items[2].Text:='Extensions: '+IntToStr(Length(OniDataConnection.GetExtensionsList));
+      CASE OniDataConnection.Backend OF
+        ODB_Dat:
+          BEGIN
+            statbar.Panels.Items[0].Text:='.dat loaded: '+OniDataConnection.FileName;
+          END;
+        ODB_ADB:
+          BEGIN
+            statbar.Panels.Items[0].Text:='OLDB loaded: '+OniDataConnection.FileName;
+          END;
+      ELSE
+        Form1.Caption:='Oni Un/Packer '+version;
+        statbar.Panels.Items[0].Text:='Nothing loaded';
+        statbar.Panels.Items[1].Text:='Files: -';
+        statbar.Panels.Items[2].Text:='Extensions: -';
+        menu_tools.Enabled:=False;
+        menu_convert.Enabled:=True;
+      END;
+    END ELSE BEGIN
+      Form1.Caption:='Oni Un/Packer '+version;
+      statbar.Panels.Items[0].Text:='Nothing loaded';
+      statbar.Panels.Items[1].Text:='Files: -';
+      statbar.Panels.Items[2].Text:='Extensions: -';
+      menu_tools.Enabled:=False;
+      menu_convert.Enabled:=True;
+    END;
+  END;
+
+
+FUNCTION TForm1.TryCloseAll:Boolean;
+  BEGIN
+    menu_windows_closeallClick(Self);
+    IF MDITab.MDIChildCount=0 THEN
+      Result:=True
+    ELSE
+      Result:=False;
+  END;
+
+
+{#################################}
+{##### Main-Menu-Handlers    #####}
+{#################################}
+PROCEDURE TForm1.menu_loaddatClick(Sender: TObject);
+  VAR i:LongWord;
+    answer:Boolean;
+  BEGIN
+    IF TryCloseAll THEN BEGIN
+      CloseDataConnection;
+      opend.InitialDir:=AppSettings.DatPath;
+      opend.Filter:='Oni-Dat-Files|*.dat';
+      IF opend.Execute THEN BEGIN
+        IF NOT CreateDataConnection(opend.FileName, ODB_Dat) THEN
+          ShowMessage('Error while loading the file:'+CrLf+opend.FileName+CrLf+'Perhaps not an Oni-.dat-file?');
+        AppSettings.DatPath:=ExtractFilepath(opend.FileName);
+      END;
+    END;
+    UpdateStatBar;
+  END;
+PROCEDURE TForm1.menu_lvldbClick(Sender: TObject);
+  VAR answer:Boolean;
+  BEGIN
+    IF TryCloseAll THEN BEGIN
+      CloseDataConnection;
+      opend.InitialDir:=AppSettings.DatPath;
+      opend.Filter:='OUP-Level-DB (*.oldb)|*.oldb';
+      IF opend.Execute THEN BEGIN
+        IF NOT CreateDataConnection(opend.FileName, ODB_ADB) THEN
+          ShowMessage('Error while loading the file:'+CrLf+opend.FileName+CrLf+'Perhaps not an OniUnPacker-LevelDatabase-file?');
+        AppSettings.DatPath:=ExtractFilepath(opend.FileName);
+      END;
+    END;
+    UpdateStatBar;
+  END;
+PROCEDURE TForm1.menu_CloseFileDBClick(Sender: TObject);
+  BEGIN
+    IF TryCloseAll THEN BEGIN
+      CloseDataConnection;
+      UpdateStatBar;
+    END;
+  END;
+PROCEDURE TForm1.menu_settingsClick(Sender: TObject);
+  BEGIN
+    Form14.Visible:=True;
+    Self.Enabled:=False;
+  END;
+PROCEDURE TForm1.menu_exitClick(Sender: TObject);
+  BEGIN
+    Form1.Close;
+  END;
+
+{####################################}
+{##### Converters-Menu-Handlers #####}
+{####################################}
+PROCEDURE TForm1.menu_createdbClick(Sender: TObject);
+  BEGIN
+    opend.Filter:='Oni-Dat-Files|*.dat';
+    saved.Filter:='OUP-Level-DB (*.oldb)|*.oldb';
+    saved.DefaultExt:='oldb';
+    IF opend.Execute THEN BEGIN
+      IF saved.Execute THEN BEGIN
+        Form10.CreateDatabase(opend.FileName,saved.FileName);
+      END;
+    END;
+  END;
+PROCEDURE TForm1.menu_createlvlClick(Sender: TObject);
+  BEGIN
+    opend.Filter:='OUP-Level-DB (*.oldb)|*.oldb';
+    saved.Filter:='Oni-Dat-Files|*.dat';
+    saved.DefaultExt:='dat';
+    IF opend.Execute THEN BEGIN
+      IF saved.Execute THEN BEGIN
+        Form10.CreateLevel(opend.FileName,saved.FileName);
+      END;
+    END;
+  END;
+
+{#################################}
+{##### Tools-Menu-Handlers   #####}
+{#################################}
+PROCEDURE TForm1.menu_previewClick(Sender: TObject);
+  BEGIN
+    open_child('preview');
+  END;
+PROCEDURE TForm1.menu_txmpreplaceClick(Sender: TObject);
+  BEGIN
+    open_child('txmpreplace');
+  END;
+PROCEDURE TForm1.menu_bineditClick(Sender: TObject);
+  BEGIN
+    open_child('binedit');
+  END;
+PROCEDURE TForm1.menu_raweditClick(Sender: TObject);
+  BEGIN
+    open_child('rawedit');
+  END;
+
+PROCEDURE TForm1.menu_extractorClick(Sender: TObject);
+  BEGIN
+    open_child('extractor');
+  END;
+PROCEDURE TForm1.menu_filecompareClick(Sender: TObject);
+  BEGIN
+    open_child('compare');
+  END;
+
+
+{#################################}
+{#####   View-Menu-Handlers  #####}
+{#################################}
+procedure TForm1.menu_view_mdibarClick(Sender: TObject);
+  begin
+    menu_view_mdibar.Checked := not menu_view_mdibar.Checked;
+    mditoolbar.Visible := menu_view_mdibar.Checked;
+  end;
+procedure TForm1.menu_view_statusbarClick(Sender: TObject);
+  begin
+    menu_view_statusbar.Checked := not menu_view_statusbar.Checked;
+    statbar.Visible := menu_view_statusbar.Checked;
+  end;
+procedure TForm1.menu_view_toolbarClick(Sender: TObject);
+  begin
+    menu_view_toolbar.Checked := not menu_view_toolbar.Checked;
+    toolbar.Visible := menu_view_toolbar.Checked;
+  end;
+
+
+  
+{#################################}
+{#####  Window-Menu-Handlers #####}
+{#################################}
+PROCEDURE TForm1.menu_windows_cascadeClick(Sender: TObject);
+  BEGIN
+    Form1.Cascade;
+  END;
+PROCEDURE TForm1.menu_windows_tileClick(Sender: TObject);
+  BEGIN
+    Form1.TileMode:=tbHorizontal;
+    Form1.Tile;
+  END;
+PROCEDURE TForm1.menu_windows_closeallClick(Sender: TObject);
+  VAR
+    i:Byte;
+  BEGIN
+    MDITab.CloseAll;
+  END;
+PROCEDURE TForm1.menu_windows_nextClick(Sender: TObject);
+  VAR i:Byte;
+    first_window:Byte;
+    current_focus:String;
+  BEGIN
+    IF MDIChildCount>1 THEN BEGIN
+      FOR i:=0 TO menu_windows.Count-1 DO BEGIN
+        IF Pos('menu_window_',menu_windows.Items[i].Name)=1 THEN BEGIN
+          first_window:=i;
+          Break;
+        END;
+      END;
+      current_focus:=ActiveMDIChild.Name;
+      FOR i:=first_window TO menu_windows.Count-1 DO
+        IF Pos(current_focus,menu_windows.Items[i].Name)>0 THEN
+          Break;
+      IF i=menu_windows.Count-1 THEN
+        menu_windows.Items[first_window].Click
+      ELSE
+        menu_windows.Items[i+1].Click;
+    END;
+  END;
+PROCEDURE TForm1.menu_windows_previousClick(Sender: TObject);
+  VAR i:Byte;
+    first_window:Byte;
+    current_focus:String;
+  BEGIN
+    IF MDIChildCount>1 THEN BEGIN
+      FOR i:=0 TO menu_windows.Count-1 DO BEGIN
+        IF Pos('menu_window_',menu_windows.Items[i].Name)=1 THEN BEGIN
+          first_window:=i;
+          Break;
+        END;
+      END;
+      current_focus:=ActiveMDIChild.Name;
+      FOR i:=first_window TO menu_windows.Count-1 DO
+        IF Pos(current_focus,menu_windows.Items[i].Name)>0 THEN
+          Break;
+      IF i=first_window THEN
+        menu_windows.Items[menu_windows.Count-1].Click
+      ELSE
+        menu_windows.Items[i-1].Click;
+    END;
+  END;
+
+PROCEDURE TForm1.menu_window_entryClick(Sender: TObject);
+  VAR
+    i:Byte;
+    window_name:String;
+  BEGIN
+    window_name:=MidStr(TComponent(Sender).Name,Pos('window_',TComponent(Sender).Name)+7,Length(TComponent(Sender).Name)-Pos('window_',TComponent(Sender).Name)+7+1);
+    FOR i:=0 TO MDIChildCount-1 DO BEGIN
+      IF MDIChildren[i].Name=window_name THEN BEGIN
+        MDIChildren[i].BringToFront;
+      END;
+    END;
+  END;
+
+procedure TForm1.menu_AboutClick(Sender: TObject);
+  begin
+    ShowMessage('Will be implemented later ;)');
+  end;
+
+
+
+
+FUNCTION TForm1.open_child(window_context:String):Boolean;
+  VAR
+    rawEdit:TForm13;
+    binEdit:TForm8;
+    preview:TForm5;
+    txmpreplacer:TForm7;
+    extractor:TForm11;
+    menu_button:TTBItem;
+    used:Array[1..9] OF Boolean;
+    i:Byte;
+    caption:String;
+    name:String;
+  BEGIN
+    Result:=True;
+    FOR i:=1 TO 9 DO used[i]:=False;
+    IF MDIChildCount>0 THEN
+      FOR i:=0 TO MDIChildCount-1 DO
+        IF Pos(window_context,Form1.MDIChildren[i].Name)=1 THEN
+          used[StrToInt(RightStr(Form1.MDIChildren[i].Caption,1))]:=True;
+    FOR i:=1 TO 10 DO
+      IF i=10 THEN
+        Break
+      ELSE
+        IF NOT used[i] THEN Break;
+
+    IF i<10 THEN BEGIN
+      name:=window_context+IntToStr(i);
+      IF window_context='binedit' THEN
+        caption:='Binary .dat-Editor '+IntToStr(i);
+      IF window_context='rawedit' THEN
+        caption:='Binary .raw-Editor '+IntToStr(i);
+      IF window_context='preview' THEN
+        caption:='Preview-Window '+IntToStr(i);
+      IF window_context='txmpreplace' THEN
+        caption:='TXMP Replacer '+IntToStr(i);
+      IF window_context='extractor' THEN
+        caption:='Extractor '+IntToStr(i);
+
+      menu_button:=TTBItem.Create(menu_windows);
+      menu_button.Caption:=caption;
+      menu_button.Name:='menu_window_'+name;
+      menu_button.OnClick:=Form1.menu_window_entryClick;
+      menu_windows.Add(menu_button);
+
+      IF window_context='binedit' THEN BEGIN
+        binEdit:=TForm8.Create(Application);
+        binEdit.Name:=name;
+        binEdit.Caption:=caption;
+        binEdit.Recreatelist;
+        MDITab.AddTab(binEdit,-1); 
+      END;
+      IF window_context='rawedit' THEN BEGIN
+        rawEdit:=TForm13.Create(Application);
+        rawEdit.Name:=name;
+        rawEdit.Caption:=caption;
+        rawEdit.Recreatelist;
+        MDITab.AddTab(rawEdit,-1);
+      END;
+      IF window_context='preview' THEN BEGIN
+        preview:=TForm5.Create(Application);
+        preview.Name:=name;
+        preview.Caption:=caption;
+        preview.Recreatelist;
+        MDITab.AddTab(preview,-1);
+      END;
+      IF window_context='txmpreplace' THEN BEGIN
+        txmpreplacer:=TForm7.Create(Application);
+        txmpreplacer.Name:=name;
+        txmpreplacer.Caption:=caption;
+        txmpreplacer.Recreatelist;
+        MDITab.AddTab(txmpreplacer,-1);
+      END;
+      IF window_context='extractor' THEN BEGIN
+        extractor:=TForm11.Create(Application);
+        extractor.Name:=name;
+        extractor.Caption:=caption;
+        extractor.Recreatelist;
+        MDITab.AddTab(extractor,-1); 
+      END;
+
+      IF MDIChildCount=9 THEN menu_tools.Enabled:=False;
+    END ELSE BEGIN
+      Result:=False;
+    END;
+  END;
+
+
+PROCEDURE TForm1.close_window(window_name:String);
+  VAR
+    i,j:Byte;
+  BEGIN
+    FOR i:=0 TO menu_windows.Count-1 DO BEGIN
+      IF menu_windows.Items[i].Name='menu_window_'+window_name THEN BEGIN
+        menu_windows.Items[i].Free;
+        Break;
+      END;
+    END;
+    menu_tools.Enabled:=True;
+  END;
+
+
+END.
Index: /oup/current/Unit2_functions.pas
===================================================================
--- /oup/current/Unit2_functions.pas	(revision 10)
+++ /oup/current/Unit2_functions.pas	(revision 10)
@@ -0,0 +1,294 @@
+UNIT Unit2_functions;
+INTERFACE
+USES Classes, Dialogs, SysUtils, StrUtils, Math,
+      Unit3_data;
+
+TYPE
+  TExportSet=SET OF (DO_dat,DO_raw,DO_convert,DO_toone);
+
+FUNCTION BoolToStr(bool:Boolean):String;
+FUNCTION HexToLong(hex:String):LongWord;
+FUNCTION Decode_Int(buffer:Tdata):LongWord;
+FUNCTION Encode_Int(input:LongWord):Tdata;
+FUNCTION Decode_Float(buffer:Tdata):Single;
+FUNCTION Encode_Float(input:Single):Tdata;
+FUNCTION DataToBin(data:Tdata):String;
+FUNCTION BinToInt(bin:String):Byte;
+
+FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;
+
+FUNCTION StringSmaller(string1,string2:String):Boolean;
+
+FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
+FUNCTION FormatFileSize(size:LongWord):String;
+FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
+FUNCTION DecodeHexString(hex:String):Tdata;
+FUNCTION GetWinFileName(name:String):String;
+FUNCTION GetExtractPath:String;
+
+FUNCTION Explode(_string:String; delimiter:Char):TStringArray;
+
+
+IMPLEMENTATION
+USES Unit4_Exporters, Unit15_Classes;
+
+TYPE
+  TValueSwitcher=Record
+    CASE IsFloat: Boolean OF
+      True: (ValueFloat:Single);
+      False: (ValueInt:LongWord);
+  END;
+
+FUNCTION BoolToStr(bool:Boolean):String;
+  BEGIN
+    IF bool THEN
+      Result:='true'
+    ELSE
+      Result:='false';
+  END;
+
+FUNCTION HexToLong(hex:String):LongWord;
+  FUNCTION NormalizeHexString(VAR hex:String):Boolean;
+    VAR
+      i:Byte;
+    BEGIN
+      IF hex[1]='$' THEN BEGIN
+        FOR i:=1 TO Length(hex)-1 DO BEGIN
+          hex[i]:=hex[i+1];
+        END;
+        SetLength(hex, Length(hex)-1);
+      END;
+      IF (hex[1]='0') AND (UpCase(hex[2])='X') THEN BEGIN
+        FOR i:=1 TO Length(hex)-2 DO BEGIN
+          hex[i]:=hex[i+2];
+        END;
+        SetLength(hex, Length(hex)-2);
+      END;
+      IF Length(hex)=0 THEN
+        Result:=False
+      ELSE
+        Result:=True;
+    END;
+  VAR
+    i:Byte;
+  BEGIN
+    IF NormalizeHexString(hex) THEN BEGIN
+      hex:=UpperCase(hex);
+      Result:=0;
+      FOR i:=1 TO Length(hex) DO BEGIN
+        Result:=Result SHL 4;
+        CASE hex[i] OF
+          '0'..'9': Result:=Result+Ord(hex[i])-48;
+          'A'..'F': Result:=Result+Ord(hex[i])-55;
+        ELSE
+          Result:=0;
+          Exit;
+        END;
+      END;
+    END ELSE BEGIN
+      Result:=0;
+    END;
+  END;
+
+FUNCTION Decode_Int(buffer:Tdata):LongWord;
+  BEGIN
+    Result:=buffer[0]+buffer[1]*256+buffer[2]*256*256+buffer[3]*256*256*256;
+  END;
+FUNCTION Encode_Int(input:LongWord):Tdata;
+  BEGIN
+    SetLength(Result,4);
+    Result[0]:=input MOD 256;
+    input:=input DIV 256;
+    Result[1]:=input MOD 256;
+    input:=input DIV 256;
+    Result[2]:=input MOD 256;
+    input:=input DIV 256;
+    Result[3]:=input MOD 256;
+  END;
+FUNCTION Decode_Float(buffer:Tdata):Single;
+  VAR _valueswitcher:TValueSwitcher;
+  BEGIN
+    _valueswitcher.ValueInt:=Decode_Int(buffer);
+    Result:=_valueswitcher.ValueFloat;
+    IF IsNAN(Result) THEN Result:=0.0;
+  END;
+FUNCTION Encode_Float(input:Single):Tdata;
+  VAR _valueswitcher:TValueSwitcher;
+  BEGIN
+    _valueswitcher.ValueFloat:=input;
+    Result:=Encode_Int(_valueswitcher.ValueInt);
+  END;
+
+FUNCTION DataToBin(data:Tdata):String;
+  VAR
+    i,j:Byte;
+    singlebyte:Byte;
+    bytepart:String;
+  BEGIN
+    SetLength(bytepart,8);
+    Result:='';
+    FOR i:=0 TO High(data) DO BEGIN
+      singlebyte:=data[i];
+      FOR j:=7 DOWNTO 0 DO BEGIN
+        bytepart[j+1]:=Char((singlebyte AND $01)+48);
+        singlebyte:=singlebyte SHR 1;
+      END;
+      Result:=Result+bytepart+' ';
+    END;
+  END;
+FUNCTION BinToInt(bin:String):Byte;
+  VAR
+    Add: Integer;
+    i: Byte;
+  BEGIN
+    Result:=0;
+    IF Length(bin)<>8 THEN Exit;
+    Add:=1;
+    FOR i:=8 DOWNTO 1 DO BEGIN
+      IF NOT (bin[i] IN ['0','1']) THEN Exit;
+      IF bin[i] = '1' THEN Inc(Result,Add);
+      Add:=Add SHL 1;
+    END;
+  END;
+
+
+
+FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
+  BEGIN
+    Result:=AnsiReplaceStr(Format('%'+IntToStr(width)+'u',[value]),' ',leadingzeros);
+  END;
+
+FUNCTION FormatFileSize(size:LongWord):String;
+  BEGIN
+    IF size>=1000*1024*1024 THEN BEGIN
+      Result:=FloatToStrF(size/1024/1024/1024,ffFixed,5,1)+' GB';
+    END ELSE BEGIN
+      IF size>=1000*1024 THEN BEGIN
+        Result:=FloatToStrF(size/1024/1024,ffFixed,5,1)+' MB';
+      END ELSE BEGIN
+        IF size>=1000 THEN BEGIN
+          Result:=FloatToStrF(size/1024,ffFixed,5,1)+' KB';
+        END ELSE BEGIN
+          Result:=IntToStr(size)+' B';
+        END;
+      END;
+    END;
+  END;
+
+FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
+  VAR
+    string_build,ascii_version:String;
+    i:LongWord;
+  BEGIN
+    string_build:='';
+    ascii_version:='';
+    FOR i:=0 TO High(data) DO BEGIN
+      IF NOT HexOnly THEN
+        IF (i MOD 16)=0 THEN
+          string_build:=string_build+'0x'+IntToHex(i,6)+'  ';
+      string_build:=string_build+IntToHex(data[i],2);
+      IF NOT HexOnly THEN BEGIN
+        IF data[i]>=32 THEN ascii_version:=ascii_version+Chr(data[i])
+        ELSE ascii_version:=ascii_version+'.';
+        IF ((i+1) MOD 2)=0 THEN string_build:=string_build+#32;
+        IF ((i+1) MOD 16)=0 THEN BEGIN
+          string_build:=string_build+#32+ascii_version+CrLf;
+          ascii_version:='';
+        END;
+      END;
+    END;
+    Result:=string_build;
+  END;
+
+FUNCTION DecodeHexString(hex:String):Tdata;
+  VAR
+    i:LongWord;
+  BEGIN
+    SetLength(Result, Length(hex) DIV 2);
+    FOR i:=0 TO Length(Result) DO BEGIN
+      Result[i]:=0;
+      CASE UpCase(hex[1+i*2]) OF
+        '0'..'9': Result[i]:=(Ord(UpCase(hex[1+i*2]))-48)*16;
+        'A'..'F': Result[i]:=(Ord(UpCase(hex[1+i*2]))-55)*16;
+      END;
+      CASE UpCase(hex[1+i*2+1]) OF
+        '0'..'9': Result[i]:=Result[i]+(Ord(UpCase(hex[1+i*2+1]))-48);
+        'A'..'F': Result[i]:=Result[i]+(Ord(UpCase(hex[1+i*2+1]))-55);
+      END;
+    END;
+  END;
+
+
+
+FUNCTION StringSmaller(string1,string2:String):Boolean;
+  VAR
+    i:Integer;
+    len:Integer;
+  BEGIN
+    len:=Min(Length(string1),Length(string2));
+    FOR i:=1 TO len DO
+      IF Ord(string1[i])<>Ord(string2[i]) THEN BEGIN
+        Result:=Ord(string1[i])<Ord(string2[i]);
+        Exit;
+      END;
+    Result:=Length(string1)<Length(string2);
+  END;
+
+
+
+
+FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;
+  VAR
+    i:Byte;
+    extension:String;
+    rawlist:TRawList;
+  BEGIN
+    Result:=export_noerror;
+    extension:=RightStr(filename,4);
+    IF DO_toone IN settings THEN BEGIN
+      ExportDatFile(fileid,path+'\'+GetWinFileName(filename));
+    END ELSE BEGIN
+      IF DO_dat IN settings THEN ExportDatFile(fileid,path+'\'+GetWinFileName(filename));
+      IF DO_raw IN settings THEN BEGIN
+        rawlist:=OniDataConnection.GetRawList(fileid);
+        IF Length(rawlist)>0 THEN BEGIN
+          FOR i:=0 TO High(rawlist) DO BEGIN
+            ExportRawFile(fileid,rawlist[i].src_offset,path+'\'+GetWinFileName(filename));
+          END;
+        END;
+      END;
+    END;
+  END;
+
+FUNCTION Explode(_string:String; delimiter:Char):TStringArray;
+  VAR
+    start,len:Word;
+  BEGIN
+    SetLength(Result, 0);
+    start:=1;
+    WHILE PosEx(delimiter,_string,start)>0 DO BEGIN
+      len:=PosEx(delimiter,_string,start)-start;
+      SetLength(Result, Length(Result)+1);
+      Result[High(Result)]:=MidStr(_string,start,len);
+      start:=start+len+1;
+    END;
+    SetLength(Result, Length(Result)+1);
+    Result[High(Result)]:=MidStr(_string,start,Length(_string)-start+1);
+  END;
+
+FUNCTION GetWinFileName(name:String):String;
+  BEGIN
+    Result:=name;
+    Result:=AnsiReplaceStr(Result,'\','__');
+    Result:=AnsiReplaceStr(Result,'/','__');
+    Result:=AnsiReplaceStr(Result,'>','__');
+    Result:=AnsiReplaceStr(Result,'<','__');
+  END;
+
+FUNCTION GetExtractPath:String;
+  BEGIN
+    Result:=ExtractFilePath(OniDataConnection.FileName)+'\extracted_'+ExtractFileName(OniDataConnection.Filename);
+  END;
+
+
+END.
Index: /oup/current/Unit3_data.pas
===================================================================
--- /oup/current/Unit3_data.pas	(revision 10)
+++ /oup/current/Unit3_data.pas	(revision 10)
@@ -0,0 +1,130 @@
+unit Unit3_data;
+interface
+uses Classes, Graphics;
+
+const
+  Version:String='v0.32a';
+  DBVersion:String='0.3';
+  CrLf:String[2]=#13+#10;
+
+type
+  TData=Array of Byte;
+  THeader=packed Record
+    Ident:Array[0..$13] of Byte;
+    Files:LongWord;
+    NamedFiles:LongWord;
+    Extensions:LongWord;
+    DataAddr:LongWord;
+    DataSize:LongWord;
+    NamesAddr:LongWord;
+    NamesSize:LongWord;
+    Ident2:Array[0..$F] of Byte;
+  end;
+  TFilesMap=Array of packed Record
+    Extension:Array[0..$3] of Char;
+    DataAddr:LongWord;
+    NameAddr:LongWord;
+    FileSize:LongWord;
+    FileType:LongWord;
+  end;
+  TFileInfo=packed Record
+    ID:Integer;
+    FileName:String;
+    FileNameHex:String;
+    Extension:String[4];
+    Name:String;
+    Size:LongWord;
+    FileType:LongWord;
+    DatAddr:LongWord;
+    opened:Boolean;
+  end;
+  TFiles=Array of TFileInfo;
+
+  TNamedFilesMap=Array of packed Record
+  	FileNumber:LongWord;
+	  blubb:LongWord;
+  end;
+  TExtensionsMap=Array of packed Record
+  	Ident:Array[0..$7] of Byte;
+	  Extension:Array[0..$3] of Char;
+  	ExtCount:LongWord;
+  end;
+
+  TLevelInfo=Record
+    Ident:Array[0..$13] of Byte;
+    LevelNumber:Byte;
+  end;
+
+  TAppSettings=Record
+    DatPath:String[250];
+    ExtractPath:String[250];
+    FilenumbersAsHex:Boolean;
+    CharSet:TFontCharSet;
+    HideUnusedData:Boolean;
+  end;
+
+  TExportHandlers=Record
+    Ext:String[4];
+    needed:Boolean;
+    Handler:Function(fileid:LongWord; filename:String; convert:Boolean):Integer;
+  end;
+
+  TStringArray=Array of String;
+  TExtList=Array of Record
+    Ext:String;
+    count:LongWord;
+  end;
+
+  TRawInfo=Record
+    src_id:LongWord;
+    src_offset:LongWord;
+    raw_addr:LongWord;
+    raw_size:LongWord;
+    loc_sep:Boolean;
+  end;
+  TRawList=Array of TRawInfo;
+
+  TDatLinks=Array of Record
+    Src_Offset:LongWord;
+    Target:LongWord;
+  END;
+
+var
+{
+  opened_state:Byte=0;
+  dat_filename:String='';
+  raw_filename:String='';
+  dat_os_mac:Boolean=False;
+  dat_header:Theader;
+  dat_filesmap:Tfilesmap;
+  dat_files:Tfiles;
+  dat_namedfilesmap:Tnamedfilesmap;
+  dat_extensionsmap:Textensionsmap;
+}
+  AppSettings:TAppSettings;
+  AppSettingsFile:File of TAppSettings;
+{
+  database_level:LongWord;
+  database_ident:Array[0..$13] of Byte;
+}
+const
+{  header_ident1_pc:Array[0..$13] of Byte=
+      ($1F,$27,$DC,$33,$DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
+  header_ident1_mac:Array[0..$13] of Byte=
+      ($61,$30,$C1,$23,$DF,$BC,$03,$00,$31,$33,$52,$56,$40,$00,$14,$00,$10,$00,$08,$00);
+  header_ident2:Array[0..$F] of Byte=
+      ($99,$CF,$40,$00,$90,$4F,$63,$00,$F4,$55,$5F,$00,$90,$4F,$63,$00);
+}
+  export_noerror:Integer=0;
+  export_nohandler:Integer=1;
+  export_handlererror:Integer=2;
+  export_error:Integer=3;
+{
+  opened_nothing:Byte=0;
+  opened_dat:Byte=1;
+  opened_db:Byte=2;
+}
+implementation
+
+end.
+
Index: /oup/current/Unit4_Exporters.pas
===================================================================
--- /oup/current/Unit4_Exporters.pas	(revision 10)
+++ /oup/current/Unit4_Exporters.pas	(revision 10)
@@ -0,0 +1,218 @@
+UNIT Unit4_Exporters;
+INTERFACE
+USES Classes, Dialogs, StrUtils, SysUtils, Math, Unit3_data, Unit6_imgfuncs;
+
+PROCEDURE ExportDatFile(fileid:LongWord; filename:String);
+PROCEDURE ExportRawFile(fileid:LongWord; dat_offset:LongWord; filename:String);
+
+FUNCTION ExportSNDD(fileid:LongWord; filename:String; convert:Boolean):Integer;
+FUNCTION ExportTRAC(fileid:LongWord; filename:String; convert:Boolean):Integer;
+FUNCTION ExportTXAN(fileid:LongWord; filename:String; convert:Boolean):Integer;
+FUNCTION ExportTXMB(fileid:LongWord; filename:String; convert:Boolean):Integer;
+FUNCTION ExportTXMP(fileid:LongWord; filename:String; convert:Boolean):Integer;
+VAR
+  ExportHandlers:Array[1..1] OF TExportHandlers=(
+//    (Ext:'ABNA'; needed:False),
+    //(Ext:'AGDB'; needed:False),
+    (Ext:'SNDD'; needed:True; Handler:ExportSNDD)
+{    (Ext:'TRAC'; needed:True; Handler:ExportTRAC),
+    (Ext:'TXAN'; needed:True; Handler:ExportTXAN),
+    (Ext:'TXMB'; needed:True; Handler:ExportTXMB),
+    (Ext:'TXMP'; needed:True; Handler:ExportTXMP)
+}  );
+
+
+
+IMPLEMENTATION
+USES Unit2_functions, Unit9_data_structures, Unit15_Classes;
+
+PROCEDURE ExportDatFile(fileid:LongWord; filename:String);
+  VAR
+    filestream:TFileStream;
+    data:Tdata;
+  BEGIN
+    data:=OniDataConnection.LoadDatFile(fileid);
+    IF FileExists(filename) THEN BEGIN
+      filestream:=TFileStream.Create(filename,fmOpenReadWrite);
+      filestream.Seek(0,soFromEnd);
+    END ELSE BEGIN
+      filestream:=TFileStream.Create(filename,fmCreate);
+    END;
+    filestream.Write(data[0],Length(data));
+    filestream.Free;
+  END;
+
+PROCEDURE ExportRawFile(fileid:LongWord; dat_offset:LongWord; filename:String);
+  VAR
+    filestream:TFileStream;
+    data:Tdata;
+  BEGIN
+    SetLength(data, OniDataConnection.GetRawInfo(fileid, dat_offset).raw_size);
+    OniDataConnection.LoadRawFile(fileid,dat_offset,@data[0]);
+    IF FileExists(filename+'.raw0x'+IntToHex(dat_offset,8)) THEN BEGIN
+      filestream:=TFileStream.Create(filename+'.raw0x'+IntToHex(dat_offset,8),fmOpenReadWrite);
+      filestream.Seek(0,soFromEnd);
+    END ELSE BEGIN
+      filestream:=TFileStream.Create(filename+'.raw0x'+IntToHex(dat_offset,8),fmCreate);
+    END;
+    filestream.Write(data[0],Length(data));
+    filestream.Free;
+  END;
+
+FUNCTION ExportSNDD;
+{  CONST
+    WAVheader:Array[0..0] OF Byte=(
+        Ord('R'),Ord('I'),Ord('F'),Ord('F'),0,0,0,0,Ord('W'),Ord('A'),Ord('V'),Ord('E'),
+        Ord('f'),Ord('m'),Ord('t'),Ord(' '),24,0,0,0,
+      );
+}  TYPE
+    TDatData=RECORD
+      {0x00}
+      _fileid:LongWord;
+      level:LongWord;
+      Flag:LongWord;
+      FormatTag:Word;
+      ChanNo:Word;
+      {0x10}
+      SampleRate:LongWord;
+      BytesPSec:LongWord;
+      BPSample:LongWord;
+      BitsPS:LongWord;
+      {0x20}
+      Unknown:Array[1..7] OF LongWord;
+      Unknown2:Word;
+      {0x40}
+      RawSize:LongWord;
+      RawPos:LongWord;
+    END;
+  VAR
+      filestream:TFileStream;
+
+    DatData:TDatData;
+      //Wave Header Stuff
+      ASCII_Group:LongWord; //"RIFF"
+      WAV_Len:LongWord;
+      ASCII_WAV:LongWord; //"WAVE"
+      ASCII_FMT:LongWord; //"fmt "
+      WAV_FMT_Len:LongWord;
+      ASCII_DATA:LongWord; //"data"
+      WAV_FolLen:LongWord;
+
+      data:Tdata;
+  BEGIN
+      Result:=export_noerror;
+    OniDataConnection.LoadDatFilePart(fileid,0,SizeOf(DatData),@DatData);
+    WITH DatData DO BEGIN
+        //Initializing Header vars
+        ASCII_Group:=1179011410; // 'RIFF'
+        WAV_Len:=RAWSize+70;
+        ASCII_WAV:=1163280727;  // 'WAVE'
+        ASCII_FMT:=544501094;   // 'fmt '
+        WAV_FMT_Len:=50;        // 50 bytes
+        ASCII_DATA:=1635017060; // 'data'
+        WAV_FolLen:=RAWSize;
+        SetLength(data,RAWSize);
+        OniDataConnection.LoadRawFile(fileid,$44,data);
+
+      filestream:=TFileStream.Create(filename+'.raw',fmCreate);
+      filestream.Write(data[0],Length(data));
+      filestream.Free;
+
+      IF convert THEN BEGIN
+          //Now start packing this into a neat wave...
+        filestream:=TFileStream.Create(filename+'.wav',fmCreate);
+          filestream.Write(ASCII_Group,SizeOf(ASCII_Group));
+          filestream.Write(WAV_Len,SizeOf(WAV_Len));
+          filestream.Write(ASCII_WAV,SizeOf(ASCII_WAV));
+          filestream.Write(ASCII_FMT,SizeOf(ASCII_FMT));
+          filestream.Write(WAV_FMT_Len,SizeOf(WAV_FMT_Len));
+          filestream.Write(ChanNo,SizeOf(ChanNo));
+          filestream.Write(Samplerate,SizeOf(Samplerate));
+          filestream.Write(BytesPSec,SizeOf(BytesPSec));
+          filestream.Write(BPSample,SizeOf(BPSample));
+          filestream.Write(BitsPS,SizeOf(BitsPS));
+          filestream.Write(Unknown[1],SizeOf(Unknown));
+          filestream.Write(Unknown2,SizeOf(Unknown2));
+          filestream.Write(ASCII_DATA,SizeOf(ASCII_DATA));
+          filestream.Write(WAV_FolLen,SizeOf(WAV_FolLen));
+          filestream.Write(data[0],Length(data));
+          filestream.Free;
+      END;
+    END;
+  END;
+
+FUNCTION ExportTRAC;
+  VAR
+    link:LongWord;
+    linkcount:Word;
+    i:LongWord;
+  BEGIN
+    Result:=export_noerror;
+
+    OniDataConnection.LoadDatFilePart(fileid,$18,SizeOf(link),@link);
+    link:=link DIV 256;
+
+    OniDataConnection.LoadDatFilePart(fileid,$1E,SizeOf(linkcount),@linkcount);
+    FOR i:=1 TO linkcount DO BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$20+(i-1)*12+8,SizeOf(link),@link);
+      link:=link DIV 256;
+    END;
+  END;
+
+FUNCTION ExportTXAN;
+  VAR
+    loop_speed,unknown:Word;
+    linkcount:LongWord;
+    link:LongWord;
+    i:Byte;
+  BEGIN
+    Result:=export_noerror;
+
+    OniDataConnection.LoadDatFilePart(fileid,$14,SizeOf(loop_speed),@loop_speed);
+    OniDataConnection.LoadDatFilePart(fileid,$16,SizeOf(unknown),@unknown);
+
+    OniDataConnection.LoadDatFilePart(fileid,$1C,SizeOf(linkcount),@linkcount);
+    FOR i:=0 TO linkcount-1 DO BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$20+i*4,SizeOf(link),@link);
+      link:=link DIV 256;
+      IF link=0 THEN link:=fileid-1;
+    END;
+  END;
+
+FUNCTION ExportTXMB;
+  VAR
+    filestream:TFileStream;
+//    img:TImgPackage;
+    data:Tdata;
+  BEGIN
+    Result:=export_noerror;
+    IF convert THEN BEGIN
+{      img:=LoadTXMBconnected(fileid);
+      data:=ImgdataToBmp(img.imgx,img.imgy,img.imgdepth,img.storetype,img.imgdata);
+      filestream:=TFileStream.Create(filename+'.bmp',fmCreate);
+      filestream.Write(data[0],Length(data));
+      filestream.Free;
+}    END;
+  END;
+
+FUNCTION ExportTXMP;
+  VAR
+    filestream:TFileStream;
+//    img:TImgPackage;
+  BEGIN
+    Result:=export_noerror;
+{    img:=LoadImgData(fileid);
+
+    filestream:=TFileStream.Create(filename+'.raw',fmCreate);
+    filestream.Write(img.imgdata[0],Length(img.imgdata));
+    filestream.Free;
+
+    IF convert THEN BEGIN
+      img.imgdata:=ImgdataToBMP(img.imgx,img.imgy,img.imgdepth,img.storetype,img.imgdata);
+      filestream:=TFileStream.Create(filename+'.bmp',fmCreate);
+      filestream.Write(img.imgdata[0],Length(img.imgdata));
+      filestream.Free;
+    END;
+}  END;
+
+END.
Index: /oup/current/Unit5_preview.dfm
===================================================================
--- /oup/current/Unit5_preview.dfm	(revision 10)
+++ /oup/current/Unit5_preview.dfm	(revision 10)
@@ -0,0 +1,191 @@
+object Form5: TForm5
+  Left = 0
+  Top = 0
+  Caption = 'Preview'
+  ClientHeight = 473
+  ClientWidth = 472
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIChild
+  OldCreateOrder = False
+  Visible = True
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCreate = FormCreate
+  OnResize = FormResize
+  PixelsPerInch = 96
+  TextHeight = 13
+  object Splitter1: TSplitter
+    Left = 150
+    Top = 0
+    Width = 9
+    Height = 473
+    AutoSnap = False
+    Beveled = True
+    MinSize = 150
+  end
+  object panel_preview: TPanel
+    Left = 159
+    Top = 0
+    Width = 313
+    Height = 473
+    Align = alClient
+    BevelOuter = bvNone
+    TabOrder = 0
+    object img: TImage
+      Left = 0
+      Top = 20
+      Width = 313
+      Height = 453
+      Align = alClient
+    end
+    object lbl_notpossible: TLabel
+      Left = 16
+      Top = 56
+      Width = 97
+      Height = 65
+      AutoSize = False
+      Caption = 'No preview possible for this filetype'
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -16
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      ParentFont = False
+      Visible = False
+      WordWrap = True
+    end
+    object panel_buttons: TPanel
+      Left = 0
+      Top = 0
+      Width = 313
+      Height = 20
+      Align = alTop
+      BevelOuter = bvNone
+      TabOrder = 0
+      Visible = False
+      OnResize = panel_buttonsResize
+      object btn_dec: TButton
+        Left = 0
+        Top = 0
+        Width = 20
+        Height = 20
+        Caption = '-'
+        Enabled = False
+        TabOrder = 0
+        OnClick = btn_decClick
+      end
+      object btn_startstop: TButton
+        Left = 21
+        Top = 0
+        Width = 80
+        Height = 20
+        Caption = 'Stop automatic'
+        TabOrder = 1
+        OnClick = btn_startstopClick
+      end
+      object btn_inc: TButton
+        Left = 102
+        Top = 0
+        Width = 20
+        Height = 20
+        Caption = '+'
+        Enabled = False
+        TabOrder = 2
+        OnClick = btn_incClick
+      end
+    end
+  end
+  object panel_files: TPanel
+    Left = 0
+    Top = 0
+    Width = 150
+    Height = 473
+    Align = alLeft
+    BevelOuter = bvNone
+    TabOrder = 1
+    object list: TListBox
+      Left = 0
+      Top = 0
+      Width = 150
+      Height = 370
+      Align = alClient
+      ItemHeight = 13
+      TabOrder = 0
+      OnClick = listClick
+    end
+    object panel_extension: TPanel
+      Left = 0
+      Top = 370
+      Width = 150
+      Height = 103
+      Align = alBottom
+      BevelOuter = bvNone
+      TabOrder = 1
+      OnResize = panel_extensionResize
+      object lbl_filter: TLabel
+        Left = 2
+        Top = 62
+        Width = 100
+        Height = 17
+        AutoSize = False
+        Caption = 'Filter by &extension:'
+        FocusControl = combo_extension
+      end
+      object combo_extension: TComboBox
+        Left = 2
+        Top = 76
+        Width = 145
+        Height = 21
+        Style = csDropDownList
+        DropDownCount = 12
+        Font.Charset = DEFAULT_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -11
+        Font.Name = 'Tahoma'
+        Font.Style = []
+        ItemHeight = 13
+        ParentFont = False
+        Sorted = True
+        TabOrder = 3
+        OnClick = combo_extensionClick
+      end
+      object check_zerobyte: TCheckBox
+        Left = 2
+        Top = 44
+        Width = 130
+        Height = 13
+        Caption = 'Show &zero-byte files'
+        TabOrder = 2
+        OnClick = check_zerobyteClick
+      end
+      object edit_filtername: TEdit
+        Left = 2
+        Top = 20
+        Width = 145
+        Height = 18
+        AutoSize = False
+        TabOrder = 1
+      end
+      object check_filtername: TCheckBox
+        Left = 2
+        Top = 5
+        Width = 130
+        Height = 15
+        Caption = 'Filter by file&name:'
+        TabOrder = 0
+        OnClick = check_filternameClick
+      end
+    end
+  end
+  object timer: TTimer
+    Enabled = False
+    OnTimer = timerTimer
+    Left = 144
+    Top = 24
+  end
+end
Index: /oup/current/Unit5_preview.pas
===================================================================
--- /oup/current/Unit5_preview.pas	(revision 10)
+++ /oup/current/Unit5_preview.pas	(revision 10)
@@ -0,0 +1,301 @@
+UNIT Unit5_preview;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Math, ExtCtrls, StdCtrls, StrUtils, Menus,
+  Unit2_functions, Unit3_data, Unit4_exporters, Unit6_imgfuncs, Unit15_Classes;
+
+TYPE
+  TForm5 = Class(TForm)
+    timer: TTimer;
+    panel_preview: TPanel;
+    img: TImage;
+    panel_buttons: TPanel;
+    btn_dec: TButton;
+    btn_startstop: TButton;
+    btn_inc: TButton;
+    Splitter1: TSplitter;
+    lbl_notpossible: TLabel;
+    panel_files: TPanel;
+    list: TListBox;
+    panel_extension: TPanel;
+    lbl_filter: TLabel;
+    combo_extension: TComboBox;
+    check_zerobyte: TCheckBox;
+    edit_filtername: TEdit;
+    check_filtername: TCheckBox;
+    PROCEDURE LoadFileNames;
+    PROCEDURE check_filternameClick(Sender: TObject);
+    PROCEDURE check_zerobyteClick(Sender: TObject);
+    PROCEDURE combo_extensionClick(Sender: TObject);
+    PROCEDURE panel_extensionResize(Sender: TObject);
+    PROCEDURE listClick(Sender: TObject);
+    PROCEDURE Recreatelist;
+
+    PROCEDURE PreviewTXAN;
+    PROCEDURE PreviewTXMB;
+    PROCEDURE PreviewTXMP;
+    PROCEDURE PreviewPSpc;
+    PROCEDURE btn_incClick(Sender: TObject);
+    PROCEDURE btn_decClick(Sender: TObject);
+    PROCEDURE FormResize(Sender: TObject);
+    PROCEDURE btn_startstopClick(Sender: TObject);
+    PROCEDURE panel_buttonsResize(Sender: TObject);
+    PROCEDURE timerTimer(Sender: TObject);
+    PROCEDURE FormCreate(Sender: TObject);
+    PROCEDURE FormClose(Sender: TObject; var Action: TCloseAction);
+  PRIVATE
+    memstreams:Array OF TMemoryStream;
+    actualimg:Byte;
+    _fileid:LongWord;
+  PUBLIC
+  END;
+
+VAR
+  Form5: TForm5;
+
+IMPLEMENTATION
+{$R *.dfm}
+USES Unit1_main;
+
+
+PROCEDURE TForm5.Recreatelist;
+  VAR
+    i:LongWord;
+    exts:TStringArray;
+  BEGIN
+    combo_extension.Items.Clear;
+    combo_extension.Items.Add('_All files_ ('+IntToStr(OniDataConnection.GetFilesCount)+')');
+    exts:=OniDataConnection.GetExtensionsList;
+    FOR i:=0 TO High(exts) DO
+      combo_extension.Items.Add(exts[i]);
+    combo_extension.ItemIndex:=0;
+    combo_extensionClick(Self);
+  END;
+
+PROCEDURE TForm5.LoadFileNames;
+  VAR
+    Extension:String[4];
+    no_zero_bytes:Boolean;
+    pattern:String;
+    files:TStringArray;
+    i:LongWord;
+  BEGIN
+    Extension:=MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex],1,4);
+    no_zero_bytes:=NOT check_zerobyte.Checked;
+    pattern:='';
+    IF check_filtername.Checked THEN pattern:=edit_filtername.Text;
+    IF Extension='_All' THEN Extension:='';
+
+    files:=OniDataConnection.GetFilesList(extension,pattern,no_zero_bytes);
+    list.Items.Clear;
+    IF Length(files)>0 THEN
+      FOR i:=0 TO High(files) DO
+        list.Items.Add(files[i]);
+  END;
+
+PROCEDURE TForm5.panel_extensionResize(Sender: TObject);
+  BEGIN
+    combo_extension.Width:=panel_extension.Width-5;
+    edit_filtername.Width:=panel_extension.Width-5;
+  END;
+
+PROCEDURE TForm5.combo_extensionClick(Sender: TObject);
+  BEGIN
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm5.check_zerobyteClick(Sender: TObject);
+  VAR
+    i:Byte;
+  BEGIN
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm5.check_filternameClick(Sender: TObject);
+  BEGIN
+    edit_filtername.Enabled:=NOT check_filtername.Checked;
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm5.listClick(Sender: TObject);
+  BEGIN
+    _fileid:=OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]);
+    lbl_notpossible.Visible:=False;
+    Self.img.Visible:=True;
+    Self.timer.Enabled:=False;
+    Self.panel_buttons.Visible:=False;
+    IF RightStr(list.Items.Strings[list.ItemIndex],4)='PSpc' THEN PreviewPSpc
+    ELSE
+    IF RightStr(list.Items.Strings[list.ItemIndex],4)='TXAN' THEN PreviewTXAN
+    ELSE
+    IF RightStr(list.Items.Strings[list.ItemIndex],4)='TXMB' THEN PreviewTXMB
+    ELSE
+    IF RightStr(list.Items.Strings[list.ItemIndex],4)='TXMP' THEN PreviewTXMP
+    ELSE BEGIN
+      Self.lbl_notpossible.Visible:=True;
+      Self.img.Visible:=False;
+    END;
+  END;
+
+
+
+PROCEDURE TForm5.PreviewPSpc;
+  VAR
+    OniImage:TOniImage;
+    data:Tdata;
+  BEGIN
+    SetLength(memstreams,1);
+    OniImage:=TOniImage.Create;
+    OniImage.LoadFromPSpc(_fileid);
+    data:=OniImage.GetAsBMP;
+    OniImage.Free;
+
+    memstreams[0].Clear;
+    memstreams[0].Write(data[0],Length(data));
+    memstreams[0].Seek(0,soFromBeginning);
+
+    Self.img.Picture.Bitmap.LoadFromStream(memstreams[0]);
+  END;
+
+
+PROCEDURE TForm5.PreviewTXMB;
+  VAR
+    OniImage:TOniImage;
+    data:Tdata;
+  BEGIN
+    SetLength(memstreams,1);
+    OniImage:=TOniImage.Create;
+    OniImage.LoadFromTXMB(_fileid);
+    data:=OniImage.GetAsBMP;
+    OniImage.Free;
+
+    memstreams[0].Clear;
+    memstreams[0].Write(data[0],Length(data));
+    memstreams[0].Seek(0,soFromBeginning);
+
+    Self.img.Picture.Bitmap.LoadFromStream(memstreams[0]);
+  END;
+
+PROCEDURE TForm5.PreviewTXMP;
+  VAR
+    OniImage:TOniImage;
+    data:Tdata;
+  BEGIN
+    SetLength(memstreams,1);
+    OniImage:=TOniImage.Create;
+    OniImage.LoadFromTXMP(_fileid);
+    data:=OniImage.GetAsBMP;
+    OniImage.Free;
+
+    memstreams[0].Clear;
+    memstreams[0].Write(data[0],Length(data));
+    memstreams[0].Seek(0,soFromBeginning);
+
+    Self.img.Picture.Bitmap.LoadFromStream(memstreams[0]);
+  END;
+
+PROCEDURE TForm5.PreviewTXAN;
+  VAR
+    loop_speed:Word;
+    linkcount:LongWord;
+    link:LongWord;
+    i:Byte;
+    data:Tdata;
+    OniImage:TOniImage;
+  BEGIN
+    OniDataConnection.LoadDatFilePart(_fileid,$14,SizeOf(loop_speed),@loop_speed);
+    OniDataConnection.LoadDatFilePart(_fileid,$1C,SizeOf(linkcount),@linkcount);
+    SetLength(memstreams,linkcount);
+    FOR i:=0 TO linkcount-1 DO BEGIN
+      OniDataConnection.LoadDatFilePart(_fileid,$20+i*4,SizeOf(link),@link);
+      link:=link DIV 256;
+      IF link=0 THEN link:=_fileid-1;
+      memstreams[i]:=TMemoryStream.Create;
+      OniImage:=TOniImage.Create;
+      OniImage.LoadFromTXMP(link);
+      data:=OniImage.GetAsBMP;
+      OniImage.Free;
+      memstreams[i].Clear;
+      memstreams[i].Write(data[0],Length(data));
+      memstreams[i].Seek(0,soFromBeginning);
+    END;
+    actualimg:=254;
+    Self.timer.Interval:=Floor(loop_speed*(1/60)*1000);
+    Self.timer.Enabled:=False;
+    Self.btn_startstopClick(Self);
+    Self.panel_buttons.Visible:=True;
+  END;
+
+
+PROCEDURE TForm5.FormCreate(Sender: TObject);
+  BEGIN
+    SetLength(memstreams,1);
+    memstreams[0]:=TMemoryStream.Create;
+    Self.Width:=260;
+    Self.Height:=300;
+  END;
+
+PROCEDURE TForm5.timerTimer(Sender: TObject);
+  BEGIN
+    Inc(actualimg);
+    IF actualimg>=Length(memstreams) THEN actualimg:=0;
+    Self.img.Picture.Bitmap.LoadFromStream(memstreams[actualimg]);
+    memstreams[actualimg].Seek(0,soFromBeginning);
+    Self.Caption:='Preview '+OniDataConnection.GetFileInfo(_fileid).FileName+' ('+IntToStr(actualimg+1)+'/'+IntToStr(Length(memstreams))+')';
+  END;
+
+PROCEDURE TForm5.panel_buttonsResize(Sender: TObject);
+  BEGIN
+    btn_startstop.Width:=panel_buttons.Width-45;
+    btn_inc.Left:=panel_buttons.Width-23;
+  END;
+
+PROCEDURE TForm5.btn_startstopClick(Sender: TObject);
+  BEGIN
+    Self.timer.Enabled:=NOT Self.timer.Enabled;
+    Self.btn_dec.Enabled:=NOT Self.timer.Enabled;
+    Self.btn_inc.Enabled:=NOT Self.timer.Enabled;
+    IF Self.timer.Enabled THEN
+      Self.btn_startstop.Caption:='Stop automatic'
+    ELSE
+      Self.btn_startstop.Caption:='Start automatic';
+  END;
+
+PROCEDURE TForm5.FormResize(Sender: TObject);
+  BEGIN
+    IF Self.Width>=300 THEN BEGIN
+    END ELSE Self.Width:=300;
+    IF Self.Height>=200 THEN BEGIN
+    END ELSE Self.Height:=200;
+  END;
+
+PROCEDURE TForm5.btn_decClick(Sender: TObject);
+  BEGIN
+    IF actualimg>0 THEN
+      Dec(actualimg)
+    ELSE
+      actualimg:=High(memstreams);
+    Self.Caption:='Preview '+OniDataConnection.GetFileInfo(_fileid).FileName+' ('+IntToStr(actualimg+1)+'/'+IntToStr(Length(memstreams))+')';
+    Self.img.Picture.Bitmap.LoadFromStream(memstreams[actualimg]);
+    memstreams[actualimg].Seek(0,soFromBeginning);
+  END;
+
+PROCEDURE TForm5.btn_incClick(Sender: TObject);
+  BEGIN
+    IF actualimg<High(memstreams) THEN
+      Inc(actualimg)
+    ELSE
+      actualimg:=0;
+    Self.Caption:='Preview '+OniDataConnection.GetFileInfo(_fileid).FileName+' ('+IntToStr(actualimg+1)+'/'+IntToStr(Length(memstreams))+')';
+    Self.img.Picture.Bitmap.LoadFromStream(memstreams[actualimg]);
+    memstreams[actualimg].Seek(0,soFromBeginning);
+  END;
+
+
+PROCEDURE TForm5.FormClose(Sender: TObject; var Action: TCloseAction);
+  BEGIN
+    Action:=caFree;
+  END;
+
+END.
Index: /oup/current/Unit6_imgfuncs.pas
===================================================================
--- /oup/current/Unit6_imgfuncs.pas	(revision 10)
+++ /oup/current/Unit6_imgfuncs.pas	(revision 10)
@@ -0,0 +1,693 @@
+unit Unit6_imgfuncs;
+interface
+uses Math, Dialogs, Types, SysUtils, Classes, Unit3_data, Unit15_Classes;
+
+type
+  TImgDataType=Set of (DT_OniReverted,DT_Oni,DT_Decoded32);
+
+type
+  TOniImage = class
+    private
+      FLoaded:Boolean;
+      FDataType:TImgDataType;
+      FData:Tdata;
+      FWidth,FHeight:Word;
+      FDepth:Byte;
+      FStoreType:Byte;
+
+      function ResizeImage(oldx,oldy:LongWord; img:Tdata):Tdata;
+      procedure RevertImage;
+      procedure DecodeImage;
+      procedure DecompressImage;
+    protected
+    public
+      property Loaded:Boolean read FLoaded write FLoaded;
+      property DataType:TImgDataType read FDataType write FDataType;
+      property Width:Word read FWidth write FWidth;
+      property Height:Word read FHeight write FHeight;
+      property Depth:Byte read FDepth write FDepth;
+      property StoreType:Byte read FStoreType write FStoreType;
+      property Data:Tdata read FData write FData;
+
+      constructor Create;
+      function LoadFromPSpc(fileid:LongWord):Boolean;
+      function LoadFromTXMP(fileid:LongWord):Boolean;
+      function LoadFromTXMB(fileid:LongWord):Boolean;
+      function GetImageDataSize(fading:Boolean):LongWord;
+
+      function GetAsData:Tdata;
+      function GetAs32bit:Tdata;
+      function GetAsBMP:Tdata;
+      function LoadFromBMP(filename:String):Boolean;
+      function WriteToBMP(filename:String):Boolean;
+      function GetMipMappedImage(var faded:Tdata):Boolean;
+    published
+  end;
+
+
+implementation
+uses Unit2_functions;
+
+
+
+constructor TOniImage.Create;
+  begin
+    Self.FLoaded:=False;
+    Self.FDataType:=[];
+    SetLength(Self.FData,0);
+    Self.FWidth:=0;
+    Self.FHeight:=0;
+    Self.FDepth:=0;
+    Self.FStoreType:=0;
+  end;
+
+
+
+function TOniImage.ResizeImage(oldx,oldy:LongWord; img:Tdata):Tdata;
+  var
+    i,j:LongWord;
+    col,row,row_orig:LongWord;
+  begin
+    SetLength(Result,(oldx div 2)*(oldy div 2)*(Self.FDepth div 8));
+    row_orig:=0;
+    row:=0;
+    col:=0;
+    for i:=0 to (oldx*oldy)-1 do begin
+      if ((i mod oldx)=0) and (i>0) then begin
+        Inc(row_orig);
+        if (row_orig mod 2)=0 then begin
+          Inc(row);
+          col:=0;
+        end;
+      end;
+      if (row_orig mod 2)=0 then begin
+        if (i mod 2)=0 then begin
+          for j:=0 to (Self.FDepth div 8)-1 do
+            Result[((row*(oldx div 2))+col)*(Self.FDepth div 8)+j]:=img[(i*(Self.FDepth div 8))+j];
+          Inc(col);
+        end;
+      end;
+    end;
+  end;
+
+
+
+procedure TOniImage.RevertImage;
+  var
+    x,y,i:LongWord;
+    tempd:Tdata;
+  begin
+    SetLength(tempd, Self.FWidth * Self.FHeight *(Self.FDepth div 8));
+    for y:=0 to Self.FHeight-1 do
+      for x:=0 to Self.FWidth-1 do
+        for i:=0 to (Self.FDepth div 8)-1 do
+          tempd[((Self.FWidth*(Self.FHeight-1-y)+x)*(Self.FDepth div 8))+i]:=
+                  Self.FData[(Self.FWidth*y+x)*(Self.FDepth div 8)+i];
+    for x:=0 to High(tempd) do
+      Self.FData[x]:=tempd[x];
+    if DT_OniReverted in Self.FDataType then
+      Self.FDataType:=Self.FDataType-[DT_OniReverted]
+    else
+      Self.FDataType:=Self.FDataType+[DT_OniReverted];
+  end;
+
+
+
+procedure TOniImage.DecodeImage;
+  var
+    x,y:LongWord;
+    tempd:Tdata;
+  begin
+    if not (DT_Decoded32 in Self.FDataType) then begin
+      SetLength(tempd, Self.FWidth * Self.FHeight * 4);
+      case Self.FStoreType of
+        0: begin
+            for y:=0 to Self.FHeight-1 do begin
+              for x:=0 to Self.FWidth-1 do begin
+                tempd[((Self.FWidth*y+x)*4)+0]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $000F ) / $000F * 255);
+                tempd[((Self.FWidth*y+x)*4)+1]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $00F0 ) / $00F0 * 255);
+                tempd[((Self.FWidth*y+x)*4)+2]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $0F00 ) / $0F00 * 255);
+                tempd[((Self.FWidth*y+x)*4)+3]:=0;
+              end;
+            end;
+          end;
+        1,2: begin
+            for y:=0 to Self.FHeight-1 do begin
+              for x:=0 to Self.FWidth-1 do begin
+                tempd[((Self.FWidth*y+x)*4)+0]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $001F ) / $001F * 255);
+                tempd[((Self.FWidth*y+x)*4)+1]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $03E0 ) / $03E0 * 255);
+                tempd[((Self.FWidth*y+x)*4)+2]:=Floor( ( (Self.FData[(Self.FWidth*y+x)*2]+Self.FData[(Self.FWidth*y+x)*2+1]*256) AND $7C00 ) / $7C00 * 255);
+                tempd[((Self.FWidth*y+x)*4)+3]:=0;
+              end;
+            end;
+          end;
+        9: begin
+            DecompressImage;
+          end;
+      end;
+      Self.FDepth:=32;
+      if (Self.FStoreType<>9) AND (Self.FStoreType<>8) then begin
+        SetLength(Self.FData, Length(tempd));
+        for x:=0 to High(tempd) do
+          Self.FData[x]:=tempd[x];
+      end;
+      Self.FStoreType:=8;
+      if DT_Oni in Self.FDataType then
+        Self.FDataType:=Self.FDataType-[DT_Oni];
+      Self.FDataType:=Self.FDataType+[DT_Decoded32];
+    end;
+    if DT_OniReverted in Self.FDataType then
+      Self.RevertImage;
+  end;
+
+
+
+procedure TOniImage.DecompressImage;
+  type
+    Tcolor=record
+        RGBb:Byte;
+        RGBg:Byte;
+        RGBr:Byte;
+        RGBa:Byte;
+      end;
+  var
+    i,j,x,y:LongWord;
+    color:Array[1..4] of Tcolor;
+    pixel:Array[1..16] of Byte;
+    tempd:Tdata;
+  begin
+    x:=0;
+    y:=0;
+    SetLength(tempd, Self.FWidth * Self.FHeight * 4);
+    for i:=0 to ((Self.FWidth * Self.FHeight) div 16)-1 do begin
+      Color[1].RGBb:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $001F) / $001F * 255);
+      Color[1].RGBg:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $07E0) / $07E0 * 255);
+      Color[1].RGBr:=Floor(((Self.FData[(i*8)+0]+Self.FData[(i*8)+1]*256) and $F800) / $F800 * 255);
+      Color[1].RGBa:=255;
+      Color[2].RGBb:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $001F) / $001F * 255);
+      Color[2].RGBg:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $07E0) / $07E0 * 255);
+      Color[2].RGBr:=Floor(((Self.FData[(i*8)+2]+Self.FData[(i*8)+3]*256) and $F800) / $F800 * 255);
+      Color[2].RGBa:=255;
+      Color[3].RGBb:=Floor( Color[1].RGBb/3*2 + Color[2].RGBb/3 );
+      Color[3].RGBg:=Floor( Color[1].RGBg/3*2 + Color[2].RGBg/3 );
+      Color[3].RGBr:=Floor( Color[1].RGBr/3*2 + Color[2].RGBr/3 );
+      Color[3].RGBa:=255;
+      Color[4].RGBb:=Floor( Color[1].RGBb/3 + Color[2].RGBb/3*2 );
+      Color[4].RGBg:=Floor( Color[1].RGBg/3 + Color[2].RGBg/3*2 );
+      Color[4].RGBr:=Floor( Color[1].RGBr/3 + Color[2].RGBr/3*2 );
+      Color[4].RGBa:=255;
+      Pixel[1]:=Floor( (Self.FData[(i*8)+4] and $C0) / $40 + 1 );
+      Pixel[2]:=Floor( (Self.FData[(i*8)+4] and $30) / $10 + 1 );
+      Pixel[3]:=Floor( (Self.FData[(i*8)+4] and $0C) / $04 + 1 );
+      Pixel[4]:=Floor( (Self.FData[(i*8)+4] and $03) + 1 );
+      Pixel[5]:=Floor( (Self.FData[(i*8)+5] and $C0) / $40 + 1 );
+      Pixel[6]:=Floor( (Self.FData[(i*8)+5] and $30) / $10 + 1 );
+      Pixel[7]:=Floor( (Self.FData[(i*8)+5] and $0C) / $04 + 1 );
+      Pixel[8]:=Floor( (Self.FData[(i*8)+5] and $03) + 1 );
+      Pixel[9]:=Floor( (Self.FData[(i*8)+6] and $C0) / $40 + 1 );
+      Pixel[10]:=Floor( (Self.FData[(i*8)+6] and $30) / $10 + 1 );
+      Pixel[11]:=Floor( (Self.FData[(i*8)+6] and $0C) / $04 + 1 );
+      Pixel[12]:=Floor( (Self.FData[(i*8)+6] and $03) + 1 );
+      Pixel[13]:=Floor( (Self.FData[(i*8)+7] and $C0) / $40 + 1 );
+      Pixel[14]:=Floor( (Self.FData[(i*8)+7] and $30) / $10 + 1 );
+      Pixel[15]:=Floor( (Self.FData[(i*8)+7] and $0C) / $04 + 1 );
+      Pixel[16]:=Floor( (Self.FData[(i*8)+7] and $03) + 1 );
+      for j:=0 to 3 do begin
+        tempd[((y+3)*Self.FWidth+x+j)*4+0]:=Color[Pixel[16-j]].RGBb;
+        tempd[((y+3)*Self.FWidth+x+j)*4+1]:=Color[Pixel[16-j]].RGBg;
+        tempd[((y+3)*Self.FWidth+x+j)*4+2]:=Color[Pixel[16-j]].RGBr;
+        tempd[((y+3)*Self.FWidth+x+j)*4+3]:=0;
+      end;
+      for j:=0 to 3 do begin
+        tempd[((y+2)*Self.FWidth+x+j)*4+0]:=Color[Pixel[12-j]].RGBb;
+        tempd[((y+2)*Self.FWidth+x+j)*4+1]:=Color[Pixel[12-j]].RGBg;
+        tempd[((y+2)*Self.FWidth+x+j)*4+2]:=Color[Pixel[12-j]].RGBr;
+        tempd[((y+2)*Self.FWidth+x+j)*4+3]:=0;
+      end;
+      for j:=0 to 3 do begin
+        tempd[((y+1)*Self.FWidth+x+j)*4+0]:=Color[Pixel[8-j]].RGBb;
+        tempd[((y+1)*Self.FWidth+x+j)*4+1]:=Color[Pixel[8-j]].RGBg;
+        tempd[((y+1)*Self.FWidth+x+j)*4+2]:=Color[Pixel[8-j]].RGBr;
+        tempd[((y+1)*Self.FWidth+x+j)*4+3]:=0;
+      end;
+      for j:=0 to 3 do begin
+        tempd[((y+0)*Self.FWidth+x+j)*4+0]:=Color[Pixel[4-j]].RGBb;
+        tempd[((y+0)*Self.FWidth+x+j)*4+1]:=Color[Pixel[4-j]].RGBg;
+        tempd[((y+0)*Self.FWidth+x+j)*4+2]:=Color[Pixel[4-j]].RGBr;
+        tempd[((y+0)*Self.FWidth+x+j)*4+3]:=0;
+      end;
+      x:=x+4;
+      if x=Self.FWidth THEN begin
+        y:=y+4;
+        x:=0;
+      end;
+    end;
+    SetLength(Self.FData, Length(tempd));
+    for i:=0 to High(tempd) do
+      Self.FData[i]:=tempd[i];
+    Self.FStoreType:=8;
+    Self.FDepth:=32;
+    Self.FDataType:=Self.FDataType-[DT_Oni]+[DT_Decoded32];
+  end;
+
+
+
+
+
+function TOniImage.LoadFromPSpc(fileid:LongWord):Boolean;
+  type
+    TPoint=Packed Record
+      X,Y:Word;
+    end;
+    TPSpc=Packed Record
+      p1:Array[0..8] of TPoint;
+      p2:Array[0..8] of TPoint;
+      TXMP:LongWord;
+    end;
+    TPart=Packed Record
+      x_txmp,y_txmp:Word;
+      x_pspc,y_pspc:Word;
+      w,h:Word;
+      imgdata:Tdata;
+      used:Boolean;
+    end;
+  const
+    PartMatch:Array[0..8] of Byte=(0,3,6,1,4,7,2,5,8);
+  var
+    x,y,pixel:Word;
+    i:Integer;
+
+    PSpc:TPSpc;
+    txmpimg:TOniImage;
+    txmpdata:Tdata;
+    
+    parts:Array[0..8] of TPart;
+    part:Byte;
+    cols:Array[0..2] of Word;
+    rows:Array[0..2] of Word;
+    col,row:Byte;
+  begin
+    OniDataConnection.LoadDatFilePart ( fileid , $08 , SizeOf(PSpc) , @PSpc );
+    PSpc.TXMP := PSpc.TXMP div 256;
+    if PSpc.TXMP = 0 then begin
+      Result := False;
+      Exit;
+    end;
+    txmpimg := TOniImage.Create;
+    txmpimg.LoadFromTXMP ( PSpc.TXMP );
+    txmpimg.DecodeImage;
+    txmpimg.WriteToBMP('D:\file.bmp'); 
+    txmpdata:=txmpimg.GetAs32bit;
+{    ShowMessage(IntToStr(txmpimg.Width)+'x'+IntToStr(txmpimg.Height));
+    for i:=0 to High(txmpdata) do
+      txmpimg.Data[i]:=txmpdata[i];
+    txmpimg.WriteToBMP('D:\file2.bmp');
+}
+    with PSpc do begin
+      for i := 0 to 2 do begin
+        cols[i] := 0;
+        rows[i] := 0;
+      end;
+      for i := 0 to 8 do begin
+        part := PartMatch[i];
+        col := i div 3;
+        row := i mod 3;
+        if (p2[i].X>0) or (p2[i].Y>0) then begin
+          parts[part].x_txmp := p1[i].X - 1;
+          parts[part].y_txmp := p1[i].Y - 1;
+          parts[part].x_pspc := 0;
+          if col>0 then
+            for x := 0 to col-1 do
+              Inc( parts[part].x_pspc , cols[x] );
+          parts[part].y_pspc := 0;
+          if row>0 then
+            for y := 0 to row-1 do
+              Inc ( parts[part].y_pspc , rows[y] );
+          parts[part].w := p2[i].X - p1[i].X + 1;
+          parts[part].h := p2[i].Y - p1[i].Y + 1;
+          parts[part].used := True;
+          cols[col] := parts[part].w;
+          rows[row] := parts[part].h;
+          SetLength(parts[part].imgdata, parts[part].w * parts[part].h * 4);
+          for y := 0 to parts[part].h-1 do begin
+            for x := 0 to parts[part].w-1 do begin
+              for pixel := 0 to 3 do begin
+                parts[part].imgdata[ ( y*parts[part].w + x ) * 4 + pixel ] :=
+                   txmpdata[ ( ( parts[part].y_txmp + y ) * txmpimg.Width + parts[part].x_txmp + x ) * 4 + pixel ];
+              end;
+            end;
+          end;
+        end else begin
+          parts[part].used := False;
+        end;
+      end;
+
+    end;
+
+    txmpimg.Free;
+    txmpimg:=TOniImage.Create;
+    for i:=0 to 8 do begin
+      if parts[i].used then begin
+        SetLength( txmpimg.FData, Length(parts[i].imgdata) );
+        for pixel:=0 to High(parts[i].imgdata) do
+          txmpimg.Data[pixel]:=parts[i].imgdata[pixel];
+        txmpimg.Width:=parts[i].w;
+        txmpimg.Height:=parts[i].h;
+        txmpimg.StoreType:=8;
+        txmpimg.DataType:=[DT_Decoded32];
+        txmpimg.Depth:=32;
+        txmpimg.WriteToBMP('D:\'+IntToStr(i)+'.bmp');
+      end;
+    end;
+    txmpimg.Free;
+
+    Self.FWidth := 0;
+    Self.FHeight := 0;
+    for i := 0 to 2 do begin
+      Inc( Self.FWidth , cols[i] );
+      Inc( Self.FHeight , rows[i] );
+    end;
+    SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
+
+//Combine data parts
+
+    Self.FDepth:=32;
+    Self.FStoreType:=8;
+    Self.FDataType:=[DT_Decoded32];
+//    Self.RevertImage;
+  end;
+
+
+function TOniImage.LoadFromTXMP(fileid:LongWord):Boolean;
+  var
+    img_addr:LongWord;
+  begin
+    Result:=True;
+    OniDataConnection.LoadDatFilePart(fileid,$8C,SizeOf(Self.FWidth),@Self.FWidth);
+    OniDataConnection.LoadDatFilePart(fileid,$8E,SizeOf(Self.FHeight),@Self.FHeight);
+    OniDataConnection.LoadDatFilePart(fileid,$90,SizeOf(Self.FStoreType),@Self.FStoreType);
+    if not OniDataConnection.OSisMac then
+      OniDataConnection.LoadDatFilePart(fileid,$9C,SizeOf(img_addr),@img_addr)
+    else
+      OniDataConnection.LoadDatFilePart(fileid,$A0,SizeOf(img_addr),@img_addr);
+
+    case Self.FStoreType of
+      0,1,2: begin
+          SetLength(Self.FData, Self.FWidth * Self.FHeight * 2);
+          Self.FDepth:=16;
+        end;
+      8: begin
+          SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
+          Self.FDepth:=32;
+        end;
+      9: begin
+          SetLength(Self.FData, Self.FWidth * Self.FHeight div 2);
+          Self.FDepth:=16;
+        end;
+    else
+      Result:=False;
+      Exit;
+    end;
+
+    if not OniDataConnection.OSisMac then
+      OniDataConnection.LoadRawFile(fileid,$9C,@Self.FData[0])
+    else
+      OniDataConnection.LoadRawFile(fileid,$A0,@Self.FData[0]);
+
+    Self.FDataType:=[DT_OniReverted,DT_Oni];
+  end;
+
+
+
+function TOniImage.LoadFromTXMB(fileid:LongWord):Boolean;
+  var
+    i,x,y,x2,y2,pixelid,imgid:LongWord;
+    rows,cols:Word;
+    linkcount:LongWord;
+    link:LongWord;
+    images_decoded:Array of TOniImage;
+    x_start,y_start:LongWord;
+  begin
+    OniDataConnection.LoadDatFilePart(fileid,$10,SizeOf(Self.FWidth),@Self.FWidth);
+    OniDataConnection.LoadDatFilePart(fileid,$12,SizeOf(Self.FHeight),@Self.FHeight);
+    OniDataConnection.LoadDatFilePart(fileid,$18,SizeOf(cols),@cols);
+    OniDataConnection.LoadDatFilePart(fileid,$1A,SizeOf(rows),@rows);
+    OniDataConnection.LoadDatFilePart(fileid,$1C,SizeOf(linkcount),@linkcount);
+    SetLength(images_decoded,linkcount);
+    for i:=0 to linkcount-1 do begin
+      OniDataConnection.LoadDatFilePart(fileid,$20+i*4,SizeOf(link),@link);
+      link:=link div 256;
+      images_decoded[i]:=TOniImage.Create;
+      images_decoded[i].LoadFromTXMP(link);
+      images_decoded[i].DecodeImage;
+      images_decoded[i].RevertImage;
+    end;
+    SetLength(Self.FData, Self.FWidth * Self.FHeight * 4);
+    for y:=0 to rows-1 do begin
+      for x:=0 to cols-1 do begin
+        imgid:=y*cols+x;
+        x_start:=0;
+        y_start:=0;
+        for i:=0 to x do   if i<x then x_start:=x_start+images_decoded[i].Width;
+        for i:=0 to y do   if i<y then y_start:=y_start+images_decoded[i].Height;
+        for y2:=0 to images_decoded[imgid].Height-1 do begin
+          for x2:=0 to images_decoded[imgid].Width-1 do begin
+            if ( (x_start+x2)<Self.FWidth ) and ( (y_start+y2)<Self.FHeight ) then begin
+              pixelid:=y_start*Self.FWidth+x_start+y2*Self.FWidth+x2;
+              Self.FData[pixelid*4+0]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+0];
+              Self.FData[pixelid*4+1]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+1];
+              Self.FData[pixelid*4+2]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+2];
+              Self.FData[pixelid*4+3]:=images_decoded[imgid].Data[(y2*images_decoded[imgid].Width+x2)*4+3];
+            end;
+          end;
+        end;
+      end;
+    end;
+    for i:=0 to linkcount-1 do
+      images_decoded[i].Free;
+    Self.FDepth:=32;
+    Self.FStoreType:=8;
+    Self.FDataType:=[DT_Decoded32];
+    Self.RevertImage;
+  end;
+
+
+
+function TOniImage.GetImageDataSize(fading:Boolean):LongWord;
+  var
+    size:LongWord;
+    x,y:Word;
+    bpp:Byte;
+  begin
+    case Self.FStoreType of
+        9: bpp:=8;
+        0,1,2: bpp:=16;
+        8: bpp:=32;
+    else
+      Result:=0;
+      Exit;
+    end;
+
+    x:=Self.FWidth;
+    y:=Self.FHeight;
+    size:=x*y*bpp div 8;
+    if fading then begin
+      repeat
+        x:=x div 2;
+        y:=y div 2;
+        size:=size+x*y*bpp div 8;
+      until (x=1) or (y=1);
+    end;
+    Result:=size;
+  end;
+
+
+
+function TOniImage.GetAsData:Tdata;
+  var
+    i: Integer;
+    revert:Boolean;
+  begin
+//    if not (DT_Decoded32 in Self.FDataType) then
+//      Self.DecodeImage;
+    if not (DT_OniReverted in Self.FDataType) then begin
+      revert:=True;
+      Self.RevertImage;
+    end else revert:=False;
+    SetLength(Result, Length(Self.FData));
+    for i:=0 to High(Result) do
+      Result[i]:=Self.FData[i];
+    if revert then
+      Self.RevertImage;
+  end;
+
+
+
+function TOniImage.GetAs32bit:Tdata;
+  var
+    i:Integer;
+  begin
+    if not (DT_Decoded32 in Self.FDataType) then
+      Self.DecodeImage;
+    SetLength(Result,Length(Self.FData));
+    for i:=0 to High(Result) do
+      Result[i]:=Self.FData[i];
+  end;
+
+
+
+function TOniImage.GetAsBMP:Tdata;
+  const BMPheader:Array[0..53] of Byte=
+          ($42,$4D,0,0,0,0,0,0,0,0,54,0,0,0,
+           40,0,0,0,0,0,0,0,0,0,0,0,1,0,$18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+  var
+    i,x,y:LongWord;
+  begin
+    if not (DT_Decoded32 in Self.FDataType) then
+      Self.DecodeImage;
+
+    SetLength(Result, Self.FWidth * Self.FHeight * 3 + 54);
+    for y:=0 to Self.FHeight-1 do begin
+      for x:=0 to Self.FWidth-1 do begin
+        Result[((Self.FWidth*y+x)*3)+0+54]:=Self.FData[(Self.FWidth*y+x)*4+0];
+        Result[((Self.FWidth*y+x)*3)+1+54]:=Self.FData[(Self.FWidth*y+x)*4+1];
+        Result[((Self.FWidth*y+x)*3)+2+54]:=Self.FData[(Self.FWidth*y+x)*4+2];
+      end;
+    end;
+
+    for i:=0 to High(BMPheader) do
+      Result[i]:=BMPheader[i];
+    Result[2]:=((Self.FWidth*Self.FHeight*3+54) and $000000FF) div $1;
+    Result[3]:=((Self.FWidth*Self.FHeight*3+54) and $0000FF00) div $100;
+    Result[4]:=((Self.FWidth*Self.FHeight*3+54) and $00FF0000) div $10000;
+    Result[5]:=((Self.FWidth*Self.FHeight*3+54) and $FF000000) div $1000000;
+    Result[18]:=(Self.FWidth and $000000FF) div $1;
+    Result[19]:=(Self.FWidth and $0000FF00) div $100;
+    Result[20]:=(Self.FWidth and $00FF0000) div $10000;
+    Result[21]:=(Self.FWidth and $FF000000) div $1000000;
+    Result[22]:=(Self.FHeight and $000000FF) div $1;
+    Result[23]:=(Self.FHeight and $0000FF00) div $100;
+    Result[24]:=(Self.FHeight and $00FF0000) div $10000;
+    Result[25]:=(Self.FHeight and $FF000000) div $1000000;
+    Result[34]:=((Self.FWidth*Self.FHeight*3) and $000000FF) div $1;
+    Result[35]:=((Self.FWidth*Self.FHeight*3) and $0000FF00) div $100;
+    Result[36]:=((Self.FWidth*Self.FHeight*3) and $00FF0000) div $10000;
+    Result[37]:=((Self.FWidth*Self.FHeight*3) and $FF000000) div $1000000;
+  end;
+
+
+
+function TOniImage.LoadFromBMP(filename:String):Boolean;
+  var
+    filestream:TFileStream;
+    tempd:Tdata;
+
+    x,y:LongWord;
+  begin
+    filestream:=TFileStream.Create(filename, fmOpenRead);
+    SetLength(tempd,filestream.Size);
+    filestream.Read(tempd[0],filestream.Size);
+    filestream.Free;
+
+    if not((tempd[00]=$42) and (tempd[01]=$4D)) then begin
+      Result:=False;
+      ShowMessage('Not a standard 24bit bitmap');
+      Exit;
+    end;
+    if not(tempd[10]=54) then begin
+      Result:=False;
+      ShowMessage('Imagedata has to start at 0x54');
+      Exit;
+    end;
+    if not(tempd[14]=40) then begin
+      Result:=False;
+      ShowMessage('Second bitmap header has to have 40 bytes');
+      Exit;
+    end;
+    if not(tempd[28]=24) then begin
+      Result:=False;
+      ShowMessage('Bitmap has to have 24bits');
+      Exit;
+    end;
+    if not(tempd[30]=0) then begin
+      Result:=False;
+      ShowMessage('Bitmap has to be uncompressed');
+      Exit;
+    end;
+
+    Self.FWidth :=tempd[18]+tempd[19]*256+tempd[20]*256*256+tempd[21]*256*256*256;
+    Self.FHeight:=tempd[22]+tempd[23]*256+tempd[24]*256*256+tempd[25]*256*256*256;
+    Self.FDepth:=32;
+    Self.FStoreType:=8;
+
+    SetLength(Self.FData, Self.FWidth * Self.FHeight * Self.FDepth div 8);
+    for y:=0 to Self.FHeight-1 do begin
+      for x:=0 to Self.FWidth-1 do begin
+        Self.FData[((Self.FWidth*y+x)*4)+0]:=tempd[54+(Self.FWidth*y+x)*3+0];
+        Self.FData[((Self.FWidth*y+x)*4)+1]:=tempd[54+(Self.FWidth*y+x)*3+1];
+        Self.FData[((Self.FWidth*y+x)*4)+2]:=tempd[54+(Self.FWidth*y+x)*3+2];
+        Self.FData[((Self.FWidth*y+x)*4)+3]:=0;
+      end;
+    end;
+
+    Self.FDataType:=[DT_Decoded32];
+  end;
+
+
+
+function TOniImage.WriteToBMP(filename:String):Boolean;
+  var
+    filestream:TFileStream;
+    tempd:Tdata;
+  begin
+    tempd:=Self.GetAsBMP;
+    filestream:=TFileStream.Create(filename,fmCreate);
+    filestream.Write(tempd[0],Length(tempd));
+    filestream.Free;
+  end;
+
+
+
+function TOniImage.GetMipMappedImage(var faded:Tdata):Boolean;
+  var
+    i:LongWord;
+    x,y:Word;
+    fadelvldata:Tdata;
+    revert:Boolean;
+  begin
+    Result:=False;
+
+//    if not (DT_Decoded32 in Self.FDataType) then
+//      Self.DecodeImage;
+    if Self.FStoreType=9 then
+      Self.DecompressImage;
+    if not (DT_OniReverted in Self.FDataType) then begin
+      revert:=True;
+      Self.RevertImage;
+    end else revert:=False;
+
+    x:=Self.FWidth;
+    y:=Self.FHeight;
+    SetLength(faded,x*y*Self.FDepth div 8);
+    SetLength(fadelvldata,x*y*Self.FDepth div 8);
+    for i:=0 to Length(faded)-1 do begin
+      faded[i]:=Self.FData[i];
+      fadelvldata[i]:=Self.FData[i];
+    end;
+    repeat
+      fadelvldata:=Self.ResizeImage(x,y,fadelvldata);
+      x:=x div 2;
+      y:=y div 2;
+      SetLength(faded,Length(faded)+x*y*Self.FDepth div 8);
+      for i:=0 to Length(fadelvldata)-1 do
+        faded[Length(faded)-x*y*Self.FDepth div 8+i]:=fadelvldata[i];
+    until (x=1) or (y=1) or ((x mod 2)=1) or ((y mod 2)=1);
+    if (x>1) and (y>1) then Exit;
+    Result:=True;
+
+    if revert then
+      Self.RevertImage;
+  end;
+
+
+end.
Index: /oup/current/Unit7_txmpreplace.dfm
===================================================================
--- /oup/current/Unit7_txmpreplace.dfm	(revision 10)
+++ /oup/current/Unit7_txmpreplace.dfm	(revision 10)
@@ -0,0 +1,178 @@
+object Form7: TForm7
+  Left = 0
+  Top = 0
+  BorderStyle = bsSingle
+  Caption = 'TXMP Replacer'
+  ClientHeight = 428
+  ClientWidth = 394
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIChild
+  OldCreateOrder = False
+  Visible = True
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCreate = FormCreate
+  PixelsPerInch = 96
+  TextHeight = 13
+  object panel_12: TPanel
+    Left = 0
+    Top = 0
+    Width = 394
+    Height = 349
+    Align = alClient
+    BevelOuter = bvNone
+    TabOrder = 0
+    object Splitter1: TSplitter
+      Left = 200
+      Top = 0
+      Width = 8
+      Height = 349
+      AutoSnap = False
+      Beveled = True
+      MinSize = 150
+    end
+    object group_txmpselect: TGroupBox
+      Left = 0
+      Top = 0
+      Width = 200
+      Height = 349
+      Align = alLeft
+      Caption = '1. Select TXMP to replace'
+      TabOrder = 0
+      object splitter_txmp: TSplitter
+        Left = 2
+        Top = 190
+        Width = 196
+        Height = 8
+        Cursor = crVSplit
+        Align = alTop
+        AutoSnap = False
+        Beveled = True
+        MinSize = 60
+      end
+      object image_txmppreview: TImage
+        Left = 2
+        Top = 198
+        Width = 196
+        Height = 119
+        Align = alClient
+      end
+      object list_txmp: TListBox
+        Left = 2
+        Top = 15
+        Width = 196
+        Height = 175
+        Align = alTop
+        ItemHeight = 13
+        TabOrder = 0
+        OnClick = list_txmpClick
+      end
+      object panel_txmppreview: TPanel
+        Left = 2
+        Top = 317
+        Width = 196
+        Height = 30
+        Align = alBottom
+        BevelOuter = bvNone
+        TabOrder = 1
+        object btn_save: TButton
+          Left = 2
+          Top = 2
+          Width = 111
+          Height = 25
+          Caption = 'Save TXMP-Picture'
+          TabOrder = 0
+          OnClick = btn_saveClick
+        end
+      end
+    end
+    object group_bmpselect: TGroupBox
+      Left = 208
+      Top = 0
+      Width = 186
+      Height = 349
+      Align = alClient
+      Caption = '2. Open BMP to replace with'
+      Enabled = False
+      TabOrder = 1
+      object image_bmppreview: TImage
+        Left = 2
+        Top = 45
+        Width = 182
+        Height = 302
+        Align = alClient
+      end
+      object panel_load: TPanel
+        Left = 2
+        Top = 15
+        Width = 182
+        Height = 30
+        Align = alTop
+        BevelOuter = bvNone
+        TabOrder = 0
+        object btn_load: TButton
+          Left = 2
+          Top = 2
+          Width = 121
+          Height = 25
+          Caption = 'Load BMP ...'
+          TabOrder = 0
+          OnClick = btn_loadClick
+        end
+      end
+    end
+  end
+  object group_options: TGroupBox
+    Left = 0
+    Top = 349
+    Width = 394
+    Height = 79
+    Align = alBottom
+    Caption = '3. Options && Replace'
+    Enabled = False
+    TabOrder = 1
+    object btn_replace: TButton
+      Left = 4
+      Top = 50
+      Width = 157
+      Height = 25
+      Caption = 'Replace'
+      TabOrder = 0
+      OnClick = btn_replaceClick
+    end
+    object check_transparency: TCheckBox
+      Left = 8
+      Top = 16
+      Width = 105
+      Height = 17
+      Caption = 'Transparency'
+      TabOrder = 1
+    end
+    object check_fading: TCheckBox
+      Left = 8
+      Top = 32
+      Width = 105
+      Height = 17
+      Caption = 'MIP Mapping'
+      TabOrder = 2
+    end
+  end
+  object opend: TOpenDialog
+    Filter = '24bit Bitmap (*.bmp)|*.bmp'
+    Options = [ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 352
+    Top = 16
+  end
+  object saved: TSaveDialog
+    DefaultExt = 'bmp'
+    Filter = 'Windows Bitmap (*.bmp)|*.bmp'
+    Options = [ofOverwritePrompt, ofHideReadOnly, ofPathMustExist, ofEnableSizing]
+    Left = 104
+    Top = 320
+  end
+end
Index: /oup/current/Unit7_txmpreplace.pas
===================================================================
--- /oup/current/Unit7_txmpreplace.pas	(revision 10)
+++ /oup/current/Unit7_txmpreplace.pas	(revision 10)
@@ -0,0 +1,194 @@
+UNIT Unit7_txmpreplace;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, ExtCtrls, StdCtrls, StrUtils, Unit2_functions, Unit3_data, Unit6_imgfuncs;
+
+TYPE
+  TForm7 = Class(TForm)
+    panel_12: TPanel;
+    group_txmpselect: TGroupBox;
+    splitter_txmp: TSplitter;
+    list_txmp: TListBox;
+    Splitter1: TSplitter;
+    group_bmpselect: TGroupBox;
+    panel_load: TPanel;
+    btn_load: TButton;
+    image_bmppreview: TImage;
+    opend: TOpenDialog;
+    group_options: TGroupBox;
+    btn_replace: TButton;
+    check_transparency: TCheckBox;
+    check_fading: TCheckBox;
+    panel_txmppreview: TPanel;
+    btn_save: TButton;
+    image_txmppreview: TImage;
+    saved: TSaveDialog;
+    procedure FormCreate(Sender: TObject);
+    PROCEDURE btn_saveClick(Sender: TObject);
+    PROCEDURE FormClose(Sender: TObject; var Action: TCloseAction);
+    PROCEDURE btn_replaceClick(Sender: TObject);
+    PROCEDURE btn_loadClick(Sender: TObject);
+    PROCEDURE list_txmpClick(Sender: TObject);
+    PROCEDURE Recreatelist;
+  PRIVATE
+    OniImage_Old:TOniImage;
+    OniImage_New:TOniImage;
+  PUBLIC
+  END;
+
+VAR
+  Form7: TForm7;
+
+IMPLEMENTATION
+USES Unit1_main, Unit15_Classes;
+{$R *.dfm}
+
+PROCEDURE TForm7.Recreatelist;
+  VAR
+    files:TStringArray;
+    i:LongWord;
+  BEGIN
+    list_txmp.Items.Clear;
+    files:=OniDataConnection.GetFilesList('TXMP','',True);
+    IF Length(files)>0 THEN
+      FOR i:=0 TO High(files) DO
+        list_txmp.Items.Add(files[i]);
+    group_bmpselect.Enabled:=False;
+    check_transparency.Checked:=False;
+    check_fading.Checked:=False;
+  END;
+
+  
+PROCEDURE TForm7.list_txmpClick(Sender: TObject);
+  VAR
+    id:LongWord;
+    data:Tdata;
+    mem:TMemoryStream;
+    fadingbyte,depthbyte,storebyte:Byte;
+  BEGIN
+    id:=OniDataConnection.ExtractFileID(list_txmp.Items.Strings[list_txmp.ItemIndex]);
+    OniDataConnection.LoadDatFilePart(id,$88,SizeOf(fadingbyte),@fadingbyte);
+    OniDataConnection.LoadDatFilePart(id,$89,SizeOf(depthbyte),@depthbyte);
+    OniDataConnection.LoadDatFilePart(id,$90,SizeOf(storebyte),@storebyte);
+    check_fading.Checked:=(fadingbyte AND $01)>0;
+    check_transparency.Checked:=(depthbyte AND $04)>0;
+
+    OniImage_Old.LoadFromTXMP(id);
+    data:=OniImage_Old.GetAsBMP;
+    mem:=TMemoryStream.Create;
+    mem.Write(data[0],Length(data));
+    mem.Seek(0,soFromBeginning);
+    image_txmppreview.Picture.Bitmap.LoadFromStream(mem);
+    mem.Free;
+
+    group_bmpselect.Enabled:=True;
+  END;
+
+PROCEDURE TForm7.btn_loadClick(Sender: TObject);
+  VAR
+    mem:TMemoryStream;
+    tempd:Tdata;
+  BEGIN
+    IF opend.Execute THEN BEGIN
+      OniImage_New.LoadFromBMP(opend.FileName);
+      tempd:=OniImage_New.GetAsBMP;
+      mem:=TMemoryStream.Create;
+      mem.Write(tempd[0],Length(tempd));
+      mem.Seek(0,soFromBeginning);
+      image_bmppreview.Picture.Bitmap.LoadFromStream(mem);
+      mem.Free;
+      group_options.Enabled:=True;
+    END;
+  END;
+
+PROCEDURE TForm7.btn_replaceClick(Sender: TObject);
+  VAR
+    id:LongWord;
+
+    oldsize,newsize:LongWord;
+    old_rawaddr,new_rawaddr:LongWord;
+    oldfading:Byte;
+    tempd:Tdata;
+
+    datbyte:Word;
+  BEGIN
+    IF list_txmp.ItemIndex>=0 THEN BEGIN
+      id:=OniDataConnection.ExtractFileID(list_txmp.Items.Strings[list_txmp.ItemIndex]);
+      OniDataConnection.LoadDatFilePart(id,$88,1,@oldfading);
+      if OniDataConnection.OSisMac then
+        OniDataConnection.UpdateDatFilePart(id,$A0,4,@old_rawaddr)
+      else
+        OniDataConnection.LoadDatFilePart(id,$9C,4,@old_rawaddr);
+
+      IF (OniImage_Old.Width<>OniImage_New.Width) OR (OniImage_Old.Height<>OniImage_New.Height) THEN BEGIN
+        IF MessageBox(Self.Handle,
+                    PChar('Current image and new image have different size'+CrLf+
+                            '(Current: '+IntToStr(OniImage_Old.Width)+'x'+IntToStr(OniImage_Old.Height)+
+                            ' - New: '+IntToStr(OniImage_New.Width)+'x'+IntToStr(OniImage_New.Height)+')'+CrLf+
+                            'Replace anyways?'),
+                    PChar(list_txmp.Items.Strings[list_txmp.ItemIndex]),
+                    MB_YESNO)=IDNO THEN Exit;
+      END;
+
+      oldsize:=OniImage_Old.GetImageDataSize((oldfading and $01)>0);
+
+      IF check_fading.Checked THEN
+        IF NOT OniImage_New.GetMipMappedImage(tempd) THEN
+          IF MessageBox(Self.Handle, PChar('Can not create a MipMapped-image (probably because of a wrong dimension).'+#13+#10+'Do you want to continue without MipMapping?'), PChar('Warning'), MB_YESNO)=ID_YES THEN
+            check_fading.Checked:=False
+          ELSE
+            Exit;
+
+      IF NOT check_fading.Checked THEN
+        tempd:=OniImage_New.GetAsData;
+
+      newsize:=OniImage_New.GetImageDataSize(check_fading.Checked);
+      ShowMessage(IntToStr(newsize));
+
+      IF (newsize>oldsize) AND (OniDataConnection.Backend=ODB_Dat) THEN
+        new_rawaddr:=OniDataConnection.AppendRawFile(OniDataConnection.OSisMac,Length(tempd),tempd)
+      ELSE BEGIN
+        new_rawaddr:=old_rawaddr;
+        OniDataConnection.UpdateRawFile(id,$9C,Length(tempd),tempd);
+      END;
+
+      datbyte:=$00;
+      IF check_fading.Checked THEN datbyte:=datbyte OR $01;
+      OniDataConnection.UpdateDatFilePart(id,$88,1,@datbyte);
+      datbyte:=$10;
+      IF check_transparency.Checked THEN datbyte:=datbyte OR $04;
+      OniDataConnection.UpdateDatFilePart(id,$89,1,@datbyte);
+      OniDataConnection.UpdateDatFilePart(id,$8C,2,@OniImage_New.Width);
+      OniDataConnection.UpdateDatFilePart(id,$8E,2,@OniImage_New.Height);
+      datbyte:=$08;
+      OniDataConnection.UpdateDatFilePart(id,$90,1,@datbyte);
+      if OniDataConnection.OSisMac then
+        OniDataConnection.UpdateDatFilePart(id,$A0,4,@new_rawaddr)
+      else
+        OniDataConnection.UpdateDatFilePart(id,$9C,4,@new_rawaddr);
+
+      ShowMessage('TXMP-image replaced');
+    END;
+  END;
+
+PROCEDURE TForm7.FormClose(Sender: TObject; var Action: TCloseAction);
+  BEGIN
+    OniImage_Old.Free;
+    OniImage_New.Free;
+    Action:=caFree;
+  END;
+
+PROCEDURE TForm7.FormCreate(Sender: TObject);
+  BEGIN
+    OniImage_Old:=TOniImage.Create;
+    OniImage_New:=TOniImage.Create;
+  END;
+
+PROCEDURE TForm7.btn_saveClick(Sender: TObject);
+  BEGIN
+    IF saved.Execute THEN
+      OniImage_Old.WriteToBMP(saved.FileName);
+  END;
+
+END.
Index: /oup/current/Unit8_binedit.dfm
===================================================================
--- /oup/current/Unit8_binedit.dfm	(revision 10)
+++ /oup/current/Unit8_binedit.dfm	(revision 10)
@@ -0,0 +1,384 @@
+object Form8: TForm8
+  Left = 0
+  Top = 0
+  BorderIcons = [biSystemMenu, biMaximize]
+  Caption = 'Binary .dat-Editor'
+  ClientHeight = 555
+  ClientWidth = 642
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  FormStyle = fsMDIChild
+  KeyPreview = True
+  OldCreateOrder = False
+  Visible = True
+  WindowState = wsMaximized
+  OnClose = FormClose
+  OnCloseQuery = FormCloseQuery
+  OnCreate = FormCreate
+  OnKeyUp = FormKeyUp
+  OnResize = FormResize
+  PixelsPerInch = 96
+  TextHeight = 13
+  object Splitter1: TSplitter
+    Left = 150
+    Top = 0
+    Width = 9
+    Height = 555
+    AutoSnap = False
+    Beveled = True
+    MinSize = 150
+    ExplicitHeight = 423
+  end
+  object panel_data: TPanel
+    Left = 159
+    Top = 0
+    Width = 483
+    Height = 555
+    Align = alClient
+    BevelOuter = bvNone
+    TabOrder = 0
+    object Splitter2: TSplitter
+      Left = 0
+      Top = 209
+      Width = 483
+      Height = 9
+      Cursor = crVSplit
+      Align = alTop
+      AutoSnap = False
+      Beveled = True
+      MinSize = 40
+    end
+    object Splitter3: TSplitter
+      Left = 0
+      Top = 450
+      Width = 483
+      Height = 8
+      Cursor = crVSplit
+      Align = alBottom
+      AutoSnap = False
+      Beveled = True
+      MinSize = 40
+      ExplicitTop = 375
+    end
+    object hex: TMPHexEditor
+      Left = 0
+      Top = 0
+      Width = 483
+      Height = 209
+      Cursor = crIBeam
+      Align = alTop
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -16
+      Font.Name = 'Courier'
+      Font.Style = []
+      OnKeyUp = hexKeyUp
+      ParentFont = False
+      TabOrder = 0
+      BytesPerRow = 16
+      Translation = tkASCII
+      OffsetFormat = '6!10:0x|'
+      Colors.Background = clWindow
+      Colors.ChangedBackground = clWindow
+      Colors.ChangedText = clRed
+      Colors.CursorFrame = clNavy
+      Colors.Offset = clBlack
+      Colors.OddColumn = clBlue
+      Colors.EvenColumn = clNavy
+      Colors.CurrentOffsetBackground = clBtnShadow
+      Colors.OffsetBackGround = clBtnFace
+      Colors.CurrentOffset = clBtnHighlight
+      Colors.Grid = clBtnFace
+      Colors.NonFocusCursorFrame = clAqua
+      Colors.ActiveFieldBackground = clWindow
+      FocusFrame = True
+      NoSizeChange = True
+      AllowInsertMode = False
+      DrawGridLines = False
+      Version = 'May 23, 2005; '#169' markus stephany, vcl[at]mirkes[dot]de'
+      OnChange = hexChange
+      ShowPositionIfNotFocused = True
+      OnSelectionChanged = hexSelectionChanged
+    end
+    object value_viewer: TWrapGrid
+      Left = 0
+      Top = 218
+      Width = 483
+      Height = 232
+      Align = alClient
+      ColCount = 1
+      DefaultColWidth = 80
+      DefaultRowHeight = 18
+      FixedCols = 0
+      RowCount = 8
+      FixedRows = 0
+      Options = [goFixedVertLine, goFixedHorzLine, goVertLine, goHorzLine, goColSizing]
+      PopupMenu = value_viewer_context
+      TabOrder = 1
+      OnDblClick = value_viewerDblClick
+      OnMouseDown = value_viewerMouseDown
+    end
+    object VST: TVirtualStringTree
+      Left = 0
+      Top = 458
+      Width = 483
+      Height = 97
+      Align = alBottom
+      AnimationDuration = 0
+      AutoExpandDelay = 300
+      BiDiMode = bdLeftToRight
+      Colors.UnfocusedSelectionColor = clGradientActiveCaption
+      Colors.UnfocusedSelectionBorderColor = clGradientActiveCaption
+      Ctl3D = True
+      DragOperations = []
+      DrawSelectionMode = smBlendedRectangle
+      EditDelay = 200
+      Font.Charset = DEFAULT_CHARSET
+      Font.Color = clWindowText
+      Font.Height = -11
+      Font.Name = 'Tahoma'
+      Font.Style = []
+      Header.AutoSizeIndex = 0
+      Header.Font.Charset = DEFAULT_CHARSET
+      Header.Font.Color = clWindowText
+      Header.Font.Height = -11
+      Header.Font.Name = 'Tahoma'
+      Header.Font.Style = []
+      Header.Options = [hoColumnResize, hoDblClickResize, hoDrag, hoVisible]
+      Header.PopupMenu = VTHPopup
+      Header.Style = hsFlatButtons
+      HintAnimation = hatNone
+      HintMode = hmTooltip
+      Indent = 14
+      ParentBiDiMode = False
+      ParentCtl3D = False
+      ParentFont = False
+      ParentShowHint = False
+      ShowHint = True
+      TabOrder = 2
+      TreeOptions.MiscOptions = [toAcceptOLEDrop, toCheckSupport, toFullRepaintOnResize, toInitOnSave, toToggleOnDblClick, toWheelPanning]
+      TreeOptions.PaintOptions = [toShowButtons, toShowDropmark, toShowHorzGridLines, toShowRoot, toShowTreeLines, toShowVertGridLines, toUseBlendedImages]
+      TreeOptions.SelectionOptions = [toExtendedFocus, toFullRowSelect, toRightClickSelect]
+      OnDblClick = VSTDblClick
+      OnFocusChanged = VSTFocusChanged
+      OnGetText = VSTGetText
+      OnHeaderDragged = VSTHeaderDragged
+      Columns = <
+        item
+          MaxWidth = 300
+          MinWidth = 100
+          Options = [coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 0
+          Spacing = 20
+          Width = 150
+          WideText = 'Name'
+          WideHint = 'Name of the item.'
+        end
+        item
+          MaxWidth = 110
+          MinWidth = 80
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 1
+          Spacing = 20
+          Width = 85
+          WideText = 'Offset'
+          WideHint = 'Offset of the data-item.'
+        end
+        item
+          MaxWidth = 110
+          MinWidth = 75
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 2
+          Width = 75
+          WideText = 'Type'
+          WideHint = 'Data type of the item.'
+        end
+        item
+          MaxWidth = 250
+          MinWidth = 80
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 3
+          Width = 100
+          WideText = 'Value'
+          WideHint = 'Value of the item.'
+        end
+        item
+          MaxWidth = 400
+          MinWidth = 80
+          Options = [coDraggable, coEnabled, coParentBidiMode, coParentColor, coResizable, coShowDropMark, coVisible]
+          Position = 4
+          Width = 400
+          WideText = 'Description'
+        end>
+      WideDefaultText = ''
+    end
+  end
+  object panel_files: TPanel
+    Left = 0
+    Top = 0
+    Width = 150
+    Height = 555
+    Align = alLeft
+    BevelOuter = bvNone
+    TabOrder = 1
+    object Bevel1: TBevel
+      Left = 0
+      Top = 491
+      Width = 150
+      Height = 6
+      Align = alBottom
+      Style = bsRaised
+      ExplicitTop = 359
+    end
+    object list: TListBox
+      Left = 0
+      Top = 0
+      Width = 150
+      Height = 388
+      Align = alClient
+      ItemHeight = 13
+      TabOrder = 0
+      OnClick = listClick
+    end
+    object panel_extension: TPanel
+      Left = 0
+      Top = 388
+      Width = 150
+      Height = 103
+      Align = alBottom
+      BevelOuter = bvNone
+      TabOrder = 1
+      OnResize = panel_extensionResize
+      object lbl_filter: TLabel
+        Left = 2
+        Top = 62
+        Width = 100
+        Height = 17
+        AutoSize = False
+        Caption = 'Filter by &extension:'
+        FocusControl = combo_extension
+      end
+      object combo_extension: TComboBox
+        Left = 2
+        Top = 76
+        Width = 145
+        Height = 21
+        Style = csDropDownList
+        DropDownCount = 12
+        Font.Charset = DEFAULT_CHARSET
+        Font.Color = clWindowText
+        Font.Height = -11
+        Font.Name = 'Tahoma'
+        Font.Style = []
+        ItemHeight = 13
+        ParentFont = False
+        Sorted = True
+        TabOrder = 3
+        OnClick = combo_extensionClick
+      end
+      object check_zerobyte: TCheckBox
+        Left = 2
+        Top = 44
+        Width = 130
+        Height = 13
+        Caption = 'Show &zero-byte files'
+        TabOrder = 2
+        OnClick = check_zerobyteClick
+      end
+      object edit_filtername: TEdit
+        Left = 2
+        Top = 20
+        Width = 145
+        Height = 18
+        AutoSize = False
+        TabOrder = 1
+      end
+      object check_filtername: TCheckBox
+        Left = 2
+        Top = 5
+        Width = 130
+        Height = 15
+        Caption = 'Filter by file&name:'
+        TabOrder = 0
+        OnClick = check_filternameClick
+      end
+    end
+    object panel_imexport: TPanel
+      Left = 0
+      Top = 497
+      Width = 150
+      Height = 58
+      Align = alBottom
+      BevelOuter = bvNone
+      TabOrder = 2
+      OnResize = panel_imexportResize
+      object btn_export: TButton
+        Left = 4
+        Top = 4
+        Width = 142
+        Height = 25
+        Caption = 'Export to file...'
+        TabOrder = 0
+        OnClick = btn_exportClick
+      end
+      object btn_import: TButton
+        Left = 4
+        Top = 32
+        Width = 142
+        Height = 25
+        Caption = 'Import from file...'
+        TabOrder = 1
+        OnClick = btn_importClick
+      end
+    end
+  end
+  object opend: TOpenDialog
+    Options = [ofPathMustExist, ofFileMustExist, ofEnableSizing]
+    Left = 120
+    Top = 392
+  end
+  object saved: TSaveDialog
+    Options = [ofOverwritePrompt, ofPathMustExist, ofEnableSizing]
+    Left = 120
+    Top = 368
+  end
+  object value_viewer_context: TPopupMenu
+    AutoHotkeys = maManual
+    OnPopup = value_viewer_contextPopup
+    Left = 240
+    Top = 248
+    object value_viewer_context_copy: TMenuItem
+      Caption = 'Copy to &clipboard'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasdec: TMenuItem
+      Caption = 'Copy to clipboard (as &dec)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasfloat: TMenuItem
+      Caption = 'Copy to clipboard (as &float)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasbitset: TMenuItem
+      Caption = 'Copy to clipboard (as &bitset)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyasstring: TMenuItem
+      Caption = 'Copy to clipboard (as &string)'
+      OnClick = value_viewer_context_copyClick
+    end
+    object value_viewer_context_copyashex: TMenuItem
+      Caption = 'Copy to clipboard (as &hex)'
+      OnClick = value_viewer_context_copyClick
+    end
+  end
+  object VTHPopup: TVTHeaderPopupMenu
+    OnColumnChange = VTHPopupColumnChange
+    Left = 200
+    Top = 496
+  end
+end
Index: /oup/current/Unit8_binedit.pas
===================================================================
--- /oup/current/Unit8_binedit.pas	(revision 10)
+++ /oup/current/Unit8_binedit.pas	(revision 10)
@@ -0,0 +1,894 @@
+UNIT Unit8_binedit;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, Wrapgrid, StdCtrls, Grids, StrUtils, MPHexEditor, ExtCtrls, Clipbrd,
+  Unit3_data, Unit2_functions, Unit9_data_structures, Unit4_exporters, Unit15_Classes,
+  Menus, Math, VirtualTrees, VTHeaderPopup;
+
+TYPE
+  TForm8 = Class(TForm)
+    Splitter1: TSplitter;
+    panel_data: TPanel;
+    hex: TMPHexEditor;
+    Splitter2: TSplitter;
+    panel_files: TPanel;
+    list: TListBox;
+    panel_extension: TPanel;
+    lbl_filter: TLabel;
+    combo_extension: TComboBox;
+    Bevel1: TBevel;
+    panel_imexport: TPanel;
+    btn_export: TButton;
+    btn_import: TButton;
+    opend: TOpenDialog;
+    saved: TSaveDialog;
+    value_viewer: TWrapGrid;
+    Splitter3: TSplitter;
+    value_viewer_context: TPopupMenu;
+    value_viewer_context_copy: TMenuItem;
+    value_viewer_context_copyashex: TMenuItem;
+    value_viewer_context_copyasdec: TMenuItem;
+    value_viewer_context_copyasfloat: TMenuItem;
+    value_viewer_context_copyasbitset: TMenuItem;
+    value_viewer_context_copyasstring: TMenuItem;
+    check_zerobyte: TCheckBox;
+    edit_filtername: TEdit;
+    check_filtername: TCheckBox;
+    VST: TVirtualStringTree;
+    VTHPopup: TVTHeaderPopupMenu;
+    procedure VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
+      Column: TColumnIndex);
+    procedure VSTDblClick(Sender: TObject);
+    procedure VTHPopupColumnChange(const Sender: TBaseVirtualTree;
+      const Column: TColumnIndex; Visible: Boolean);
+    procedure VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
+      OldPosition: Integer);
+    procedure VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
+      Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
+    procedure hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    PROCEDURE LoadDat(_fileid:LongWord);
+    PROCEDURE LoadFileNames;
+    PROCEDURE check_filternameClick(Sender: TObject);
+    PROCEDURE check_zerobyteClick(Sender: TObject);
+    PROCEDURE combo_extensionClick(Sender: TObject);
+    PROCEDURE panel_extensionResize(Sender: TObject);
+    PROCEDURE listClick(Sender: TObject);
+    PROCEDURE Recreatelist;
+
+    PROCEDURE FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+    PROCEDURE value_viewerDblClick(Sender: TObject);
+    PROCEDURE value_viewer_context_copyClick(Sender: TObject);
+    PROCEDURE value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+    PROCEDURE value_viewer_contextPopup(Sender: TObject);
+    PROCEDURE btn_importClick(Sender: TObject);
+    PROCEDURE btn_exportClick(Sender: TObject);
+    PROCEDURE panel_imexportResize(Sender: TObject);
+    FUNCTION Save:Boolean;
+    PROCEDURE FormClose(Sender: TObject; var Action: TCloseAction);
+    FUNCTION GetValue(datatype:Word; offset:LongWord):String;
+    PROCEDURE WriteStructureInfos; //(structinfoid:Integer);
+    PROCEDURE hexSelectionChanged(Sender: TObject);
+    PROCEDURE hexChange(Sender: TObject);
+    PROCEDURE FormResize(Sender: TObject);
+    PROCEDURE ClearStructViewer;
+    PROCEDURE FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+    PROCEDURE FormCreate(Sender: TObject);
+    PROCEDURE ClearValues;
+    PROCEDURE WriteValues;
+    PROCEDURE SetNewValue(datatype:Word; offset:LongWord; value:String);
+  PRIVATE
+    fileid:LongWord;
+  PUBLIC
+  END;
+
+VAR
+  Form8: TForm8;
+
+IMPLEMENTATION
+{$R *.dfm}
+USES Unit1_main, Unit12_ValueEdit, Unit13_rawedit;
+
+TYPE
+  PNodeData = ^TNodeData;
+  TNodeData = record
+    Caption:String;
+    Offset:LongInt;
+    DataType:Word;
+    Value:String;
+    Description:String;
+  end;
+
+
+function AddVSTEntry(AVST:TCustomVirtualStringTree; ANode:PVirtualNode; ARecord:TNodeData):PVirtualNode;
+  var
+    data:PNodeData;
+  begin
+    Result:=AVST.AddChild(ANode);
+    data:=AVST.GetNodeData(Result);
+    AVST.ValidateNode(Result,False);
+    data^:=ARecord;
+  end;
+
+
+
+PROCEDURE TForm8.LoadDat(_fileid:LongWord);
+  VAR
+    i:LongWord;
+    mem:TMemoryStream;
+    data:Tdata;
+  BEGIN
+    IF hex.Modified THEN BEGIN
+      IF NOT Save THEN BEGIN
+        FOR i:=0 TO list.Count-1 DO BEGIN
+          IF OniDataConnection.ExtractFileID(list.Items.Strings[i])=fileid THEN BEGIN
+            list.ItemIndex:=i;
+            Exit;
+          END;
+        END;
+      END;
+    END;
+    fileid:=_fileid;
+    FOR i:=0 TO list.Count-1 DO
+      IF OniDataConnection.ExtractFileID(list.Items.Strings[i])=fileid THEN BEGIN
+        list.ItemIndex:=i;
+        Break;
+      END;
+    Self.ClearStructViewer;
+    data:=OniDataConnection.LoadDatFile(fileid);
+    IF Length(data)>0 THEN BEGIN
+      mem:=TMemoryStream.Create;
+      mem.Write(data[0],Length(data));
+      mem.Seek(0,soFromBeginning);
+      hex.LoadFromStream(mem);
+      mem.Free;
+      WriteStructureInfos; 
+    END ELSE BEGIN
+      ClearValues;
+      hex.DataSize:=0;
+    END;
+  END;
+
+PROCEDURE TForm8.Recreatelist;
+  VAR
+    i:LongWord;
+    exts:TStringArray;
+  BEGIN
+    combo_extension.Items.Clear;
+    combo_extension.Items.Add('_All files_ ('+IntToStr(OniDataConnection.GetFilesCount)+')');
+    exts:=OniDataConnection.GetExtensionsList;
+    FOR i:=0 TO High(exts) DO
+      combo_extension.Items.Add(exts[i]);
+    combo_extension.ItemIndex:=0;
+    combo_extensionClick(Self);
+  END;
+
+PROCEDURE TForm8.LoadFileNames;
+  VAR
+    Extension:String[4];
+    no_zero_bytes:Boolean;
+    pattern:String;
+    files:TStringArray;
+    i:LongWord;
+  BEGIN
+    Extension:=MidStr(combo_extension.Items.Strings[combo_extension.ItemIndex],1,4);
+    no_zero_bytes:=NOT check_zerobyte.Checked;
+    pattern:='';
+    IF check_filtername.Checked THEN pattern:=edit_filtername.Text;
+    IF Extension='_All' THEN Extension:='';
+
+    files:=OniDataConnection.GetFilesList(extension,pattern,no_zero_bytes);
+    list.Items.Clear;
+    IF Length(files)>0 THEN
+      FOR i:=0 TO High(files) DO
+        list.Items.Add(files[i]);
+  END;
+
+PROCEDURE TForm8.panel_extensionResize(Sender: TObject);
+  BEGIN
+    combo_extension.Width:=panel_extension.Width-5;
+    edit_filtername.Width:=panel_extension.Width-5;
+  END;
+
+PROCEDURE TForm8.combo_extensionClick(Sender: TObject);
+  BEGIN
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm8.check_zerobyteClick(Sender: TObject);
+  BEGIN
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm8.check_filternameClick(Sender: TObject);
+  BEGIN
+    edit_filtername.Enabled:=NOT check_filtername.Checked;
+    LoadFileNames;
+  END;
+
+PROCEDURE TForm8.listClick(Sender: TObject);
+  BEGIN
+    LoadDat(OniDataConnection.ExtractFileID(list.Items.Strings[list.ItemIndex]));
+  END;
+
+
+
+
+FUNCTION IntToBin(value:Byte):String;
+  VAR i:Byte;
+  BEGIN
+    Result:='';
+    FOR i:=7 DOWNTO 0 DO BEGIN
+      Result:=Result+IntToStr((value SHR i) AND $01);
+    END;
+  END;
+
+FUNCTION TForm8.GetValue(datatype:Word; offset:LongWord):String;
+  VAR
+    data:Tdata;
+    i:Word;
+  BEGIN
+    CASE datatype OF
+      1: Result:=IntToStr(hex.data[offset]);
+      2: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256);
+      3: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256);
+      4: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256+hex.data[offset+3]*256*256*256);
+      5: Result:='0x'+IntToHex(hex.data[offset],2);
+      6: Result:='0x'+IntToHex(hex.data[offset]+hex.data[offset+1]*256,4);
+      7: Result:='0x'+IntToHex(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256,6);
+      8: Result:='0x'+IntToHex(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256+hex.data[offset+3]*256*256*256,8);
+      9: BEGIN
+          SetLength(data,4);
+          data[0]:=hex.data[offset];
+          data[1]:=hex.data[offset+1];
+          data[2]:=hex.data[offset+2];
+          data[3]:=hex.data[offset+3];
+          Result:=FloatToStr(Decode_Float(data));
+        END;
+      10: Result:=IntToBin(hex.data[offset]);
+      11: Result:='0x'+IntToHex(OniDataConnection.GetRawInfo(fileid,offset).raw_addr,8);
+      12: Result:=FormatNumber(hex.data[offset+1]+hex.data[offset+2]*256+hex.data[offset+3]*256*256,5,'0');
+      13: Result:=IntToStr(hex.data[offset]);
+      14: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256);
+      15: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256);
+      16: Result:=IntToStr(hex.data[offset]+hex.data[offset+1]*256+hex.data[offset+2]*256*256+hex.data[offset+3]*256*256*256);
+      17: Result:=IntToStr((hex.data[offset+3]) DIV 2);
+      100..300: BEGIN
+          Result:='';
+          FOR i:=1 TO datatype-100 DO BEGIN
+            IF hex.Data[offset+i-1]>=32 THEN
+              Result:=Result+Chr(hex.Data[offset+i-1])
+            ELSE
+              Break;
+          END;
+        END;
+      1000..9999: BEGIN
+          Result:='';
+          FOR i:=1 TO datatype-1000 DO BEGIN
+            IF hex.Data[offset+i-1]>=32 THEN
+              Result:=Result+Chr(hex.Data[offset+i-1])
+            ELSE
+              Result:=Result+'.';
+          END;
+        END;
+      10000..65535: BEGIN
+          Result:='';
+          FOR i:=1 TO datatype-10000 DO BEGIN
+            IF hex.Data[offset+i-1]>=32 THEN
+              Result:=Result+Chr(hex.Data[offset+i-1])
+            ELSE
+              Result:=Result+'.';
+          END;
+        END;
+    END;
+  END;
+
+PROCEDURE TForm8.WriteStructureInfos;
+  VAR
+    i,j:LongWord;
+    pdata: PNodeData;
+    data: TNodeData;
+    node: PVirtualNode;
+    structs: TStructDef;
+  BEGIN
+    VST.BeginUpdate;
+    IF VST.RootNodeCount=0 THEN BEGIN
+      structs:=LoadStructureDefinition(fileid);
+      IF structs.data THEN BEGIN
+        IF Length(structs.Global)>0 THEN BEGIN
+          FOR i:=0 TO High(structs.Global) DO BEGIN
+            data.Caption:=structs.Global[i].name;
+            data.Offset:=structs.Global[i].offset;
+            data.DataType:=structs.Global[i].datatype;
+            data.Value:=GetValue(structs.Global[i].datatype, structs.Global[i].offset);
+            data.Description:=structs.Global[i].description;
+            AddVSTEntry(VST, nil, data);
+          END;
+        END;
+        IF Length(structs.Subs)>0 THEN BEGIN
+          FOR i:=0 TO High(structs.Subs) DO BEGIN
+            WITH structs.Subs[i] DO BEGIN
+              IF Length(Entries)>0 THEN BEGIN
+                IF Pos('#',SubName)>0 THEN BEGIN
+                  data.Offset:=HexToLong(MidStr(SubName, Pos('#',SubName)+1, 8));
+                  data.Value:=MidStr(SubName, PosEx('#',SubName,Pos('#',SubName)+1)+1, 8);
+                  data.Caption:=MidStr(SubName, 1, Pos('#',SubName)-1);
+                  data.Description:=SubDesc;
+                END ELSE BEGIN
+                  data.Caption:=SubName;
+                  data.Description:=SubDesc;
+                  data.Offset:=0;
+                  data.Value:='';
+                END;
+                data.DataType:=0;
+                node:=AddVSTEntry(VST, nil, data);
+                data.Description:='';
+                FOR j:=0 TO High(Entries) DO BEGIN
+                  data.Caption:=Entries[j].name;
+                  data.Offset:=Entries[j].offset;
+                  data.DataType:=Entries[j].datatype;
+                  data.Value:=GetValue(Entries[j].datatype, Entries[j].offset);
+                  data.Description:=Entries[j].description;
+                  AddVSTEntry(VST, node, data);
+                END;
+              END;
+            END;
+          END;
+        END;
+      END;
+      IF VST.RootNodeCount>0 THEN
+        VST.FocusedNode:=VST.GetFirst;
+    END ELSE BEGIN
+      Node:=VST.GetFirst;
+      WHILE Assigned(Node) DO BEGIN
+        pdata:=VST.GetNodeData(Node);
+        IF pdata.DataType>0 THEN
+          pdata.Value:=GetValue(pdata.Datatype, pdata.Offset);
+        Node:=VST.GetNext(Node);
+      END;
+    END;
+    VST.EndUpdate;
+  END;
+
+PROCEDURE TForm8.ClearValues;
+  VAR
+    i:Byte;
+  BEGIN
+    FOR i:=1 TO value_viewer.RowCount-1 DO BEGIN
+      value_viewer.Cells[1,i]:='';
+    END;
+  END;
+
+PROCEDURE TForm8.WriteValues;
+  VAR
+    i,j:Byte;
+    data:Tdata;
+    str:String;
+    value:LongWord;
+  BEGIN
+    FOR i:=1 TO value_viewer.RowCount-1 DO BEGIN
+      IF value_viewer.Cells[0,i]='1 byte, unsigned' THEN BEGIN
+        IF ((hex.SelCount=1) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+1)>hex.DataSize) THEN BEGIN
+          value:=hex.Data[hex.SelStart];
+          value_viewer.Cells[1,i]:=IntToStr( value )+' / 0x'+IntToHex( value , 2 );
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='2 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=2) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+2)>hex.DataSize) THEN BEGIN
+          value:=hex.Data[hex.SelStart] + hex.Data[hex.SelStart+1]*256;
+          value_viewer.Cells[1,i]:=IntToStr( value )+' / 0x'+IntToHex( value , 4 );
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='4 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=4) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+4)>hex.DataSize) THEN BEGIN
+          value:=hex.Data[hex.SelStart]+hex.Data[hex.SelStart+1]*256+hex.Data[hex.SelStart+2]*256*256+hex.Data[hex.SelStart+3]*256*256*256;
+          value_viewer.Cells[1,i]:=IntToStr( value )+' / 0x'+IntToHex( value , 8 );
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='Bitset' THEN BEGIN
+        IF (hex.SelCount<=8) THEN BEGIN
+          IF hex.SelCount=0 THEN BEGIN
+            SetLength(data,1);
+            data[0]:=hex.Data[hex.SelStart];
+          END ELSE BEGIN
+            SetLength(data,hex.SelCount);
+            FOR j:=0 TO hex.SelCount-1 DO
+              data[j]:=hex.Data[hex.SelStart+j];
+          END;
+          value_viewer.Cells[1,i]:=DataToBin(data);
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='Float' THEN BEGIN
+        IF ((hex.SelCount=4) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+4)>hex.DataSize) THEN BEGIN
+          SetLength(data,4);
+          FOR j:=0 TO 3 DO
+            data[j]:=hex.Data[hex.SelStart+j];
+          value_viewer.Cells[1,i]:=FloatToStr(Decode_Float(data));
+        END ELSE
+          value_viewer.Cells[1,i]:='';
+      END;
+      IF value_viewer.Cells[0,i]='Selected length' THEN BEGIN
+        value_viewer.Cells[1,i]:=IntToStr(hex.SelCount)+' bytes';
+      END;
+      IF value_viewer.Cells[0,i]='String' THEN BEGIN
+        j:=0;
+        str:='';
+        IF hex.SelCount=0 THEN BEGIN
+          WHILE (hex.Data[hex.SelStart+j]>0) AND ((hex.SelStart+j)<hex.DataSize) DO BEGIN
+            IF hex.Data[hex.selstart+j]>=32 THEN
+              str:=str+Char(hex.Data[hex.SelStart+j])
+            ELSE
+              str:=str+'.';
+            Inc(j);
+          END;
+        END ELSE BEGIN
+          FOR j:=0 TO hex.SelCount-1 DO
+            IF hex.Data[hex.selstart+j]>=32 THEN
+              str:=str+Char(hex.Data[hex.SelStart+j])
+            ELSE
+              IF hex.Data[hex.selstart+j]>0 THEN
+                str:=str+'.'
+              ELSE
+                Break;
+        END;
+        value_viewer.Cells[1,i]:=str;
+      END;
+    END;
+  END;
+
+PROCEDURE TForm8.FormCreate(Sender: TObject);
+  BEGIN
+    Self.Caption:='';
+    fileid:=0;
+    VST.NodeDataSize:=SizeOf(TNodeData);
+    value_viewer.ColCount:=2;
+    value_viewer.RowCount:=8;
+    value_viewer.FixedRows:=1;
+    value_viewer.Cells[0,0]:='Type';
+    value_viewer.Cells[1,0]:='Value';
+    value_viewer.Cells[0,1]:='1 byte, unsigned';
+    value_viewer.Cells[0,2]:='2 bytes, unsigned';
+    value_viewer.Cells[0,3]:='4 bytes, unsigned';
+    value_viewer.Cells[0,4]:='Bitset';
+    value_viewer.Cells[0,5]:='Float';
+    value_viewer.Cells[0,6]:='String';
+    value_viewer.Cells[0,7]:='Selected length';
+    value_viewer.ColWidths[0]:=100;
+    value_viewer.ColWidths[1]:=value_viewer.Width-150;
+    hex.Height:=panel_data.Height-215;
+//
+    value_viewer.Font.Charset:=AppSettings.CharSet;
+    VST.Font.Charset:=AppSettings.CharSet;
+    hex.Translation:=tkAsIs;
+    hex.Font.Charset:=AppSettings.CharSet;
+//
+  END;
+
+FUNCTION TForm8.Save:Boolean;
+  VAR
+    mem:TMemoryStream;
+    data:Tdata;
+    i:LongWord;
+  BEGIN
+    CASE MessageBox(Self.Handle,PChar('Save changes to file '+OniDataConnection.GetFileInfo(fileid).FileName+'?'),PChar('Data changed...'),MB_YESNOCANCEL) OF
+      IDYES: BEGIN
+          mem:=TMemoryStream.Create;
+          hex.SaveToStream(mem);
+          mem.Seek(0,soFromBeginning);
+          SetLength(data,mem.Size);
+          mem.Read(data[0],mem.Size);
+          mem.Free;
+          OniDataConnection.UpdateDatFile(fileid,data);
+          hex.Modified:=False;
+          FOR i:=0 TO hex.Datasize-1 DO hex.ByteChanged[i]:=False;
+          Result:=True;
+        END;
+      IDNO: Result:=True;
+      IDCANCEL: BEGIN
+          Result:=False;
+        END;
+    END;
+  END;
+
+PROCEDURE TForm8.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
+  BEGIN
+    IF hex.Modified THEN BEGIN
+      IF NOT Save THEN CanClose:=False;
+    END;
+  END;
+
+PROCEDURE TForm8.ClearStructViewer;
+  BEGIN
+    VST.Clear;
+  END;
+
+PROCEDURE TForm8.FormResize(Sender: TObject);
+  BEGIN
+    IF Self.Width>=650 THEN BEGIN
+    END ELSE Self.Width:=650;
+    IF Self.Height>=450 THEN BEGIN
+    END ELSE Self.Height:=450;
+  END;
+
+PROCEDURE TForm8.hexChange(Sender: TObject);
+  BEGIN
+    ClearValues;
+    IF hex.DataSize>0 THEN BEGIN
+      WriteStructureInfos;
+      WriteValues;
+    END;
+  END;
+
+PROCEDURE TForm8.hexKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+  VAR
+    temps: String;
+  BEGIN
+    IF (Shift=[ssCtrl]) AND (Key=Ord('C')) THEN BEGIN
+      IF hex.SelCount>0 THEN BEGIN
+        IF hex.InCharField THEN
+          Clipboard.AsText:=hex.SelectionAsText
+        ELSE
+          Clipboard.AsText:=hex.SelectionAsHex;
+      END;
+    END;
+    IF (Shift=[ssCtrl]) AND (Key=Ord('V')) THEN BEGIN
+{      temps:=Clipboard.AsText;
+      IF hex.SelStart+Length(temps)>hex.DataSize THEN
+        SetLength(temps, hex.DataSize-hex.SelStart);
+      hex.Sel
+      hex.SelCount:=Length(temps);
+      hex.ReplaceSelection(temps,Length(temps));
+}    END;
+  END;
+
+PROCEDURE TForm8.hexSelectionChanged(Sender: TObject);
+  VAR
+    selstart:Integer;
+    node:PVirtualNode;
+    pdata:PNodeData;
+  BEGIN
+    IF hex.DataSize>0 THEN BEGIN
+      WriteValues;
+      selstart:=hex.SelStart;
+      IF VST.RootNodeCount>0 THEN BEGIN
+        Node:=VST.GetFirst;
+        WHILE Assigned(Node) DO BEGIN
+          pdata:=VST.GetNodeData(Node);
+          IF pdata.DataType>0 THEN BEGIN
+            IF ((selstart-pdata.Offset)<GetTypeDataLength(pdata.DataType)) AND ((selstart-pdata.Offset)>=0) THEN BEGIN
+              VST.FocusedNode:=Node;
+              VST.Selected[Node]:=True;
+              Break;
+            END;
+          END;
+          Node:=VST.GetNext(Node);
+        END;
+      END;
+    END;
+  END;
+
+PROCEDURE TForm8.FormClose(Sender: TObject; var Action: TCloseAction);
+  BEGIN
+    Action:=caFree;
+  END;
+
+PROCEDURE TForm8.panel_imexportResize(Sender: TObject);
+  BEGIN
+    btn_import.Width:=panel_imexport.Width-8;
+    btn_export.Width:=panel_imexport.Width-8;
+  END;
+
+PROCEDURE TForm8.btn_exportClick(Sender: TObject);
+  BEGIN
+    saved.Filter:='Files of matching extension (*.'+OniDataConnection.GetFileInfo(fileid).Extension+')|*.'+OniDataConnection.GetFileInfo(fileid).Extension+'|All files|*.*';
+    saved.DefaultExt:=OniDataConnection.GetFileInfo(fileid).Extension;
+    IF saved.Execute THEN BEGIN
+      ExportDatFile(fileid,saved.FileName);
+    END;
+  END;
+
+PROCEDURE TForm8.btn_importClick(Sender: TObject);
+  VAR
+    fs:TFileStream;
+  BEGIN
+    opend.Filter:='Files of matching extension (*.'+OniDataConnection.GetFileInfo(fileid).Extension+')|*.'+OniDataConnection.GetFileInfo(fileid).Extension+'|All files|*.*';
+    IF opend.Execute THEN BEGIN
+      fs:=TFileStream.Create(opend.FileName,fmOpenRead);
+      IF fs.Size<>hex.DataSize THEN BEGIN
+        ShowMessage('Can''t import '+ExtractFilename(opend.FileName)+
+                    ', file has to have same size as file in .dat.'+CrLf+
+                    'Size of file in .dat: '+FormatFileSize(hex.datasize)+CrLf+
+                    'Size of chosen file: '+FormatFileSize(fs.Size));
+      END ELSE BEGIN
+        hex.LoadFromStream(fs);
+        hex.Modified:=True;
+      END;
+      fs.Free;
+    END;
+  END;
+
+PROCEDURE TForm8.value_viewer_contextPopup(Sender: TObject);
+  VAR
+    i:Byte;
+  BEGIN
+    FOR i:=0 TO value_viewer_context.Items.Count-1 DO
+      value_viewer_context.Items.Items[i].Visible:=False;
+    WITH value_viewer DO BEGIN
+      IF (Col=1) AND (Row>0) AND (Length(Cells[Col,Row])>0) THEN BEGIN
+        IF Pos(' byte',Cells[0,Row])=2 THEN BEGIN
+          value_viewer_context.Items.Find('Copy to &clipboard').Visible:=True;
+          value_viewer_context.Items.Find('Copy to clipboard (as &dec)').Visible:=True;
+          value_viewer_context.Items.Find('Copy to clipboard (as &hex)').Visible:=True;
+        END;
+        IF Pos('Float',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to clipboard (as &float)').Visible:=True;
+        IF Pos('Bitset',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to clipboard (as &bitset)').Visible:=True;
+        IF Pos('String',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to clipboard (as &string)').Visible:=True;
+        IF Pos('Selected length',Cells[0,Row])=1 THEN
+          value_viewer_context.Items.Find('Copy to &clipboard').Visible:=True;
+      END;
+    END;
+  END;
+
+PROCEDURE TForm8.value_viewerMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
+  VAR
+    ACol,ARow:Integer;
+  BEGIN
+    IF Button=mbRight THEN BEGIN
+      value_viewer.MouseToCell(x,y,ACol,ARow);
+      IF ARow>0 THEN BEGIN
+        value_viewer.Col:=ACol;
+        value_viewer.Row:=ARow;
+      END;
+    END;
+  END;
+
+PROCEDURE TForm8.value_viewer_context_copyClick(Sender: TObject);
+  VAR
+    name:String;
+    value:LongWord;
+  BEGIN
+    name:=TMenuItem(Sender).Name;
+    IF Pos('asstring',name)>0 THEN BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END ELSE
+    IF Pos('asfloat',name)>0 THEN BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END ELSE
+    IF Pos('asbitset',name)>0 THEN BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END ELSE
+    IF (Pos('ashex',name)>0) OR (Pos('asdec',name)>0) THEN BEGIN
+      IF value_viewer.Cells[0,value_viewer.Row]='1 byte, unsigned' THEN BEGIN
+        IF ((hex.SelCount=1) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+1)>hex.DataSize) THEN
+          value:=hex.Data[hex.SelStart];
+      END;
+      IF value_viewer.Cells[0,value_viewer.Row]='2 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=2) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+2)>hex.DataSize) THEN
+          value:=hex.Data[hex.SelStart] + hex.Data[hex.SelStart+1]*256;
+      END;
+      IF value_viewer.Cells[0,value_viewer.Row]='4 bytes, unsigned' THEN BEGIN
+        IF ((hex.SelCount=4) OR (hex.SelCount=0)) AND NOT ((hex.SelStart+4)>hex.DataSize) THEN
+          value:=hex.Data[hex.SelStart]+hex.Data[hex.SelStart+1]*256+hex.Data[hex.SelStart+2]*256*256+hex.Data[hex.SelStart+3]*256*256*256;
+      END;
+      IF Pos('asdec',name)>0 THEN BEGIN
+        Clipboard.AsText:=IntToStr(value);
+      END ELSE BEGIN
+        IF value_viewer.Cells[0,value_viewer.Row]='1 byte, unsigned' THEN
+          Clipboard.AsText:='0x'+IntToHex(value,2);
+        IF value_viewer.Cells[0,value_viewer.Row]='2 bytes, unsigned' THEN
+          Clipboard.AsText:='0x'+IntToHex(value,4);
+        IF value_viewer.Cells[0,value_viewer.Row]='4 bytes, unsigned' THEN
+          Clipboard.AsText:='0x'+IntToHex(value,8);
+      END;
+    END ELSE BEGIN
+      Clipboard.AsText:=value_viewer.Cells[value_viewer.Col,value_viewer.Row];
+    END;
+  END;
+
+procedure TForm8.VSTDblClick(Sender: TObject);
+  var
+    node:PVirtualNode;
+    nodedata:PNodeData;
+    id:Integer;
+  begin
+    if VST.FocusedColumn=3 then begin
+      node:=VST.FocusedNode;
+      nodedata:=VST.GetNodeData(node);
+
+      if not (nodedata.datatype in [11,12]) and ((nodedata.DataType<100) or (nodedata.DataType>300)) then begin
+        Form12.MakeVarInput(nodedata.Caption,nodedata.offset,nodedata.datatype,nodedata.value,Self);
+      end else begin
+        if nodedata.DataType=11 then begin
+          if OniDataConnection.GetRawInfo(fileid,nodedata.offset).raw_size>0 then begin
+            if Form1.open_child('rawedit') then begin
+              TForm13(Form1.ActiveMDIChild).LoadRaw(OniDataConnection.GetRawInfo(fileid,nodedata.offset));
+            end;
+          end;
+        end;
+        if nodedata.DataType=12 then begin
+          if (StrToInt(nodedata.Value)<OniDataConnection.GetFilesCount) and
+              (StrToInt(nodedata.Value)>0) and
+              (StrToInt(nodedata.Value)<>fileid) then begin
+            if OniDataConnection.GetFileInfo(StrToInt(nodedata.Value)).Size>0 then begin
+              if Form1.open_child('binedit') then begin
+                TForm8(Form1.ActiveMDIChild).LoadDat(StrToInt(nodedata.Value));
+              end;
+            end else begin
+              ShowMessage('Linked filed is a zero-byte-file');
+            end;
+          end;
+        end;
+        if (nodedata.DataType>=100) and (nodedata.DataType<=300) then begin
+          if Form1.open_child('binedit') then begin
+            TForm8(Form1.ActiveMDIChild).edit_filtername.Text:=nodedata.Value;
+            TForm8(Form1.ActiveMDIChild).check_filtername.Checked:=True;
+            TForm8(Form1.ActiveMDIChild).check_filternameClick(Self);
+          end;
+        end;
+      end;
+
+    end;
+  end;
+
+procedure TForm8.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
+  Column: TColumnIndex);
+  var
+    data:PNodeData;
+  begin
+    data:=VST.GetNodeData(node);
+    IF data.DataType>0 THEN BEGIN
+      hex.SelStart:=data.Offset;
+      hex.SelEnd:=data.Offset+GetTypeDataLength(data.DataType)-1;
+    END ELSE BEGIN
+      hex.SelStart:=data.Offset;
+      hex.SelEnd:=data.Offset+HexToLong(data.Value)-1;
+    END;
+  end;
+
+procedure TForm8.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
+  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
+  var
+    data:PNodeData;
+  begin
+    data := Sender.GetNodeData(Node);
+    CellText := '';
+    if TextType = ttNormal then begin
+      case Column of
+        0: CellText := data.Caption;
+        1:
+          if data.DataType>0 then
+            CellText := '0x'+IntToHex(data.Offset,8)
+          else
+            if data.Offset>0 then
+              CellText := '0x'+IntToHex(data.Offset,8);
+        2:
+          if data.DataType>0 then
+            CellText := GetDataType(data.DataType);
+        3:
+          if data.DataType>0 then
+            CellText := data.Value //GetValue(data.DataType, data.Offset)
+          else
+            if Length(data.Value)>0 then
+              CellText := IntToStr(HexToLong(data.Value))+' Bytes';
+        4:
+          CellText := data.Description;
+      end;
+    end;
+  end;
+
+procedure TForm8.VSTHeaderDragged(Sender: TVTHeader; Column: TColumnIndex;
+  OldPosition: Integer);
+  begin
+    if Sender.Columns.Items[column].Position<1 then
+      Sender.Columns.Items[column].Position:=OldPosition;
+  end;
+
+procedure TForm8.VTHPopupColumnChange(const Sender: TBaseVirtualTree;
+  const Column: TColumnIndex; Visible: Boolean);
+  begin
+    if column=0 then
+      TVirtualStringTree(Sender).Header.Columns.Items[column].Options:=TVirtualStringTree(Sender).Header.Columns.Items[column].Options+[coVisible];
+  end;
+
+PROCEDURE TForm8.SetNewValue(datatype:Word; offset:LongWord; value:String);
+  VAR
+    data:Tdata;
+    value_int:LongWord;
+    value_float:Single;
+    i:Word;
+  BEGIN
+    CASE datatype OF
+      1..4: BEGIN
+              value_int:=StrToInt(value);
+              SetLength(data,datatype);
+              FOR i:=0 TO datatype-1 DO BEGIN
+                data[i]:=value_int MOD 256;
+                value_int:=value_int DIV 256;
+              END;
+            END;
+      5..8: BEGIN
+              value_int:=StrToInt('$'+value);
+              SetLength(data,datatype-4);
+              FOR i:=0 TO datatype-5 DO BEGIN
+                data[i]:=value_int MOD 256;
+                value_int:=value_int DIV 256;
+              END;
+            END;
+      9:    BEGIN
+              value_float:=StrToFloat(value);
+              data:=Encode_Float(value_float);
+            END;
+      10:   BEGIN
+              value_int:=BinToInt(value);
+              SetLength(data,1);
+              data[0]:=value_int;
+            END;
+      10000..65535: BEGIN
+              SetLength(data,datatype-10000);
+              FOR i:=1 TO datatype-10000 DO BEGIN
+                IF i<=Length(value) THEN
+                  data[i-1]:=Ord(value[i])
+                ELSE
+                  data[i-1]:=0;
+              END;
+            END;
+    END;
+    FOR i:=0 TO High(data) DO BEGIN
+      IF hex.Data[offset+i]<>data[i] THEN hex.ByteChanged[offset+i]:=True;
+      hex.Data[offset+i]:=data[i];
+    END;
+    hex.Modified:=True;
+    hexChange(Self);
+    hex.Repaint;
+  END;
+
+PROCEDURE TForm8.value_viewerDblClick(Sender: TObject);
+  VAR
+    offset:LongWord;
+    datatype:Word;
+    objectname:String;
+    value:String;
+  BEGIN
+    IF (value_viewer.Col=1) AND (Length(value_viewer.Cells[1,value_viewer.Row])>0) THEN BEGIN
+      offset:=hex.SelStart;
+      IF value_viewer.Cells[0,value_viewer.Row]='1 byte, unsigned' THEN
+        datatype:=1;
+      IF value_viewer.Cells[0,value_viewer.Row]='2 bytes, unsigned' THEN
+        datatype:=2;
+      IF value_viewer.Cells[0,value_viewer.Row]='4 bytes, unsigned' THEN
+        datatype:=4;
+      IF value_viewer.Cells[0,value_viewer.Row]='Bitset' THEN
+        datatype:=10;
+      IF value_viewer.Cells[0,value_viewer.Row]='Float' THEN
+        datatype:=9;
+      IF value_viewer.Cells[0,value_viewer.Row]='Selected length' THEN
+        Exit;
+      IF value_viewer.Cells[0,value_viewer.Row]='String' THEN BEGIN
+        IF hex.SelCount>0 THEN
+          datatype:=10000+hex.SelCount
+        ELSE
+          datatype:=10000+Length(value_viewer.Cells[1,value_viewer.Row]);
+      END;
+      objectname:='';
+      value:=GetValue(datatype,offset);
+      Form12.MakeVarInput(objectname,offset,datatype,value,Self);
+    END;
+  END;
+
+PROCEDURE TForm8.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
+  BEGIN
+    IF (Shift=[ssCtrl]) AND (Key=83) THEN
+      IF hex.Modified THEN
+        IF NOT Save THEN
+          Exit;
+  END;
+
+
+END.
Index: /oup/current/Unit9_data_structures.pas
===================================================================
--- /oup/current/Unit9_data_structures.pas	(revision 10)
+++ /oup/current/Unit9_data_structures.pas	(revision 10)
@@ -0,0 +1,476 @@
+UNIT Unit9_data_structures;
+INTERFACE
+USES SysUtils, Classes, Unit3_data, Dialogs, StrUtils;
+
+TYPE
+  Tstructure_entry=RECORD
+      name:String;
+      offset:LongWord;
+      datatype:Word;  // 1..4  : Integer[1..4] dec
+                      // 5..8  : Integer[1..4] hex
+                      // 9     : float
+                      // 10    : bitset
+                      // 11    : raw-addr
+                      // 12    : dat-file-ID
+                      // 13..16: Signed Integer[1..4]
+                      // 17    : level-ID
+                      // 100..300: dat-file-name[0..200]
+                      // 1000..9999: Unused data[0-8999]
+                      // 10000+: string[0+]
+      description:String;
+    END;
+  TStructDefSub=RECORD
+      SubName:String;
+      SubDesc:String;
+      Entries:Array OF TStructure_entry;
+    END;
+  TStructDef=RECORD
+      Data:Boolean;
+      Global:Array OF TStructure_entry;
+      Subs:Array OF TStructDefSub;
+    END;
+  THandler=FUNCTION(fileid:LongWord):TRawList;
+  TRawListHandlers=RECORD
+    Ext:String[4];
+    needed:Boolean;
+    Handler:THandler;
+  END;
+
+VAR
+  RawListHandlers:Array OF TRawListHandlers;
+  Raws:String;
+
+
+FUNCTION LoadStructureDefinition(fileid:LongWord):TStructDef;
+FUNCTION GetDataType(typeid:Word):String;
+FUNCTION GetTypeDataLength(datatype:Word):Word;
+
+IMPLEMENTATION
+USES Unit2_functions, Unit15_Classes, Forms;
+
+FUNCTION GetTypeDataLength(datatype:Word):Word;
+  BEGIN
+    CASE datatype OF
+      1..4: Result:=datatype;
+      5..8: Result:=datatype-4;
+      9: Result:=4;
+      10: Result:=1;
+      11: Result:=4;
+      12: Result:=4;
+      13..16: Result:=datatype-12;
+      17: Result:=4;
+      100..300: Result:=datatype-100;
+      1000..9999: Result:=datatype-1000;
+      10000..65535: Result:=datatype-10000;
+    END;
+  END;
+
+FUNCTION GetDataType(typeid:Word):String;
+  BEGIN
+    CASE typeid OF
+      1..4: Result:='Int'+IntToStr(typeid*8);
+      5..8: Result:='Int'+IntToStr((typeid-4)*8);
+      9: Result:='Float';
+      10: Result:='BitSet';
+      11: Result:='Raw-Address';
+      12: Result:='.dat-file-ID';
+      13..16: Result:='SignedInt'+IntToStr((typeid-12)*8);
+      17: Result:='LevelID';
+      100..300: Result:='.dat-file-name('+IntToStr(typeid-100)+')';
+      1000..9999: Result:='Unused('+IntToStr(typeid-1000)+')';
+      10000..65535: Result:='String('+IntToStr(typeid-10000)+')';
+    END;
+  END;
+
+
+
+
+FUNCTION AGDB(fileid:LongWord):TRawList;
+  VAR
+    link:LongWord;
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF NOT OniDataConnection.OSisMac THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
+      links:=links*2;
+      SetLength(Result,links);
+      FOR i:=0 TO links-1 DO BEGIN
+        Result[i].src_offset:=$20+i*4;
+        OniDataConnection.LoadDatFilePart(fileid,$20+i*4,4,@link);
+        Result[i].raw_addr:=link;
+        Result[i].raw_size:=0{????????????????????????????????};
+        Result[i].loc_sep:=False;
+      END;
+    END;
+  END;
+FUNCTION AKVA(fileid:LongWord):TRawList;
+  VAR
+    link:LongWord;
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF NOT OniDataConnection.OSisMac THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
+      SetLength(Result,links);
+      FOR i:=0 TO links-1 DO BEGIN
+        Result[i].src_offset:=$20+i*$74+$24;
+        OniDataConnection.LoadDatFilePart(fileid,$20+i*$74+$24,4,@link);
+        Result[i].raw_addr:=link;
+        OniDataConnection.LoadDatFilePart(fileid,$20+i*$74+$28,4,@link);
+        Result[i].raw_size:=link;
+        Result[i].loc_sep:=False;
+      END;
+    END;
+  END;
+FUNCTION BINA(fileid:LongWord):TRawList;
+  VAR
+    link:LongWord;
+    datasize:LongWord;
+  BEGIN
+    OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link);
+    OniDataConnection.LoadDatFilePart(fileid,$08,4,@datasize);
+    SetLength(Result,1);
+    Result[0].src_offset:=$0C;
+    Result[0].raw_addr:=link;
+    Result[0].raw_size:=datasize;
+    Result[0].loc_sep:=OniDataConnection.OSisMac;
+  END;
+FUNCTION OSBD(fileid:LongWord):TRawList;
+  VAR
+    link:LongWord;
+    datasize:LongWord;
+  BEGIN
+    OniDataConnection.LoadDatFilePart(fileid,$08,4,@datasize);
+    OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link);
+    SetLength(Result,1);
+    Result[0].src_offset:=$0C;
+    Result[0].raw_addr:=link;
+    Result[0].raw_size:=datasize;
+    Result[0].loc_sep:=OniDataConnection.OSisMac;
+  END;
+FUNCTION SNDD(fileid:LongWord):TRawList;
+  VAR
+    link:LongWord;
+    datasize:LongWord;
+  BEGIN
+    SetLength(Result,1);
+    IF NOT OniDataConnection.OSisMac THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$40,4,@datasize);
+      OniDataConnection.LoadDatFilePart(fileid,$44,4,@link);
+      Result[0].src_offset:=$44;
+    END ELSE BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$10,4,@datasize);
+      OniDataConnection.LoadDatFilePart(fileid,$14,4,@link);
+      Result[0].src_offset:=$14;
+    END;
+    Result[0].raw_addr:=link;
+    Result[0].raw_size:=datasize;
+    Result[0].loc_sep:=False;
+  END;
+FUNCTION SUBT(fileid:LongWord):TRawList;
+  VAR
+    baselink,lastlink:LongWord;
+    links:LongWord;
+    j,k:LongWord;
+    data:Tdata;
+  BEGIN
+    OniDataConnection.LoadDatFilePart(fileid,$18,4,@baselink);
+    OniDataConnection.LoadDatFilePart(fileid,$1C,4,@links);
+    IF links>0 THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$20+(links-1)*4,4,@lastlink);
+      SetLength(data,lastlink+1024);
+        TOniDataDat(OniDataConnection).LoadRawOffset(false, baselink,lastlink+1024,data); 
+//      OniDataConnection.LoadRawFile(fileid,$1C,baselink,lastlink+1024,False,@data[0]);
+      k:=0;
+      FOR j:=0 TO 1024 DO BEGIN
+        IF (data[lastlink+j]=$00) OR (j=1024) THEN BEGIN
+          IF j<1024 THEN BEGIN
+            IF k=0 THEN BEGIN
+              k:=1;
+            END ELSE BEGIN
+              SetLength(Result,1);
+              Result[0].src_offset:=$18;
+              Result[0].raw_addr:=baselink;
+              Result[0].raw_size:=lastlink+j;
+              Break;
+            END;
+          END;
+        END;
+      END;
+    END;
+  END;
+FUNCTION TRAM(fileid:LongWord):TRawList;
+  VAR
+    i:Integer;
+    link:LongWord;
+    frames:Word;
+    tempb:Byte;
+    tempw:Word;
+    templ:LongWord;
+    data:Tdata;
+    offset:Word;
+    frame_count:Byte;
+  BEGIN
+    SetLength(Result,13);
+    OniDataConnection.LoadDatFilePart(fileid,$16C,2,@frames);
+    {y-pos}
+    OniDataConnection.LoadDatFilePart(fileid,$0C,4,@link);
+    Result[0].src_offset:=$0C;
+    Result[0].raw_addr:=link;
+    Result[0].raw_size:=frames*4;
+    {x-z-pos}
+    OniDataConnection.LoadDatFilePart(fileid,$10,4,@link);
+    Result[1].src_offset:=$10;
+    Result[1].raw_addr:=link;
+    Result[1].raw_size:=frames*8;
+    {attacks}
+    OniDataConnection.LoadDatFilePart(fileid,$182,1,@tempb);
+    OniDataConnection.LoadDatFilePart(fileid,$14,4,@link);
+    Result[2].src_offset:=$14;
+    Result[2].raw_addr:=link;
+    Result[2].raw_size:=tempb*32;
+    {damage}
+    OniDataConnection.LoadDatFilePart(fileid,$183,1,@tempb);
+    OniDataConnection.LoadDatFilePart(fileid,$18,4,@link);
+    Result[3].src_offset:=$18;
+    Result[3].raw_addr:=link;
+    Result[3].raw_size:=tempb*8;
+    {motionblur}
+    OniDataConnection.LoadDatFilePart(fileid,$184,1,@tempb);
+    OniDataConnection.LoadDatFilePart(fileid,$1C,4,@link);
+    Result[4].src_offset:=$1C;
+    Result[4].raw_addr:=link;
+    Result[4].raw_size:=tempb*8;
+    {shortcut}
+    OniDataConnection.LoadDatFilePart(fileid,$185,1,@tempb);
+    OniDataConnection.LoadDatFilePart(fileid,$20,4,@link);
+    Result[5].src_offset:=$20;
+    Result[5].raw_addr:=link;
+    Result[5].raw_size:=tempb*8;
+    {throw}
+    OniDataConnection.LoadDatFilePart(fileid,$24,4,@link);
+    Result[6].src_offset:=$24;
+    Result[6].raw_addr:=link;
+    IF link>0 THEN
+      Result[6].raw_size:=24
+    ELSE
+      Result[6].raw_size:=0;
+    {footstep}
+    OniDataConnection.LoadDatFilePart(fileid,$186,1,@tempb);
+    OniDataConnection.LoadDatFilePart(fileid,$28,4,@link);
+    Result[7].src_offset:=$28;
+    Result[7].raw_addr:=link;
+    Result[7].raw_size:=tempb*4;
+    {particle}
+    OniDataConnection.LoadDatFilePart(fileid,$187,1,@tempb);
+    OniDataConnection.LoadDatFilePart(fileid,$2C,4,@link);
+    Result[8].src_offset:=$2C;
+    Result[8].raw_addr:=link;
+    Result[8].raw_size:=tempb*24;
+    {position}
+    OniDataConnection.LoadDatFilePart(fileid,$30,4,@link);
+    Result[9].src_offset:=$30;
+    Result[9].raw_addr:=link;
+    Result[9].raw_size:=frames*8;
+    {particle}
+    OniDataConnection.LoadDatFilePart(fileid,$154,2,@tempw);
+    OniDataConnection.LoadDatFilePart(fileid,$38,4,@link);
+    Result[11].src_offset:=$38;
+    Result[11].raw_addr:=link;
+    Result[11].raw_size:=tempw*34;
+    {extent}
+    OniDataConnection.LoadDatFilePart(fileid,$138,4,@templ);
+    OniDataConnection.LoadDatFilePart(fileid,$13C,4,@link);
+    Result[12].src_offset:=$13C;
+    Result[12].raw_addr:=link;
+    Result[12].raw_size:=templ*12;
+
+    OniDataConnection.LoadDatFilePart(fileid,$34,4,@link);
+    IF link>0 THEN BEGIN
+      OniDataConnection.LoadDatFilePart(fileid,$160,2,@tempw);
+      frame_count:=0;
+      i:=0;
+      SetLength(data,$FFFF);
+      TOniDataDat(OniDataConnection).LoadRawOffset(false,link,$FFFF,data); 
+      offset:=data[$24]+data[$25]*256;
+      WHILE (offset+i<Length(data)) AND (frame_count<frames-1) DO BEGIN
+        Inc(i,tempw);
+        frame_count:=frame_count+data[offset+i];
+        Inc(i);
+      END;
+      IF offset+i<Length(data) THEN BEGIN
+        Inc(i,tempw);
+        Result[10].raw_size:=offset+i;
+      END ELSE BEGIN
+        Result[10].raw_size:=0;
+      END;
+    END;
+    Result[10].src_offset:=$34;
+    Result[10].raw_addr:=link;
+  END;
+FUNCTION TXMP(fileid:LongWord):TRawList;
+  VAR
+    link_pc:LongWord;
+    link_mac:LongWord;
+    x,y:Word;
+    storetype:Byte;
+    datasize:LongWord;
+  BEGIN
+    OniDataConnection.LoadDatFilePart(fileid,$8C,SizeOf(x),@x);
+    OniDataConnection.LoadDatFilePart(fileid,$8E,SizeOf(y),@y);
+    OniDataConnection.LoadDatFilePart(fileid,$90,SizeOf(storetype),@storetype);
+    OniDataConnection.LoadDatFilePart(fileid,$9C,4,@link_pc);
+    OniDataConnection.LoadDatFilePart(fileid,$A0,4,@link_mac);
+    CASE storetype OF
+      0,1,2: datasize:=x*y*2;
+      8: datasize:=x*y*4;
+      9: datasize:=x*y DIV 2;
+    END;
+    SetLength(Result,1);
+    IF NOT OniDataConnection.OSisMac THEN BEGIN
+      Result[0].src_offset:=$9C;
+      Result[0].raw_addr:=link_pc
+    END ELSE BEGIN
+      Result[0].src_offset:=$A0;
+      Result[0].raw_addr:=link_mac;
+    END;
+    Result[0].raw_size:=datasize;
+    Result[0].loc_sep:=OniDataConnection.OSisMac;
+  END;
+
+
+PROCEDURE InsertRawListHandler(ext:String; needed:Boolean; handler:THandler);
+  BEGIN
+    SetLength(RawListHandlers,Length(RawListHandlers)+1);
+    RawListHandlers[High(RawListHandlers)].Ext:=ext;
+    RawListHandlers[High(RawListHandlers)].needed:=needed;
+    RawListHandlers[High(RawListHandlers)].handler:=handler;
+    Raws:=Raws+ext;
+  END;
+
+
+
+FUNCTION LoadStructureDefinition(fileid:LongWord):TStructDef;
+  VAR
+    i:LongWord;
+    current_type:Byte; //0: Global, 1: Undynamic, 2: Dynamic
+    current_base,current_package,current_package_size:LongWord;
+    packages:LongWord;
+    deffile:Text;
+    structentry:TStructure_Entry;
+    fields:TStringArray;
+    filename:String;
+    ext:String[4];
+    temps:String;
+    data:TData;
+  BEGIN
+    SetLength(Result.Global,0);
+    SetLength(Result.Subs,0);
+    Result.Data:=False;
+    ext:=OniDataConnection.GetFileInfo(fileid).Extension;
+    filename:=ExtractFilePath(Application.ExeName)+'\StructDefs\'+ext+'.txt';
+    IF FileExists(filename) THEN BEGIN
+      data:=OniDataConnection.LoadDatFile(fileid);
+      AssignFile(deffile,filename);
+      Reset(deffile);
+      current_type:=0;
+      Result.Data:=True;
+      IF NOT EoF(deffile) THEN BEGIN
+        ReadLn(deffile,temps);
+        WHILE NOT EoF(deffile) DO BEGIN
+          ReadLn(deffile,temps);
+          IF (Length(temps)>0) AND (temps[1]<>'#') THEN BEGIN
+            IF temps[1]='*' THEN BEGIN
+              fields:=Explode(temps,#9);
+              CASE Length(fields) OF
+                1..2: BEGIN
+                     current_type:=1;
+                     current_base:=0;
+                     SetLength(Result.Subs, Length(Result.Subs)+1);
+                     Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],2,Length(fields[0])-1);
+                     IF Length(fields)=2 THEN
+                       Result.Subs[High(Result.Subs)].SubDesc:=fields[1];
+                   END;
+                3: BEGIN
+                     current_type:=1;
+                     current_base:=HexToLong(fields[2]);
+                     SetLength(Result.Subs, Length(Result.Subs)+1);
+                     Result.Subs[High(Result.Subs)].SubName:=MidStr(fields[0],2,Length(fields[0])-1);
+                     Result.Subs[High(Result.Subs)].SubDesc:=fields[1];
+                   END;
+                6: BEGIN
+                     current_type:=2;
+                     current_base:=HexToLong(fields[2]);
+                     current_package:=0;
+                     current_package_size:=StrToInt(fields[5]);
+                     IF fields[4][1]<>'$' THEN BEGIN
+                       CASE StrToInt(fields[4]) OF
+                         1: packages:=data[HexToLong(fields[3])];
+                         2: packages:=data[HexToLong(fields[3])]+data[HexToLong(fields[3])+1]*256;
+                         4: packages:=data[HexToLong(fields[3])]+data[HexToLong(fields[3])+1]*256+data[HexToLong(fields[3])+2]*256*256+data[HexToLong(fields[3])+3]*256*256*256;
+                       END;
+                     END ELSE BEGIN
+                       packages:=HexToLong(fields[4]);
+                     END;
+                     SetLength(Result.Subs, Length(Result.Subs)+packages);
+                     FOR current_package:=0 TO packages-1 DO BEGIN
+                       Result.Subs[High(Result.Subs)-packages+current_package+1].SubName:=
+                           MidStr(fields[0],2,Length(fields[0])-1)+'['+IntToStr(current_package)+']'+
+                           '#'+IntToHex(current_base+current_package*current_package_size,8)+
+                           '#'+IntToHex(current_package_size,8);
+                       Result.Subs[High(Result.Subs)-packages+current_package+1].SubDesc:=
+                           fields[1];
+                     END;
+                   END;
+              END;
+            END ELSE BEGIN
+              fields:=Explode(temps,#9);
+              IF (Length(fields)=3) OR (Length(fields)=4) THEN BEGIN
+                IF NOT AppSettings.HideUnusedData OR ((StrToInt(fields[2])<1000) OR (StrToInt(fields[2])>9999)) THEN BEGIN 
+                  structentry.name:=fields[0];
+                  structentry.datatype:=StrToInt(fields[2]);
+                  IF Length(fields)=4 THEN
+                    structentry.description:=fields[3]
+                  ELSE
+                    structentry.description:='';
+                  IF current_type IN [0,1] THEN BEGIN
+                    structentry.offset:=HexToLong(fields[1])+current_base;
+                    IF Length(Result.Subs)=0 THEN BEGIN
+                      SetLength(Result.Global,Length(Result.Global)+1);
+                      Result.Global[High(Result.Global)]:=structentry;
+                    END ELSE BEGIN
+                      SetLength(Result.Subs[High(Result.Subs)].Entries,Length(Result.Subs[High(Result.Subs)].Entries)+1);
+                      Result.Subs[High(Result.Subs)].Entries[High(Result.Subs[High(Result.Subs)].Entries)]:=structentry;
+                    END;
+                  END ELSE BEGIN
+                    FOR current_package:=0 TO packages-1 DO BEGIN
+                      structentry.offset:=current_base+current_package*current_package_size+HexToLong(fields[1]);
+                      WITH Result.Subs[High(Result.Subs)-packages+current_package+1] DO BEGIN
+                        SetLength(Entries,Length(Entries)+1);
+                        Entries[High(Entries)]:=structentry;
+                      END;
+                    END;
+                  END;
+                END;
+              END;
+            END;
+          END;
+        END;
+      END;
+      CloseFile(deffile);
+    END;
+  END;
+
+
+BEGIN
+  Raws:='';
+//  InsertRawListHandler('AGDB',True,AGDB);
+  InsertRawListHandler('AKVA',True,AKVA);
+  InsertRawListHandler('BINA',True,BINA);
+  InsertRawListHandler('OSBD',True,OSBD);
+  InsertRawListHandler('SNDD',True,SNDD);
+  InsertRawListHandler('SUBT',True,SUBT);
+  InsertRawListHandler('TRAM',True,TRAM);
+  InsertRawListHandler('TXMP',True,TXMP);
+END.
Index: /oup/current/blubb.txt
===================================================================
--- /oup/current/blubb.txt	(revision 10)
+++ /oup/current/blubb.txt	(revision 10)
@@ -0,0 +1,6 @@
+___FILEINDEX___.txt
+
+
+TXMP:
+MipMapping: Bit0=an/aus
+ColorDepth: Bit0=??AnimationPic??, Bit1=shade vertex, Bit2=transparency, Bit4=16bit, Bit5=32bit
Index: /oup/current/changelog.txt
===================================================================
--- /oup/current/changelog.txt	(revision 10)
+++ /oup/current/changelog.txt	(revision 10)
@@ -0,0 +1,114 @@
+OniUnPacker v0.32a
+------------------
++DB2Dat functionality enhanced (*can* be used but is not yet finished)
++PSpc Preview added (but not yet working cause of some weird bugs)
+
+OniUnPacker v0.32a
+------------------
++Raw-part "BodyPartAnimation data" of TRAMs
++Added basic DB2Dat functionality (SHOULD NOT BE USED YET!!!)
++CharSet selection (works for ValueViewer only right now)
+
+OniUnPacker v0.31a
+------------------
++Dat2DB function working
++Fixed a bug which appeared when multiple windows of the same class were opened at one time (eg 2*BinEdit)
+
+OniUnPacker v0.30a
+------------------
++Completely rewritten data-backend-connection-classes (Unit15_Classes.pas)
+
+OniUnPacker v0.29a
+------------------
++Little changes in StructureDefs
+
+OniUnPacker v0.29a
+------------------
++New StructureViewer
++New StructureTypes: 12=.dat-file-ID, 13..16=SignedInteger, 1000..9999=Unused data
++Dynamic Structures (look at TXAN-files or AISA-files for examples)
++File-type associations (.dat, .oldb, .opf) with OUP possible
++File IDs as Hex
+
+OniUnPacker v0.28a
+------------------
++StructureDefinitions as separate txt-files
++Minor bugfixes
++Ctrl+C for Hex-fields
+
+OniUnPacker v0.27a
+------------------
++Added MAC-file support
++Added StructureDefs for ONCCs / TRAMs (thanks to SSG)
+
+OniUnPacker v0.26a
+------------------
++Fixed some bugs again ;)
+
+OniUnPacker v0.25a
+------------------
++Fixed some bugs here and there ;)
++BinEdit/RawEdit: Added keycombo CTRL+S for saving current file
+
+OniUnPacker v0.24a
+------------------
++RawEdit. Open it by doubleclick on a Raw-Link in the StructureViewer of BinEdit or enter the FileID and the offset of the raw-link in the .dat-file manually
+
+OniUnPacker v0.23a
+------------------
++Added copy2clipboard functions to ValueViewer (rightclick)
++Enhanced FileList-filters
++Added ValueEditor to BinEdit -> StructViewer / ValueViewer (doubleclick on either value field of ValueViewer or StructViewer)
+
+OniUnPacker v0.22a
+------------------
++Replaced DB-Backend (much faster conversion of levels)
++Added ValueViewer to BinEdit (decodes selected area as different variable-types)
+
+OniUnPacker v0.21a
+------------------
++Extractor tool works almost completely (you can't select where the files are stored if you *don't* choose to put them all in one file. They are stored in the root of drive d:)
++Corrected string-display in the structure viewer of BinEdit (strings are now displayed as a hint of the value-box if you move the mouse over it)
+
+OniUnPacker v0.20a
+------------------
++? (Forgot what I added here ;) )
+
+OniUnPacker v0.19a
+------------------
++.dat/.raw -> OUP-Level-DB-Convert basics
++Extractor tool (not working yet :D )
+
+OniUnPacker v0.18a
+------------------
++Completely rewritten GUI
+
+OniUnPacker v0.17a
+------------------
++Binary-editor: Structure-viewer (only TXMP so far)
+
+OniUnPacker v0.16a
+------------------
++Replaced hex-view-box with a true hex-component
++Binary-editor for .dat-files
+
+OniUnPacker v0.15a
+------------------
++Extract menu
++Changed layout
+
+OniUnPacker v0.14a
+------------------
++Corrected image-decoder for 32bit images
++TXMP-Replace: 32bit option (for prevention from quality loss)
+
+OniUnPacker v0.13a
+------------------
++TXMP-Replace: Transparency option
++TXMP-Replace: Fading option
++TXMP-Replace: Overwrites old data if the new fits in that space (to keep the raw as small as possible)
+
+OniUnPacker v0.12a
+------------------
++TXMP-Replace function (Menu -> Tools -> TXMP Replacer)
++TXMB-Decoder (export with convert & preview)
Index: /oup/current/exe/StructDefs/ABNA.txt
===================================================================
--- /oup/current/exe/StructDefs/ABNA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ABNA.txt	(revision 10)
@@ -0,0 +1,11 @@
+BSP Tree Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	16
+Unknown	$00	4	Unknown
+Unknown	$04	3	Unknown
+High bit	$07	1	High bit
+Unknown	$08	4	Unknown
+Unknown	$0C	4	Unknown
Index: /oup/current/exe/StructDefs/AGDB.txt
===================================================================
--- /oup/current/exe/StructDefs/AGDB.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AGDB.txt	(revision 10)
@@ -0,0 +1,8 @@
+Gunk Quad Debug Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	8
+Unknown	$00	8	Unknown
+Unknown	$04	8	Unknown
Index: /oup/current/exe/StructDefs/AGQC.txt
===================================================================
--- /oup/current/exe/StructDefs/AGQC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AGQC.txt	(revision 10)
@@ -0,0 +1,14 @@
+Gunk Quad Collision Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	28
+Unknown	$00	3	Unknown
+High bit	$03	1	High bit
+Unknown	$04	9	Unknown
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
Index: /oup/current/exe/StructDefs/AGQG.txt
===================================================================
--- /oup/current/exe/StructDefs/AGQG.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AGQG.txt	(revision 10)
@@ -0,0 +1,25 @@
+Gunk Quad General Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	56
+Unknown	$00	4	Unknown
+Unknown	$04	4	Unknown
+Unknown	$08	4	Unknown
+Unknown	$0C	4	Unknown
+Unknown	$10	4	Unknown
+Unknown	$14	4	Unknown
+Unknown	$18	4	Unknown
+Unknown	$1C	4	Unknown
+Unknown	$20	2	Unknown
+Unknown	$22	2	Unknown
+Unknown	$24	2	Unknown
+Unknown	$26	2	Unknown
+Unknown	$28	2	Unknown
+Unknown	$2A	2	Unknown
+Unknown	$2C	2	Unknown
+Unknown	$2E	2	Unknown
+Unknown	$30	2	Unknown
+Unknown	$32	2	Unknown
+Unknown	$34	4	Unknown
Index: /oup/current/exe/StructDefs/AGQR.txt
===================================================================
--- /oup/current/exe/StructDefs/AGQR.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AGQR.txt	(revision 10)
@@ -0,0 +1,8 @@
+Gunk Quad Render Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+Unknown	$00	2	Unknown
+Not used	$02	1002	Not used
Index: /oup/current/exe/StructDefs/AISA.txt
===================================================================
--- /oup/current/exe/StructDefs/AISA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AISA.txt	(revision 10)
@@ -0,0 +1,27 @@
+AI Character Setup Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	352
+Unknown	$00	10032	unknown; always zero; maybe space for notes
+Charcter id	$20	2	Id of the character, which you can spawn with the script command "chr_create"
+Flag id	$22	2	Od of the flag, where Oni spawns the character (works only, if the flag exits; look to Flag.BINA for a flag list)
+Unknown	$24	2	Unknown
+Unknown	$26	2	Unknown
+ONCC-link	$28	12	Link to the Character Class
+Unknown	$2C	4	Unknown; always the same
+Unknown	$30	10032	Unknown; never used in Oni
+Spawn function	$50	10032	Name of the function, which is called up when Oni spawns the character
+Lose function	$70	10032	Name of the function, which is called up when the character dies
+Alert function	$90	10032	Name of the function, which is called up when the character notices the player
+Unknown	$B0	10032	Unknown; never used in Oni
+Hit function	$D0	10032	Name of the function, which is called up when someone hits the character the first time
+Health = 1 function	$F0	10032	Name of the function, which is called up when the health of the character is equal 1
+Reload function	$110	10032	Name of the function, which is called up when the character reloads its weapon with its last ammo/cell; works only, if the character has some ammo/cells when Oni spawns it
+Unknown	$130	10032	Unknown; never used in Oni
+ONWC-link	$150	12	Link to the Weapon Class; used to give the charcater a weapon
+Unknown	$154	2	Unknown
+Unknown	$156	14	Unknown; always the same
+Unknown	$158	4	Unknown; always the same
+Unknown	$15C	4	Unknown; always the same
Index: /oup/current/exe/StructDefs/AITR.txt
===================================================================
--- /oup/current/exe/StructDefs/AITR.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AITR.txt	(revision 10)
@@ -0,0 +1,15 @@
+AI Script Trigger Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	84
+Unknown	$00	2	Unknown
+Unknown	$02	2	Unknown
+Unknown	$04	2	Unknown
+Unknown	$06	2	Unknown
+Unknown	$08	2	Unknown
+Unknown	$0A	2	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	10064	Unknown
Index: /oup/current/exe/StructDefs/AKAA.txt
===================================================================
--- /oup/current/exe/StructDefs/AKAA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AKAA.txt	(revision 10)
@@ -0,0 +1,9 @@
+Adjacency Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	12
+Unknown	$00	4	Unknown
+Unknown	$04	4	Unknown
+Unknown	$08	4	Unknown
Index: /oup/current/exe/StructDefs/AKBA.txt
===================================================================
--- /oup/current/exe/StructDefs/AKBA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AKBA.txt	(revision 10)
@@ -0,0 +1,14 @@
+Side Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	28
+Unknown	$00	3	Unknown
+High bit	$03	1	High bit
+Unknown	$04	4	Unknown
+Unknown	$08	4	Unknown
+Unknown	$0C	4	Unknown
+Unknown	$10	4	Unknown
+Unknown	$14	4	Unknown
+Unknown	$18	4	Unknown
Index: /oup/current/exe/StructDefs/AKBP.txt
===================================================================
--- /oup/current/exe/StructDefs/AKBP.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AKBP.txt	(revision 10)
@@ -0,0 +1,10 @@
+BSP Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	12
+Unknown	$00	3	Unknown
+High bit	$03	1	High bit
+Unknown	$04	4	Unknown
+Unknown	$08	4	Unknown; always the same
Index: /oup/current/exe/StructDefs/AKDA.txt
===================================================================
--- /oup/current/exe/StructDefs/AKDA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AKDA.txt	(revision 10)
@@ -0,0 +1,19 @@
+Door Frame Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	52
+Unknown	$00	4	Unknown
+Low left x-coordinate	$04	9	x-coordinate of the lower left point of the doorframe
+Low left y-coordinate	$08	9	y-coordinate (height) of the lower left point of the doorframe
+Low left z-coordinate	$0C	9	z-coordinate of the lower left point of the doorframe
+Up right x-coordinate	$10	9	x-coordinate of the upper right point of the doorframe
+Up right y-coordinate	$14	9	y-coordinate (height) of the upper right point of the doorframe
+Up right z-coordinate	$18	9	z-coordinate of the upper right point of the doorframe
+Center x-coordinate	$1C	9	x-coordinate of the center point of the doorframe
+Center y-coordinate	$20	9	y-coordinate (height) of the center point of the doorframe
+Center z-coordinate	$24	9	z-coordinate of the center point of the doorframe
+Depth	$28	9	Depth of the doorframe
+Width	$2C	9	Width of the doorframe
+Height	$30	9	Height of the doorframe
Index: /oup/current/exe/StructDefs/AKEV.txt
===================================================================
--- /oup/current/exe/StructDefs/AKEV.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AKEV.txt	(revision 10)
@@ -0,0 +1,28 @@
+Environment
+File id	$00	12	File id
+Level id	$04	17	Level id
+PNTA-link	$08	12	Link to the 3D Point Array
+PLEA-link	$0C	12	Link to the Plane Equation Array
+TXCA-link	$10	12	Link to the Texture Coordinate Array
+AGQG-link	$14	12	Link to the Gunk Quad General Array
+AGQR-link	$18	12	Link to the Gunk Quad Render Array
+AGQC-link	$1C	12	Link to the Gunk Quad Collision Array
+AGDB-link	$20	12	Link to the Gunk Quad Debug Array
+TXMA-link	$24	12	Link to the Texture Map Array
+AKVA-link	$28	12	Link to the BNV Node Array
+AKBA-link	$2C	12	Link to the Side Array
+IDXA-link	$30	12	Link to the Index Array
+IDXA-link	$34	12	Link to the Index Array
+AKBP-link	$38	12	Link to the BSP Node Array
+ABNA-link	$3C	12	Link to the BSP Tree Node Array
+AKOT-link	$40	12	Link to the Oct Tree
+AKAA-link	$44	12	Link to the Adjacency Array
+AKDA-link	$48	12	Link to the Door Frame Array
+Neg. x-coordinate	$4C	9	Maximal negative x-coordinate of the level model
+Neg. y-coordinate	$50	9	Maximal negative y-coordinate of the level model
+Neg. z-coordinate	$54	9	Maximal negative z-coordinate (height) of the level model
+Pos. x-coordinate	$58	9	Maximal positive x-coordinate of the level model
+Pos. y-coordinate	$5C	9	Maximal positive y-coordinate (height) of the level model
+Pos. z-coordinate	$60	9	Maximal positive z-coordinate of the level model
+Not used	$64	1024	Not used
+Unknown	$7C	9	Unknown; maybe the tolerance
Index: /oup/current/exe/StructDefs/AKOT.txt
===================================================================
--- /oup/current/exe/StructDefs/AKOT.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AKOT.txt	(revision 10)
@@ -0,0 +1,9 @@
+Oct Tree
+File id	$00	12	File id
+Level id	$04	17	Level id
+OTIT-link	$08	12	Link to the Oct Tree Interior Node Array
+OTLF-link	$0C	12	Link to the Oct Tree Leaf Node Array
+QTNA-link	$10	12	Link to the Quad Tree Node Array
+IDXA-link	$14	12	Link to the Index Array
+IDXA-link	$18	12	Link to the Index Array
+Not used	$1C	1004	Not used
Index: /oup/current/exe/StructDefs/AKVA.txt
===================================================================
--- /oup/current/exe/StructDefs/AKVA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/AKVA.txt	(revision 10)
@@ -0,0 +1,35 @@
+BNV Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	116
+Unknown	$00	4	Unknown
+Id	$04	4	Id
+Unknown	$08	4	Unknown
+Unknown	$0C	4	Unknown
+Unknown	$10	4	Unknown
+Unknown	$14	4	Unknown
+Unknown	$18	4	Unknown
+Unknown	$1C	4	Unknown
+Unknown	$20	4	Unknown
+Unknown	$24	11	From this position starts the unknown part in the raw file
+Size	$28	4	Size of the part in the raw file
+Unknown	$2C	9	Unknown
+Unknown	$30	9	Unknown
+Unknown	$34	9	Unknown
+Unknown	$38	9	Unknown
+Unknown	$3C	9	Unknown
+Unknown	$40	9	Unknown
+Unknown	$44	9	Unknown
+Unknown	$48	4	Unknown
+Id (again)	$4C	4	Id (again)
+Unknown	$50	9	Unknown
+Unknown	$54	9	Unknown
+Unknown	$58	9	Unknown
+Unknown	$5C	4	Unknown
+Unknown	$60	9	Unknown
+Unknown	$64	9	Unknown
+Unknown	$68	9	Unknown
+Unknown	$6C	9	Unknown
+Unknown	$70	9	Unknown
Index: /oup/current/exe/StructDefs/BINA.txt
===================================================================
--- /oup/current/exe/StructDefs/BINA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/BINA.txt	(revision 10)
@@ -0,0 +1,6 @@
+Binary Data
+File id	$00	12	File id
+Level id	$04	17	Level id
+Size	$08	4	Size of the part in the raw file
+Offset	$0C	11	At this position starts the part in the raw/sep file
+Not used	$10	1016	Not used
Index: /oup/current/exe/StructDefs/CBPI.txt
===================================================================
--- /oup/current/exe/StructDefs/CBPI.txt	(revision 10)
+++ /oup/current/exe/StructDefs/CBPI.txt	(revision 10)
@@ -0,0 +1,61 @@
+Character Body Part Impacts
+File id	$00	12	File id
+Level id	$04	17	Level id
+Impt-link	$08	12	Link to the Impact Tree
+Impt-link	$0C	12	Link to the Impact Tree
+Impt-link	$10	12	Link to the Impact Tree
+Impt-link	$14	12	Link to the Impact Tree
+Impt-link	$18	12	Link to the Impact Tree
+Impt-link	$1C	12	Link to the Impact Tree
+Impt-link	$20	12	Link to the Impact Tree
+Impt-link	$24	12	Link to the Impact Tree
+Impt-link	$28	12	Link to the Impact Tree
+Impt-link	$2C	12	Link to the Impact Tree
+Impt-link	$30	12	Link to the Impact Tree
+Impt-link	$34	12	Link to the Impact Tree
+Impt-link	$38	12	Link to the Impact Tree
+Impt-link	$3C	12	Link to the Impact Tree
+Impt-link	$40	12	Link to the Impact Tree
+Impt-link	$44	12	Link to the Impact Tree
+Impt-link	$48	12	Link to the Impact Tree
+Impt-link	$4C	12	Link to the Impact Tree
+Impt-link	$50	12	Link to the Impact Tree
+Impt-link	$54	12	Link to the Impact Tree
+Impt-link	$58	12	Link to the Impact Tree
+Impt-link	$5C	12	Link to the Impact Tree
+Impt-link	$60	12	Link to the Impact Tree
+Impt-link	$64	12	Link to the Impact Tree
+Impt-link	$68	12	Link to the Impact Tree
+Impt-link	$6C	12	Link to the Impact Tree
+Impt-link	$70	12	Link to the Impact Tree
+Impt-link	$74	12	Link to the Impact Tree
+Impt-link	$78	12	Link to the Impact Tree
+Impt-link	$7C	12	Link to the Impact Tree
+Impt-link	$80	12	Link to the Impact Tree
+Impt-link	$84	12	Link to the Impact Tree
+Impt-link	$88	12	Link to the Impact Tree
+Impt-link	$8C	12	Link to the Impact Tree
+Impt-link	$90	12	Link to the Impact Tree
+Impt-link	$94	12	Link to the Impact Tree
+Impt-link	$98	12	Link to the Impact Tree
+Impt-link	$9C	12	Link to the Impact Tree
+Impt-link	$A0	12	Link to the Impact Tree
+Impt-link	$A4	12	Link to the Impact Tree
+Impt-link	$A8	12	Link to the Impact Tree
+Impt-link	$AC	12	Link to the Impact Tree
+Impt-link	$B0	12	Link to the Impact Tree
+Impt-link	$B4	12	Link to the Impact Tree
+Impt-link	$B8	12	Link to the Impact Tree
+Impt-link	$BC	12	Link to the Impact Tree
+Impt-link	$C0	12	Link to the Impact Tree
+Impt-link	$C4	12	Link to the Impact Tree
+Impt-link	$C8	12	Link to the Impact Tree
+Impt-link	$CC	12	Link to the Impact Tree
+Impt-link	$D0	12	Link to the Impact Tree
+Impt-link	$D4	12	Link to the Impact Tree
+Impt-link	$D8	12	Link to the Impact Tree
+Impt-link	$DC	12	Link to the Impact Tree
+Impt-link	$E0	12	Link to the Impact Tree
+Impt-link	$E4	12	Link to the Impact Tree
+Impt-link	$E8	12	Link to the Impact Tree
+Not used	$EC	1020	Not used
Index: /oup/current/exe/StructDefs/CBPM.txt
===================================================================
--- /oup/current/exe/StructDefs/CBPM.txt	(revision 10)
+++ /oup/current/exe/StructDefs/CBPM.txt	(revision 10)
@@ -0,0 +1,23 @@
+Character Body Part Material
+File id	$00	12	File id
+Level id	$04	17	Level id
+Mtrl-link	$08	12	Link to the Material
+Mtrl-link	$0C	12	Link to the Material
+Mtrl-link	$10	12	Link to the Material
+Mtrl-link	$14	12	Link to the Material
+Mtrl-link	$18	12	Link to the Material
+Mtrl-link	$1C	12	Link to the Material
+Mtrl-link	$20	12	Link to the Material
+Mtrl-link	$24	12	Link to the Material
+Mtrl-link	$28	12	Link to the Material
+Mtrl-link	$2C	12	Link to the Material
+Mtrl-link	$30	12	Link to the Material
+Mtrl-link	$34	12	Link to the Material
+Mtrl-link	$38	12	Link to the Material
+Mtrl-link	$3C	12	Link to the Material
+Mtrl-link	$40	12	Link to the Material
+Mtrl-link	$44	12	Link to the Material
+Mtrl-link	$48	12	Link to the Material
+Mtrl-link	$4C	12	Link to the Material
+Mtrl-link	$50	12	Link to the Material
+Not used	$54	1012	Not used
Index: /oup/current/exe/StructDefs/CONS.txt
===================================================================
--- /oup/current/exe/StructDefs/CONS.txt	(revision 10)
+++ /oup/current/exe/StructDefs/CONS.txt	(revision 10)
@@ -0,0 +1,18 @@
+Console
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	4	Unknown; always the same
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown; always the same
+Unknown	$14	9	Unknown; always the same
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown; always the same
+Unknown	$20	9	Unknown; always the same
+OFGA-link	$24	12	Link to the Object Furn Geom Array
+M3GM-link	$28	12	Link to the Geometry
+Unknown	$2C	2	Unknown; always the same
+Unknown	$2E	2	Unknown; always the same
+Unknown	$30	10032	Unknown; always the same
+Unknown	$50	10032	Unknown; always the same
+Unknown	$70	10032	Unknown; always the same
+Not used	$90	1016	Not used
Index: /oup/current/exe/StructDefs/CRSA.txt
===================================================================
--- /oup/current/exe/StructDefs/CRSA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/CRSA.txt	(revision 10)
@@ -0,0 +1,244 @@
+Corpse Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1012	Not used
+Packages available	$14	4	Amount of packages that are available
+Packages used	$18	4	Amount of packages that follow
+Packages possible	$1C	4	Amount of packages that are possible
+*Package		$20	$18	4	1100
+Old file name	$00	10160	Old file name
+ONCC-link	$A0	12	Link to the Character Class
+1st point x-coordinate	$A4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$A8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$AC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$B0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$B4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$B8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$BC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$C0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$C4	9	z-position of the 3rd point of an equilateral triangle
+Pelvis x-position	$C8	9	x-position of the pelvis
+Pelvis y-position	$CC	9	y-position (height) of the pelvis
+Pelvis z-position	$D0	9	z-position of the pelvis
+1st point x-coordinate	$D4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$D8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$DC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$E0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$E4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$E8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$EC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$F0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$F4	9	z-position of the 3rd point of an equilateral triangle
+Left thigh x-position	$F8	9	x-position of the left thigh
+Left thigh y-position	$FC	9	y-position (height) of the left thigh
+Left thigh z-position	$100	9	z-position of the left thigh
+1st point x-coordinate	$104	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$108	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$10C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$110	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$114	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$118	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$11C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$120	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$124	9	z-position of the 3rd point of an equilateral triangle
+Left calf x-position	$128	9	x-position of the left calf
+Left calf y-position	$12C	9	y-position (height) of the left calf
+Left calf z-position	$130	9	z-position of the left calf
+1st point x-coordinate	$134	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$138	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$13C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$140	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$144	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$148	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$14C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$150	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$154	9	z-position of the 3rd point of an equilateral triangle
+Left foot x-position	$158	9	x-position of the left foot
+Left foot y-position	$15C	9	y-position (height) of the left foot
+Left foot z-position	$160	9	z-position of the left foot
+1st point x-coordinate	$164	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$168	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$16C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$170	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$174	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$178	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$17C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$180	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$184	9	z-position of the 3rd point of an equilateral triangle
+Right thigh x-position	$188	9	x-position of the right thigh
+Right thigh y-position	$18C	9	y-position (height) of the right thigh
+Right thigh z-position	$190	9	z-position of the right thigh
+1st point x-coordinate	$194	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$198	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$19C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$1A0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$1A4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$1A8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$1AC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$1B0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$1B4	9	z-position of the 3rd point of an equilateral triangle
+Right calf x-position	$1B8	9	x-position of the right calf
+Right calf y-position	$1BC	9	y-position (height) of the right calf
+Right calf z-position	$1C0	9	z-position of the right calf
+1st point x-coordinate	$1C4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$1C8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$1CC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$1D0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$1D4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$1D8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$1DC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$1E0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$1E4	9	z-position of the 3rd point of an equilateral triangle
+Right foot x-position	$1E8	9	x-position of the right foot
+Right foot y-position	$1EC	9	y-position (height) of the right foot
+Right foot z-position	$1F0	9	z-position of the right foot
+1st point x-coordinate	$1F4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$1F8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$1FC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$200	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$204	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$208	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$20C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$210	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$214	9	z-position of the 3rd point of an equilateral triangle
+Mid x-position	$218	9	x-position of the mid
+Mid y-position	$21C	9	y-position (height) of the mid
+Mid z-position	$220	9	z-position of the mid
+1st point x-coordinate	$224	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$228	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$22C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$230	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$234	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$238	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$23C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$240	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$244	9	z-position of the 3rd point of an equilateral triangle
+Chest x-position	$248	9	x-position of the chest
+Chest y-position	$24C	9	y-position (height) of the chest
+Chest z-position	$250	9	z-position of the chest
+1st point x-coordinate	$254	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$258	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$25C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$260	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$264	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$268	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$26C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$270	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$274	9	z-position of the 3rd point of an equilateral triangle
+Neck x-position	$278	9	x-position of the neck
+Neck y-position	$27C	9	y-position (height) of the neck
+Neck z-position	$280	9	z-position of the neck
+1st point x-coordinate	$284	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$288	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$28C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$290	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$294	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$298	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$29C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$2A0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$2A4	9	z-position of the 3rd point of an equilateral triangle
+Head x-position	$2A8	9	x-position of the head
+Head y-position	$2AC	9	y-position (height) of the head
+Head z-position	$2B0	9	z-position of the head
+1st point x-coordinate	$2B4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$2B8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$2BC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$2C0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$2C4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$2C8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$2CC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$2D0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$2D4	9	z-position of the 3rd point of an equilateral triangle
+Left shoulder x-position	$2D8	9	x-position of the left shoulder
+Left shoulder y-position	$2DC	9	y-position (height) of the left shoulder
+Left shoulder z-position	$2E0	9	z-position of the left shoulder
+1st point x-coordinate	$2E4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$2E8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$2EC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$2F0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$2F4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$2F8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$2FC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$300	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$304	9	z-position of the 3rd point of an equilateral triangle
+Left bicep x-position	$308	9	x-position of the left bicep
+Left bicep y-position	$30C	9	y-position (height) of the left bicep
+Left bicep z-position	$310	9	z-position of the left bicep
+1st point x-coordinate	$314	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$318	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$31C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$320	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$324	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$328	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$32C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$330	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$334	9	z-position of the 3rd point of an equilateral triangle
+Left wrist x-position	$338	9	x-position of the left wrist
+Left wrist y-position	$33C	9	y-position (height) of the left wrist
+Left wrist z-position	$340	9	z-position of the left wrist
+1st point x-coordinate	$344	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$348	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$34C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$350	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$354	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$358	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$35C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$360	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$364	9	z-position of the 3rd point of an equilateral triangle
+Left hand x-position	$368	9	x-position of the left hand
+Left hand y-position	$36C	9	y-position (height) of the left hand
+Left hand z-position	$370	9	z-position of the left hand
+1st point x-coordinate	$374	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$378	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$37C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$380	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$384	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$388	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$38C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$390	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$394	9	z-position of the 3rd point of an equilateral triangle
+Right shoulder x-position	$398	9	x-position of the right shoulder
+Right shoulder y-position	$39C	9	y-position (height) of the right shoulder
+Right shoulder z-position	$3A0	9	z-position of the right shoulder
+1st point x-coordinate	$3A4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$3A8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$3AC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$3B0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$3B4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$3B8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$3BC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$3C0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$3C4	9	z-position of the 3rd point of an equilateral triangle
+Right bicep x-position	$3C8	9	x-position of the right bicep
+Right bicep y-position	$3CC	9	y-position (height) of the right bicep
+Right bicep z-position	$3D0	9	z-position of the right bicep
+1st point x-coordinate	$3D4	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$3D8	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$3DC	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$3E0	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$3E4	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$3E8	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$3EC	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$3F0	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$3F4	9	z-position of the 3rd point of an equilateral triangle
+Right wrist x-position	$3F8	9	x-position of the right wrist
+Right wrist y-position	$3FC	9	y-position (height) of the right wrist
+Right wrist z-position	$400	9	z-position of the right wrist
+1st point x-coordinate	$404	9	x-position of the 1st point of an equilateral triangle
+1st point y-coordinate	$408	9	y-position (height) of the 1st point of an equilateral triangle
+1st point z-coordinate	$40C	9	z-position of the 1st point of an equilateral triangle
+2nd point x-coordinate	$410	9	x-position of the 2nd point of an equilateral triangle
+2nd point y-coordinate	$414	9	y-position (height) of the 2nd point of an equilateral triangle
+2nd point z-coordinate	$418	9	z-position of the 2nd point of an equilateral triangle
+3rd point x-coordinate	$41C	9	x-position of the 3rd point of an equilateral triangle
+3rd point y-coordinate	$420	9	y-position (height) of the 3rd point of an equilateral triangle
+3rd point z-coordinate	$424	9	z-position of the 3rd point of an equilateral triangle
+Right hand x-position	$428	9	x-position of the right hand
+Right hand y-position	$42C	9	y-position (height) of the right hand
+Right hand z-position	$430	9	z-position of the right hand
+Minimal x-coordinate	$434	9	Minimal x-coordinate of the bounding box
+Minimal y-coordinate	$438	9	Minimal y-coordinate (height) of the bounding box
+Minimal z-coordinate	$43C	9	Minimal z-coordinate of the bounding box
+Maximal x-coordinate	$440	9	Maximal x-coordinate of the bounding box
+Maximal y-coordinate	$444	9	Maximal y-coordinate (height) of the bounding box
+Maximal z-coordinate	$448	9	Maximal z-coordinate of the bounding box
Index: /oup/current/exe/StructDefs/DOOR.txt
===================================================================
--- /oup/current/exe/StructDefs/DOOR.txt	(revision 10)
+++ /oup/current/exe/StructDefs/DOOR.txt	(revision 10)
@@ -0,0 +1,15 @@
+DOOR File
+File id	$00	12	File id
+Level id	$04	17	Level id
+OFGA-link	$08	12	Link to the Object Furn Geom Array
+Unknown	$0C	4	Unknown; maybe a canceled link; always the same
+OBAN-link	$10	12	Link to the Object Animation
+Unknown	$14	9	Unknown; always the same
+Unknown	$18	4	Unknown; always the same
+Unknown	$1C	16	Unknown; always the same
+Unknown	$20	9	Unknown; always the same
+Door open sound	$24	132	Reference to an OSBD file of level 0
+Door close sound	$44	132	Reference to an OSBD file of level 0
+Unknown	$64	4	Unknown
+Unknown	$68	4	Unknown
+Not useed	$6C	1020	Not used
Index: /oup/current/exe/StructDefs/DPge.txt
===================================================================
--- /oup/current/exe/StructDefs/DPge.txt	(revision 10)
+++ /oup/current/exe/StructDefs/DPge.txt	(revision 10)
@@ -0,0 +1,8 @@
+Diary Page
+File id	$00	12	File id
+Level id	$04	17	Level id
+Level	$08	2	Level
+Page	$0A	2	Page
+Not used	$0C	1052	Not used
+IGPG-link	$40	12	Link to the In-Game User Interface Page
+Not used	$44	1028	Not used
Index: /oup/current/exe/StructDefs/ENVP.txt
===================================================================
--- /oup/current/exe/StructDefs/ENVP.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ENVP.txt	(revision 10)
@@ -0,0 +1,23 @@
+Environment Particle Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	208
+3D particle	$00	164	Reference to a BINA file of level 0
+Particle name	$40	10048	Name of the particle
+Unknown	$70	9	Unknown
+Unknown	$74	9	Unknown
+Unknown	$78	9	Unknown
+Unknown	$7C	9	Unknown
+Unknown	$80	9	Unknown
+Unknown	$84	9	Unknown
+Unknown	$88	9	Unknown
+Unknown	$8C	9	Unknown
+Unknown	$90	9	Unknown
+Unknown	$94	9	Unknown
+Unknown	$98	9	Unknown
+Unknown	$9C	9	Unknown
+Unknown	$A0	9	Unknown
+Unknown	$A4	9	Unknown
+Unknown	$A8	1040	Unknown; always the same
Index: /oup/current/exe/StructDefs/FILM.txt
===================================================================
--- /oup/current/exe/StructDefs/FILM.txt	(revision 10)
+++ /oup/current/exe/StructDefs/FILM.txt	(revision 10)
@@ -0,0 +1,25 @@
+Film
+File id	$00	12	File id
+Level id	$04	17	Level id
+x-coordinate	$08	9	x-coordinate of the start point
+y-coordinate	$0C	9	y-coordinate (height) of the start point
+z-coordinate	$10	9	z-coordinate of the start point
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
+Look left/right	$1C	9	Look from left or right to facing state
+Look up/down	$20	9	Look up or down
+Film lenght	$24	4	Lenght of the film in 1/60 seconds
+Unknown	$28	4	Unknown
+Unknown	$2C	4	Unknown
+Not used	$30	1012	Not used
+Packages	$3C	4	Amount of packages that follow
+*Package		$40	$3C	4	24
+Camera angle	$00	9	Camera angle in degrees (up / down)
+Character rotation	$04	9	Rotation of the charcter on the y-axis in degrees
+Unknown	$08	2	Unknown
+Movement	$0A	10	Movement bitset
+Unknown	$0B	1	Unknown
+Unknown	$0C	4	Unknown
+Frames to go	$10	4	Number of the frames to go
+Unknown	$14	2	Unknown
+Unknown	$16	2	Unknown
Index: /oup/current/exe/StructDefs/HPge.txt
===================================================================
--- /oup/current/exe/StructDefs/HPge.txt	(revision 10)
+++ /oup/current/exe/StructDefs/HPge.txt	(revision 10)
@@ -0,0 +1,6 @@
+Help Page
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1004	Not used
+IGPG-link	$0C	12	Link to the In-Game User Interface Page
+Not used	$10	1016	Not used
Index: /oup/current/exe/StructDefs/IDXA.txt
===================================================================
--- /oup/current/exe/StructDefs/IDXA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/IDXA.txt	(revision 10)
@@ -0,0 +1,8 @@
+Index Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+Index id	$00	3	Index id
+High bit	$03	1	High bit
Index: /oup/current/exe/StructDefs/IGHH.txt
===================================================================
--- /oup/current/exe/StructDefs/IGHH.txt	(revision 10)
+++ /oup/current/exe/StructDefs/IGHH.txt	(revision 10)
@@ -0,0 +1,15 @@
+IGUI (In-Game User Interface) HUD (Head-Up Display) Help
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1028	Not used
+TXMP-link	$24	12	Link to the left HUD image
+TXMP-link	$28	12	Link to the right HUD image
+Left image position	$2C	4	The left HUD image starts 55 pixel from the left screen border
+Right image position	$30	4	The right HUD image starts 42 pixel from the right screen border (65535 - 65493 = 42)
+Left words	$34	4	Number of words on the left side
+Right words	$38	4	Number of words on the right side
+Word-packages	$3C	4	Amount of word-packages that follow
+*Package		$40	$3C	4	68
+Text field	$00	10064	Text field (all entries after the fist 00 are useless)
+Text x-position	$40	2	x-position of the text (from the left/right border of the HUD image)
+Text y-position	$42	2	y-position of the text (from the top border of the HUD image)
Index: /oup/current/exe/StructDefs/IGPA.txt
===================================================================
--- /oup/current/exe/StructDefs/IGPA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/IGPA.txt	(revision 10)
@@ -0,0 +1,7 @@
+IGUI (In-Game User Interface) Page Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+IGPG-link	$00	12	Link to the In-Game User Interface Page
Index: /oup/current/exe/StructDefs/IGPG.txt
===================================================================
--- /oup/current/exe/StructDefs/IGPG.txt	(revision 10)
+++ /oup/current/exe/StructDefs/IGPG.txt	(revision 10)
@@ -0,0 +1,15 @@
+IGUI (In-Game User Interface) Page
+File id	$00	12	File id
+Level id	$04	17	Level id
+TSFF-link	$08	12	Link to the Font Family
+Font option	$0C	4	Font option
+Font color B	$10	1	Font color - blue part
+Font color G	$11	1	Font color - green part
+Font color R	$12	1	Font color - red part
+Unknown	$13	1	Unknown
+Font size	$14	2	Font size of the text; maybe the minimal font size in connection to the screen resolution
+Enabler	$16	2	Enables the previous entries; it's a bitset
+PSpc-link	$18	12	Link to the Part Specification
+IGSA-link	$1C	12	Link to the In-Game User Interface String Array
+IGSA-link	$20	12	Link to the In-Game User Interface String Array
+Not used	$24	1028	Not used
Index: /oup/current/exe/StructDefs/IGSA.txt
===================================================================
--- /oup/current/exe/StructDefs/IGSA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/IGSA.txt	(revision 10)
@@ -0,0 +1,7 @@
+IGUI (In-Game User Interface) String Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+IGSt-link	$00	12	Link to the In-Game User Interface String
Index: /oup/current/exe/StructDefs/IGSt.txt
===================================================================
--- /oup/current/exe/StructDefs/IGSt.txt	(revision 10)
+++ /oup/current/exe/StructDefs/IGSt.txt	(revision 10)
@@ -0,0 +1,13 @@
+IGUI (In-Game User Interface) String
+File id	$00	12	File id
+Level id	$04	17	Level id
+TSFF-link	$08	12	Link to the Font Family
+Font option	$0C	4	Font option
+Font color B	$10	1	Font color - blue part
+Font color G	$11	1	Font color - green part
+Font color R	$12	1	Font color - red part
+Unknown	$13	1	Unknown
+Font size	$14	2	Font size of the text
+Enabler	$16	2	Enables the previous entries; it's a bitset
+Text	$18	10384	Space for text
+Not used	$198	1008	Not used
Index: /oup/current/exe/StructDefs/IPge.txt
===================================================================
--- /oup/current/exe/StructDefs/IPge.txt	(revision 10)
+++ /oup/current/exe/StructDefs/IPge.txt	(revision 10)
@@ -0,0 +1,6 @@
+Item Page
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	4	Unknown
+Impt-link	$0C	12	Link to the In-Game User Interface Page
+Not used	$10	1016	Not used
Index: /oup/current/exe/StructDefs/Impt.txt
===================================================================
--- /oup/current/exe/StructDefs/Impt.txt	(revision 10)
+++ /oup/current/exe/StructDefs/Impt.txt	(revision 10)
@@ -0,0 +1,7 @@
+Impact Tree
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	14	Unknown
+Not used	$0A	1006	Not used
+Impt-link	$10	12	Link to the next higher Impact Tree
+Not used	$14	1012	Not used
Index: /oup/current/exe/StructDefs/KeyI.txt
===================================================================
--- /oup/current/exe/StructDefs/KeyI.txt	(revision 10)
+++ /oup/current/exe/StructDefs/KeyI.txt	(revision 10)
@@ -0,0 +1,14 @@
+Key Icons
+File id	$00	12	File id
+Level id	$04	17	Level id
+TXMP-link	$08	12	Link to the punch texture
+TXMP-link	$0C	12	Link to the kick texture
+TXMP-link	$10	12	Link to the forward texture
+TXMP-link	$14	12	Link to the backward texture
+TXMP-link	$18	12	Link to the left texture
+TXMP-link	$1C	12	Link to the right texture
+TXMP-link	$20	12	Link to the crouch texture
+TXMP-link	$24	12	Link to the jump texture
+TXMP-link	$28	12	Link to the hold texture
+TXMP-link	$2C	12	Link to the plus texture
+Not used	$30	1016	Not used
Index: /oup/current/exe/StructDefs/M3GA.txt
===================================================================
--- /oup/current/exe/StructDefs/M3GA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/M3GA.txt	(revision 10)
@@ -0,0 +1,7 @@
+Geometry Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+M3GM-link	$00	12	Link to the Geometry
Index: /oup/current/exe/StructDefs/M3GM.txt
===================================================================
--- /oup/current/exe/StructDefs/M3GM.txt	(revision 10)
+++ /oup/current/exe/StructDefs/M3GM.txt	(revision 10)
@@ -0,0 +1,13 @@
+Geometry
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	4	Unknown; not used
+PNTA-link	$0C	12	Link to the 3D Point Array
+VCRA-link	$10	12	Link to the 3D Vector Array
+VCRA-link	$14	12	Link to the 3D Vector Array
+TXCA-link	$18	12	Link to the Texture Coordinate Array
+IDXA-link	$1C	12	Link to the Index Array
+IDXA-link	$20	12	Link to the Index Array
+TXMP-link	$24	12	Link to the Texture
+Unknown	$28	4	Unknown; not used
+Not used	$2C	1020	Not used
Index: /oup/current/exe/StructDefs/Mtrl.txt
===================================================================
--- /oup/current/exe/StructDefs/Mtrl.txt	(revision 10)
+++ /oup/current/exe/StructDefs/Mtrl.txt	(revision 10)
@@ -0,0 +1,7 @@
+Material
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	14	Unknown
+Not used	$0A	1006	Not used
+Mtrl-link	$10	12	Link to the next higher Material
+Not used	$14	1012	Not used
Index: /oup/current/exe/StructDefs/OBAN.txt
===================================================================
--- /oup/current/exe/StructDefs/OBAN.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OBAN.txt	(revision 10)
@@ -0,0 +1,44 @@
+Object Animation
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	4	Unknown
+Unknown	$0C	4	Unknown
+Unknown	$10	4	Unknown
+Unknown	$14	4	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown
+Unknown	$20	9	Unknown
+Unknown	$24	9	Unknown
+Unknown	$28	9	Unknown
+Unknown	$2C	9	Unknown
+Unknown	$30	9	Unknown
+Unknown	$34	9	Unknown
+Unknown	$38	9	Unknown
+x-position	$3C	9	x-position of the start point
+y-position	$40	9	y-position (height) of the start point
+z-position	$44	9	z-position of the start point
+Unknown	$48	9	Unknown
+Unknown	$4C	9	Unknown
+Unknown	$50	9	Unknown
+Unknown	$54	9	Unknown
+Unknown	$58	9	Unknown
+Unknown	$5C	9	Unknown
+Unknown	$60	9	Unknown
+Unknown	$64	9	Unknown
+Unknown	$68	9	Unknown
+Unknown	$6C	9	Unknown
+Unknown	$70	9	Unknown
+Unknown	$74	9	Unknown
+Frames	$78	2	Number of frames
+Animation time	$7A	2	Animation time in 1/60 seconds
+Unknown	$7C	2	Unknown
+Packages	$7E	2	Amount of packages that follow
+*Package		$80	$7E	2	32
+Unknown	$00	9	Unknown
+Unknown	$04	9	Unknown
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+x-position	$10	9	x-position
+y-position	$14	9	y-position
+z-position	$18	9	z-position
+Passed time	$1C	4	Passed time in 1/60 seconds
Index: /oup/current/exe/StructDefs/OBDC.txt
===================================================================
--- /oup/current/exe/StructDefs/OBDC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OBDC.txt	(revision 10)
@@ -0,0 +1,12 @@
+Door Class Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	24
+Unknown	$00	4	Unknown
+OBAN-link	$04	12	Link to the Object Animation
+Unknown	$08	4	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	4	Unknown
+Unknown	$14	4	Unknown
Index: /oup/current/exe/StructDefs/OBOA.txt
===================================================================
--- /oup/current/exe/StructDefs/OBOA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OBOA.txt	(revision 10)
@@ -0,0 +1,36 @@
+Starting Object Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	240
+M3GA-link	$00	12	Link to the Geometry Array
+OBAN-link	$04	12	Link to the Object Animation
+ENVP-link	$08	12	Link to the Environment Particle Array
+Unknown	$0C	4	Unknown
+Unknown	$10	4	Unknown
+Unknown	$14	4	Unknown
+Unknown	$18	4	Unknown
+Unknown	$1C	4	Unknown
+Unknown	$20	9	Unknown
+Unknown	$24	9	Unknown
+Unknown	$28	9	Unknown
+Unknown	$2C	9	Unknown
+Unknown	$30	9	Unknown
+Unknown	$34	9	Unknown
+Unknown	$38	9	Unknown
+Unknown	$3C	9	Unknown
+Unknown	$40	9	Unknown
+Unknown	$44	9	Unknown
+Unknown	$48	9	Unknown
+Unknown	$4C	9	Unknown
+Unknown	$50	9	Unknown
+Unknown	$54	9	Unknown
+Unknown	$58	9	Unknown
+Unknown	$5C	9	Unknown
+Unknown	$60	9	Unknown
+Unknown	$64	9	Unknown
+Unknown	$68	9	Unknown
+Unknown	$6C	9	Unknown
+Name	$70	10064	Name of the object
+Unknown	$B0	10064	Unknown; maybe an old development relict
Index: /oup/current/exe/StructDefs/OFGA.txt
===================================================================
--- /oup/current/exe/StructDefs/OFGA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OFGA.txt	(revision 10)
@@ -0,0 +1,10 @@
+Object Furniture Geometry Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	12
+Unknown	$00	2	Unknown
+Unknown	$02	2	Unknown
+M3GM-link	$04	12	Link to the Geometry
+Unknown	$08	4	Unknown
Index: /oup/current/exe/StructDefs/ONCC.txt
===================================================================
--- /oup/current/exe/StructDefs/ONCC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONCC.txt	(revision 10)
@@ -0,0 +1,277 @@
+Oni character class
+File id	$00	12	File id
+Level id	$04	17	Level id
+TXMP-link	$28	12	Shadow texture
+Shadow height 5 	$2C	9	Height, where the shadow fades out completely
+Shadow height 4	$30	9	Height, where the diameter of the shadow decreases and the shadow fades out half
+Shadow height 3	$34	9	Height, where the diameter of the shadow decreases
+Shadow height 2	$38	9	Height, where the diameter of the shadow decreases
+Shadow height 1	$3C	9	Height, where the diameter of the shadow decreases
+Shadow option 1	$40	2	Transparency of the shadow for the first part of a jump
+Shadow option 2	$42	2	Transparency of the shadow for the second part of a jump
+Regeneration time	$64	2	Regeneration time of one health point in 1/60 seconds if you use a hypo
+Hurt light sound	$98	132	Reference to an OSBD file of level 0
+Hurt medium sound	$B8	132	Reference to an OSBD file of level 0
+Hurt heavy sound	$D8	132	Reference to an OSBD file of level 0
+Death sound	$F8	132	Reference to an OSBD file of level 0
+Rotation factor	$12C	9	Rotation factor * 360 degrees = possible rotation per frame or animation
+Taunt sound query	$2B0	1	0 = not used; 100 = used
+Alert sound query	$2B1	1	0 = not used; 100 = used
+Startle sound query	$2B2	1	0 = not used; 100 = used
+Check body sound query	$2B3	1	0 = not used; 100 = used
+Pursue sound query	$2B4	1	0 = not used; 100 = used
+Cower sound query	$2B5	1	0 = not used; 100 = used
+Punch heavy sound query	$2B6	1	0 = not used; 100 = used
+Kich heavy sound query	$2B7	1	0 = not used; 100 = used
+Super3 sound query	$2B8	1	0 = not used; 100 = used
+Super4 sound query	$2B9	1	0 = not used; 100 = used
+Taunt sound	$2BC	132	Reference to a SNDD file of level 0
+Alert sound	$2DC	132	Reference to a SNDD file of level 0
+Startle sound	$2FC	132	Reference to a SNDD file of level 0
+Check body sound	$31C	132	Reference to a SNDD file of level 0
+Pursue sound	$33C	132	Reference to a SNDD file of level 0
+Cower sound	$35C	132	Reference to a SNDD file of level 0
+Punch heavy sound	$37C	132	Reference to a SNDD file of level 0
+Kick heavy sound	$39C	132	Reference to a SNDD file of level 0
+Super3 sound	$3BC	132	Reference to a SNDD file of level 0
+Super4 sound	$3DC	132	Reference to a SNDD file of level 0
+Eyeshot	$3FC	9	The max. distance where the AI can see you
+Earshot	$400	9	The max. distance where the AI can hear you
+ONCV-link	$434	12	Character varient link
+ONCP-link	$438	12	Character particle array link; useless?
+ONIA-link	$43C	12	Character impact array link; useless?
+Footstep walk impact	$454	230	Reference to an Impt file of level 0
+Footstep run impact	$4D6	230	Reference to an Impt file of level 0
+Footstep crouch impact	$558	230	Reference to an Impt file of level 0
+Fall slide impact	$5DA	230	Reference to an Impt file of level 0
+Fall land impact	$65C	230	Reference to an Impt file of level 0
+Fall land hard impact	$6DE	230	Reference to an Impt file of level 0
+Fall knockdown impact	$760	230	Reference to an Impt file of level 0
+Fall knockdown impact	$7E2	230	Reference to an Impt file of level 0
+Fall knockdown impact	$864	230	Reference to an Impt file of level 0
+Footstep turn impact	$8E6	230	Reference to an Impt file of level 0
+Footstep run start impact	$968	230	Reference to an Impt file of level 0
+Footstep single step impact	$9EA	230	Reference to an Impt file of level 0
+Footstep run stop impact	$A6C	230	Reference to an Impt file of level 0
+Footstep walk stop impact	$AEE	230	Reference to an Impt file of level 0
+Footstep run sprint impact	$B70	230	Reference to an Impt file of level 0
+Special death particles	$BF4	164	Reference to a 3Dparticle.BINA file of level 0; only the mad bomber use it
+TRBS-link	$C3C	12	Body set link
+TRMA-link	$C40	12	Texture map array link
+CBPM-link	$C44	12	Body part material link
+CBPI-link	$C48	12	Body part impact link
+Peace timer	$C4C	4	Peace timer in 1/60 seconds; after that time the character switches back from fight to peace mode
+First idle timer	$C50	4	First idle timer in 1/60 seconds; after that time Oni plays a special idle animation
+Second idle timer	$C54	4	Second idle timer in 1/60 seconds; after that time Oni plays a special idle animation
+Basic health	$C58	4	Extra health informations are stored in the Character.BINA files
+Basic health	$C5C	4	Unknown; always the same
+Minimal body size factor	$C60	9	Minimal body size factor
+Maximal body size factor	$C64	9	Maximal body size factor
+TRAC-link	$C88	8	Animation collection link
+TRSC-link	$C8C	8	Screen (aiming) collection link
+
+*Unknown
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	2	Unknown
+Unknown	$1E	2	Unknown
+Unknown	$20	9	Unknown
+Unknown	$24	9	Unknown
+Unknown	$44	9	Unknown; always the same
+Unknown	$48	1	Unknown
+Unknown	$49	1	Unknown; always the same
+Unknown	$4C	9	Unknown; always the same
+Unknown	$50	9	Unknown; always the same
+Unknown	$54	9	Unknown; always the same
+Unknown	$58	9	Unknown; always the same
+Unknown	$5C	9	Unknown; always the same
+Unknown	$60	9	Unknown; always the same
+Unknown	$68	9	Unknown; always the same
+Unknown	$6C	9	Unknown; always the same
+Unknown	$70	9	Unknown; always the same
+Unknown	$74	9	Unknown; always the same
+Unknown	$78	9	Unknown; always the same
+Unknown	$7C	2	Unknown; always the same
+Unknown	$7E	2	Unknown; always the same
+Unknown	$80	2	Unknown; always the same
+Unknown	$82	2	Unknown; always the same
+Unknown	$84	2	Unknown; always the same
+Unknown	$86	2	Unknown; always the same
+Unknown	$88	2	Unknown; always the same
+Unknown	$8A	2	Unknown; always the same
+Unknown	$8C	2	Unknown; always the same
+Unknown	$8E	2	Unknown; always the same
+Unknown	$90	2	Unknown; always the same
+Unknown	$92	1	Unknown; always the same
+Unknown	$94	9	Unknown; always the same
+Unknown	$118	4	Unknown; always the same
+Unknown	$11C	4	Unknown; always the same
+Unknown	$120	4	Unknown; always the same
+Unknown	$124	4	Unknown; always the same
+Unknown	$128	4	Unknown
+Unknown	$130	2	Unknown
+Unknown	$132	2	Unknown
+Unknown	$134	4	Unknown
+Unknown	$138	9	Unknown
+Unknown	$13C	9	Unknown
+Unknown	$140	9	Unknown; always the same
+Unknown	$144	9	Unknown; always the same
+Unknown	$148	9	Unknown; always the same
+Unknown	$14C	4	Unknown
+Unknown	$150	4	Unknown
+Unknown	$154	4	Unknown
+Unknown	$158	4	Unknown
+Unknown	$404	9	Unknown
+Unknown	$408	9	Unknown
+Unknown	$40C	9	Unknown
+Unknown	$410	9	Unknown; always the same
+Unknown	$414	9	Unknown; always the same
+Unknown	$418	4	Unknown; always the same
+Unknown	$41C	4	Unknown; always the same
+Unknown	$420	4	Unknown; always the same
+Unknown	$424	4	Unknown; always the same
+Unknown	$428	4	Unknown; always the same
+Unknown	$42C	4	Unknown; always the same
+Unknown	$430	9	Unknown; always the same
+Unknown	$294	4	Unknown; always the same
+Unknown	$298	4	Unknown; always the same
+Unknown	$29C	4	Unknown; always the same
+Unknown	$2A0	4	Unknown; always the same
+Unknown	$2A4	4	Unknown
+Unknown	$2A8	4	Unknown
+Unknown	$2AC	2	Unknown
+Unknown	$2AE	2	Unknown
+Unknown	$440	4	Unknown; maybe a canceled link; always the same
+Unknown	$444	10016	Maybe the weight of the character?
+Unknown	$BF2	2	Unknown; always the same; maybe only a filler
+Unknown	$C34	4	Unknown; maybe a canceled link; always the same
+Unknown	$C38	4	Unknown; maybe a canceled link; always the same
+Unknown	$C68	9	Unknown; always the same
+Unknown	$C6C	9	Unknown; always the same
+Unknown	$C70	9	Unknown
+Unknown	$C74	9	Unknown
+Unknown	$C78	9	Unknown; always the same
+Unknown	$C7C	9	Unknown; always the same
+Unknown	$C80	9	Unknown; always the same
+Unknown	$C84	9	Unknown
+Unknown	$C90	2	Unknown; always the same
+Unknown	$C92	2	Unknown; only the mad bomber use it
+Unknown	$C94	1	Unknown
+Unknown	$C95	1	Unknown
+Unknown	$C96	1	Unknown
+Unknown	$C97	1	Unknown
+
+*Unused
+Not used	$4A	1002	Not used
+Not used	$66	1002	Not used
+Not used	$93	1001	Not used
+Not useed	$C98	1008	Not used
+
+
+*Unknown Block1
+Block 1 - Unknown	$15C	9	Unknown
+Block 1 - Unknown	$160	9	Unknown
+Block 1 - Unknown	$164	9	Unknown; always the same
+Block 1 - Unknown	$168	9	Unknown
+Block 1 - Unknown	$16C	9	Unknown
+Block 1 - Unknown	$170	2	Unknown; always the same
+Block 1 - Unknown	$172	2	Unknown; always the same
+*Unknown Block2
+Block 2 - Unknown	$174	9	Unknown
+Block 2 - Unknown	$178	9	Unknown
+Block 2 - Unknown	$17C	9	Unknown
+Block 2 - Unknown	$180	9	Unknown
+Block 2 - Unknown	$184	9	Unknown
+Block 2 - Unknown	$188	2	Unknown; always the same
+Block 2 - Unknown	$18A	2	Unknown; always the same
+*Unknown Block3
+Block 3 - Unknown	$18C	9	Unknown
+Block 3 - Unknown	$190	9	Unknown
+Block 3 - Unknown	$194	9	Unknown; always the same
+Block 3 - Unknown	$198	9	Unknown
+Block 3 - Unknown	$19C	9	Unknown
+Block 3 - Unknown	$1A0	2	Unknown; always the same
+Block 3 - Unknown	$1A2	2	Unknown; always the same
+*Unknown Block4
+Block 4 - Unknown	$1A4	9	Unknown
+Block 4 - Unknown	$1A8	9	Unknown
+Block 4 - Unknown	$1AC	9	Unknown; always the same
+Block 4 - Unknown	$1B0	9	Unknown
+Block 4 - Unknown	$1B4	9	Unknown
+Block 4 - Unknown	$1B8	2	Unknown
+Block 4 - Unknown	$1BA	2	Unknown
+*Unknown Block5
+Block 5 - Unknown	$1BC	9	Unknown; always the same
+Block 5 - Unknown	$1C0	9	Unknown
+Block 5 - Unknown	$1C4	9	Unknown
+Block 5 - Unknown	$1C8	9	Unknown
+Block 5 - Unknown	$1CC	9	Unknown
+Block 5 - Unknown	$1D0	2	Unknown
+Block 5 - Unknown	$1D2	2	Unknown
+*Unknown Block6
+Block 6 - Unknown	$1D4	9	Unknown
+Block 6 - Unknown	$1D8	9	Unknown
+Block 6 - Unknown	$1DC	9	Unknown
+Block 6 - Unknown	$1E0	9	Unknown
+Block 6 - Unknown	$1E4	9	Unknown
+Block 6 - Unknown	$1E8	2	Unknown
+Block 6 - Unknown	$1EA	2	Unknown
+*Unknown Block7
+Block 7 - Unknown	$1EC	9	Unknown; always the same
+Block 7 - Unknown	$1F0	9	Unknown
+Block 7 - Unknown	$1F4	9	Unknown
+Block 7 - Unknown	$1F8	9	Unknown
+Block 7 - Unknown	$1FC	9	Unknown; always the same
+Block 7 - Unknown	$200	2	Unknown; always the same
+Block 7 - Unknown	$202	2	Unknown; always the same
+*Unknown Block8
+Block 8 - Unknown	$204	9	Unknown
+Block 8 - Unknown	$208	9	Unknown
+Block 8 - Unknown	$20C	9	Unknown
+Block 8 - Unknown	$210	9	Unknown; always the same
+Block 8 - Unknown	$214	9	Unknown
+Block 8 - Unknown	$218	2	Unknown
+Block 8 - Unknown	$21A	2	Unknown
+*Unknown Block9
+Block 9 - Unknown	$21C	9	Unknown
+Block 9 - Unknown	$220	9	Unknown
+Block 9 - Unknown	$224	9	Unknown
+Block 9 - Unknown	$228	9	Unknown
+Block 9 - Unknown	$22C	9	Unknown
+Block 9 - Unknown	$230	2	Unknown
+Block 9 - Unknown	$232	2	Unknown
+*Unknown Block10
+Block 10 - Unknown	$234	9	Unknown
+Block 10 - Unknown	$238	9	Unknown
+Block 10 - Unknown	$23C	9	Unknown
+Block 10 - Unknown	$240	9	Unknown
+Block 10 - Unknown	$244	9	Unknown
+Block 10 - Unknown	$248	2	Unknown
+Block 10 - Unknown	$24A	2	Unknown
+*Unknown Block11
+Block 11 - Unknown	$24C	9	Unknown
+Block 11 - Unknown	$250	9	Unknown
+Block 11 - Unknown	$254	9	Unknown; always the same
+Block 11 - Unknown	$258	9	Unknown
+Block 11 - Unknown	$25C	9	Unknown; always the same
+Block 11 - Unknown	$260	2	Unknown; always the same
+Block 11 - Unknown	$262	2	Unknown; always the same
+*Unknown Block12
+Block 12 - Unknown	$264	9	Unknown
+Block 12 - Unknown	$268	9	Unknown
+Block 12 - Unknown	$26C	9	Unknown; always the same
+Block 12 - Unknown	$270	9	Unknown
+Block 12 - Unknown	$274	9	Unknown; always the same
+Block 12 - Unknown	$278	2	Unknown; always the same
+Block 12 - Unknown	$27A	2	Unknown; always the same
+*Unknown Block13
+Block 13 - Unknown	$27C	9	Unknown
+Block 13 - Unknown	$280	9	Unknown
+Block 13 - Unknown	$284	9	Unknown; always the same
+Block 13 - Unknown	$288	9	Unknown
+Block 13 - Unknown	$28C	9	Unknown; always the same
+Block 13 - Unknown	$290	2	Unknown; always the same
+Block 13 - Unknown	$292	2	Unknown; always the same
Index: /oup/current/exe/StructDefs/ONCC_2.txt
===================================================================
--- /oup/current/exe/StructDefs/ONCC_2.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONCC_2.txt	(revision 10)
@@ -0,0 +1,258 @@
+Oni Character Class
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	9	Unknown; always the same; maybe downwards velocity?
+Downward acceleration	$0C	9	Downward gravity acceleration
+Starting velocity	$10	9	Starting velocity for a simple (tap) JUMP
+Limit velocity	$14	9	Limit velocity for jumping and gravity flight 
+Upward acceleration	$18	9	Upward acceleration (jetpack) if you hold JUMP
+Unknown	$1C	2	Unknown; always the same; maybe a gravity timer?
+Jetpack timer	$1E	2	Jetpack timer; time during which you can use the jetpack
+Height no damage	$20	9	Maximal falling height without damage 
+Height damage	$24	9	Maximal falling height with damage
+TXMP-link	$28	12	Link to the shadow texture
+Shadow height 5 	$2C	9	Height, where the shadow fades out completely
+Shadow height 4	$30	9	Height, where the diameter of the shadow decreases and the shadow fades out half
+Shadow height 3	$34	9	Height, where the diameter of the shadow decreases
+Shadow height 2	$38	9	Height, where the diameter of the shadow decreases
+Shadow height 1	$3C	9	Height, where the diameter of the shadow decreases
+Shadow option 1	$40	2	Transparency of the shadow for the first part of a jump
+Shadow option 2	$42	2	Transparency of the shadow for the second part of a jump
+Unknown	$44	9	Unknown; always the same
+Unknown	$48	1	Unknown
+Unknown	$49	1	Unknown; always the same
+Not used	$4A	1002	Not used
+Unknown	$4C	9	Unknown; always the same
+Unknown	$50	9	Unknown; always the same
+Unknown	$54	9	Unknown; always the same
+Unknown	$58	9	Unknown; always the same
+Unknown	$5C	9	Unknown; always the same
+Unknown	$60	9	Unknown; always the same
+Regeneration time	$64	2	Regeneration time of one health point in 1/60 seconds if you use a hypo
+Not used	$66	1002	Not used
+Unknown	$68	9	Unknown; always the same
+Unknown	$6C	9	Unknown; always the same
+Unknown	$70	9	Unknown; always the same
+Unknown	$74	9	Unknown; always the same
+Unknown	$78	9	Unknown; always the same
+Unknown	$7C	2	Unknown; always the same
+Unknown	$7E	2	Unknown; always the same
+Unknown	$80	2	Unknown; always the same
+Unknown	$82	2	Unknown; always the same
+Unknown	$84	2	Unknown; always the same
+Unknown	$86	2	Unknown; always the same
+Unknown	$88	2	Unknown; always the same
+Unknown	$8A	2	Unknown; always the same
+Unknown	$8C	2	Unknown; always the same
+Unknown	$8E	2	Unknown; always the same
+Unknown	$90	2	Unknown; always the same
+Unknown	$92	1	Unknown; always the same
+Not used	$93	1001	Not used
+Unknown	$94	9	Unknown; always the same
+Hurt light sound	$98	132	Reference to an OSBD file of level 0
+Hurt medium sound	$B8	132	Reference to an OSBD file of level 0
+Hurt heavy sound	$D8	132	Reference to an OSBD file of level 0
+Death sound	$F8	132	Reference to an OSBD file of level 0
+Unknown	$118	4	Unknown; always the same
+Unknown	$11C	4	Unknown; always the same
+Unknown	$120	4	Unknown; always the same
+Unknown	$124	4	Unknown; always the same
+Unknown	$128	4	Unknown
+Rotation factor	$12C	9	Rotation factor * 360 degrees = possible rotation per frame or animation
+Unknown	$130	2	Unknown
+Unknown	$132	2	Unknown
+Unknown	$134	4	Unknown
+Unknown	$138	9	Unknown
+Unknown	$13C	9	Unknown
+Unknown	$140	9	Unknown; always the same
+Unknown	$144	9	Unknown; always the same
+Unknown	$148	9	Unknown; always the same
+Unknown	$14C	4	Unknown
+Unknown	$150	4	Unknown
+Unknown	$154	4	Unknown
+Unknown	$158	4	Unknown
+w0_sec - recoil	$15C	9	recoil compensation amount (0 = min, 1 = max)
+w0_sec - best angle	$160	9	best aiming angle in radians
+w0_sec - error	$164	9	shot grouping error
+w0_sec - decay	$168	9	shot grouping decay
+w0_sec - inaccuracy	$16C	9	shooting inaccuracy multiplier
+w0_sec - minimum delay	$170	2	minimum delay between shots in frames
+w0_sec - maximum delay	$172	2	maximum delay between shots in frames
+w1_tap - recoil	$174	9	recoil compensation amount (0 = min, 1 = max)
+w1_tap - best angle	$178	9	best aiming angle in radians
+w1_tap - error	$17C	9	shot grouping error
+w1_tap - decay	$180	9	shot grouping decay
+w1_tap - inaccuracy	$184	9	shooting inaccuracy multiplier
+w1_tap - minimum delay	$188	2	minimum delay between shots in frames
+w1_tap - maximum delay	$18A	2	maximum delay between shots in frames
+w2_sap - recoil	$18C	9	recoil compensation amount (0 = min, 1 = max)
+w2_sap - best angle	$190	9	best aiming angle in radians
+w2_sap - error	$194	9	shot grouping error
+w2_sap - decay	$198	9	shot grouping decay
+w2_sap - inaccuracy	$19C	9	shooting inaccuracy multiplier
+w2_sap - minimum delay	$1A0	2	minimum delay between shots in frames
+w2_sap - maximum delay	$1A2	2	maximum delay between shots in frames
+w3_phr - recoil	$1A4	9	recoil compensation amount (0 = min, 1 = max)
+w3_phr - best angle	$1A8	9	best aiming angle in radians
+w3_phr - error	$1AC	9	shot grouping error
+w3_phr - decay	$1B0	9	shot grouping decay
+w3_phr - inaccuracy	$1B4	9	shooting inaccuracy multiplier
+w3_phr - minimum delay	$1B8	2	minimum delay between shots in frames
+w3_phr - maximum delay	$1BA	2	maximum delay between shots in frames
+w4_psm - recoil	$1BC	9	recoil compensation amount (0 = min, 1 = max)
+w4_psm - best angle	$1C0	9	best aiming angle in radians
+w4_psm - error	$1C4	9	shot grouping error
+w4_psm - decay	$1C8	9	shot grouping decay
+w4_psm - inaccuracy	$1CC	9	shooting inaccuracy multiplier
+w4_psm - minimum delay	$1D0	2	minimum delay between shots in frames
+w4_psm - maximum delay	$1D2	2	maximum delay between shots in frames
+w5_sbg - recoil	$1D4	9	recoil compensation amount (0 = min, 1 = max)
+w5_sbg - best angle	$1D8	9	best aiming angle in radians
+w5_sbg - error	$1DC	9	shot grouping error
+w5_sbg - decay	$1E0	9	shot grouping decay
+w5_sbg - inaccuracy	$1E4	9	shooting inaccuracy multiplier
+w5_sbg - minimum delay	$1E8	2	minimum delay between shots in frames
+w5_sbg - maximum delay	$1EA	2	maximum delay between shots in frames
+w6_vdg - recoil	$1EC	9	recoil compensation amount (0 = min, 1 = max)
+w6_vdg - best angle	$1F0	9	best aiming angle in radians
+w6_vdg - error	$1F4	9	shot grouping error
+w6_vdg - decay	$1F8	9	shot grouping decay
+w6_vdg - inaccuracy	$1FC	9	shooting inaccuracy multiplier
+w6_vdg - minimum delay	$200	2	minimum delay between shots in frames
+w6_vdg - maximum delay	$202	2	maximum delay between shots in frames
+w7_scc - recoil	$204	9	recoil compensation amount (0 = min, 1 = max)
+w7_scc - best angle	$208	9	best aiming angle in radians
+w7_scc - error	$20C	9	shot grouping error
+w7_scc - decay	$210	9	shot grouping decay
+w7_scc - inaccuracy	$214	9	shooting inaccuracy multiplier
+w7_scc - minimum delay	$218	2	minimum delay between shots in frames
+w7_scc - maximum delay	$21A	2	maximum delay between shots in frames
+w8_mbo - recoil	$21C	9	recoil compensation amount (0 = min, 1 = max)
+w8_mbo - best angle	$220	9	best aiming angle in radians
+w8_mbo - error	$224	9	shot grouping error
+w8_mbo - decay	$228	9	shot grouping decay
+w8_mbo - inaccuracy	$22C	9	shooting inaccuracy multiplier
+w8_mbo - minimum delay	$230	2	minimum delay between shots in frames
+w8_mbo - maximum delay	$232	2	maximum delay between shots in frames
+w9_scr - recoil	$234	9	recoil compensation amount (0 = min, 1 = max)
+w9_scr - best angle	$238	9	best aiming angle in radians
+w9_scr - error	$23C	9	shot grouping error
+w9_scr - decay	$240	9	shot grouping decay
+w9_scr - inaccuracy	$244	9	shooting inaccuracy multiplier
+w9_scr - minimum delay	$248	2	minimum delay between shots in frames
+w9_scr - maximum delay	$24A	2	maximum delay between shots in frames
+w10_sni - recoil	$24C	9	recoil compensation amount (0 = min, 1 = max)
+w10_sni - best angle	$250	9	best aiming angle in radians
+w10_sni - error	$254	9	shot grouping error
+w10_sni - decay	$258	9	shot grouping decay
+w10_sni - inaccuracy	$25C	9	shooting inaccuracy multiplier
+w10_sni - minimum delay	$260	2	minimum delay between shots in frames
+w10_sni - maximum delay	$262	2	maximum delay between shots in frames
+w11_ba1 - recoil	$264	9	recoil compensation amount (0 = min, 1 = max)
+w11_ba1 - best angle	$268	9	best aiming angle in radians
+w11_ba1 - error	$26C	9	shot grouping error
+w11_ba1 - decay	$270	9	shot grouping decay
+w11_ba1 - inaccuracy	$274	9	shooting inaccuracy multiplier
+w11_ba1 - minimum delay	$278	2	minimum delay between shots in frames
+w11_ba1 - maximum delay	$27A	2	maximum delay between shots in frames
+w12_ba2 - recoil	$27C	9	recoil compensation amount (0 = min, 1 = max)
+w12_ba2 - best angle	$280	9	best aiming angle in radians
+w12_ba2 - error	$284	9	shot grouping error
+w12_ba2 - decay	$288	9	shot grouping decay
+w12_ba2 - inaccuracy	$28C	9	shooting inaccuracy multiplier
+w12_ba2 - minimum delay	$290	2	minimum delay between shots in frames
+w12_ba2 - maximum delay	$292	2	maximum delay between shots in frames
+Unknown	$294	4	Unknown; always the same
+Unknown	$298	4	Unknown; always the same
+Unknown	$29C	4	Unknown; always the same
+Unknown	$2A0	4	Unknown; always the same
+Unknown	$2A4	4	Unknown
+Unknown	$2A8	4	Unknown
+Unknown	$2AC	2	Unknown
+Unknown	$2AE	2	Unknown
+Taunt sound query	$2B0	1	0 = not used; 100 = used
+Alert sound query	$2B1	1	0 = not used; 100 = used
+Startle sound query	$2B2	1	0 = not used; 100 = used
+Check body sound query	$2B3	1	0 = not used; 100 = used
+Pursue sound query	$2B4	1	0 = not used; 100 = used
+Cower sound query	$2B5	1	0 = not used; 100 = used
+Punch heavy sound query	$2B6	1	0 = not used; 100 = used
+Kich heavy sound query	$2B7	1	0 = not used; 100 = used
+Super3 sound query	$2B8	1	0 = not used; 100 = used
+Super4 sound query	$2B9	1	0 = not used; 100 = used
+Taunt sound	$2BC	132	Reference to a SNDD file of level 0
+Alert sound	$2DC	132	Reference to a SNDD file of level 0
+Startle sound	$2FC	132	Reference to a SNDD file of level 0
+Check body sound	$31C	132	Reference to a SNDD file of level 0
+Pursue sound	$33C	132	Reference to a SNDD file of level 0
+Cower sound	$35C	132	Reference to a SNDD file of level 0
+Punch heavy sound	$37C	132	Reference to a SNDD file of level 0
+Kick heavy sound	$39C	132	Reference to a SNDD file of level 0
+Super3 sound	$3BC	132	Reference to a SNDD file of level 0
+Super4 sound	$3DC	132	Reference to a SNDD file of level 0
+Eyeshot	$3FC	9	The max. distance where the AI can see you
+Earshot	$400	9	The max. distance where the AI can hear you
+Unknown	$404	9	Unknown
+Unknown	$408	9	Unknown
+Unknown	$40C	9	Unknown
+Unknown	$410	9	Unknown; always the same
+Unknown	$414	9	Unknown; always the same
+Unknown	$418	4	Unknown; always the same
+Unknown	$41C	4	Unknown; always the same
+Unknown	$420	4	Unknown; always the same
+Unknown	$424	4	Unknown; always the same
+Unknown	$428	4	Unknown; always the same
+Unknown	$42C	4	Unknown; always the same
+Unknown	$430	9	Unknown; always the same
+ONCV-link	$434	12	Link to the Character Varient
+ONCP-link	$438	12	Link to the Character Particle Array
+ONIA-link	$43C	12	Link to the Character Impact Array
+Unknown	$440	4	Unknown; maybe a canceled link; always the same
+Unknown	$444	10016	Maybe the weight of the character?
+Footstep walk impact	$454	230	Reference to an Impt file of level 0
+Footstep run impact	$4D6	230	Reference to an Impt file of level 0
+Footstep crouch impact	$558	230	Reference to an Impt file of level 0
+Fall slide impact	$5DA	230	Reference to an Impt file of level 0
+Fall land impact	$65C	230	Reference to an Impt file of level 0
+Fall land hard impact	$6DE	230	Reference to an Impt file of level 0
+Fall knockdown impact	$760	230	Reference to an Impt file of level 0
+Fall knockdown impact	$7E2	230	Reference to an Impt file of level 0
+Fall knockdown impact	$864	230	Reference to an Impt file of level 0
+Footstep turn impact	$8E6	230	Reference to an Impt file of level 0
+Footstep run start impact	$968	230	Reference to an Impt file of level 0
+Footstep single step impact	$9EA	230	Reference to an Impt file of level 0
+Footstep run stop impact	$A6C	230	Reference to an Impt file of level 0
+Footstep walk stop impact	$AEE	230	Reference to an Impt file of level 0
+Footstep run sprint impact	$B70	230	Reference to an Impt file of level 0
+Unknown	$BF2	2	Unknown; always the same; maybe only a filler
+Special death particles	$BF4	164	Reference to a 3Dparticle.BINA file of level 0; only the mad bomber use it
+Unknown	$C34	4	Unknown; maybe a canceled link; always the same
+Unknown	$C38	4	Unknown; maybe a canceled link; always the same
+TRBS-link	$C3C	12	Link to the Body Set
+TRMA-link	$C40	12	Link to the Texture Map Array
+CBPM-link	$C44	12	Link to the Body Part Material
+CBPI-link	$C48	12	Link to the Body Part Impacts
+Peace timer	$C4C	4	Peace timer in 1/60 seconds; after that time the character switches back from fight to peace mode
+First idle timer	$C50	4	First idle timer in 1/60 seconds; after that time Oni plays a special idle animation
+Second idle timer	$C54	4	Second idle timer in 1/60 seconds; after that time Oni plays a special idle animation
+Basic health	$C58	4	Extra health informations are stored in the Character.BINA files
+Basic health	$C5C	4	Unknown; always the same
+Minimal body size factor	$C60	9	Minimal body size factor
+Maximal body size factor	$C64	9	Maximal body size factor
+Unknown	$C68	9	Unknown; always the same
+Unknown	$C6C	9	Unknown; always the same
+Unknown	$C70	9	Unknown
+Unknown	$C74	9	Unknown
+Unknown	$C78	9	Unknown; always the same
+Unknown	$C7C	9	Unknown; always the same
+Unknown	$C80	9	Unknown; always the same
+Unknown	$C84	9	Unknown
+TRAC-link	$C88	12	Link to the Animation Collection
+TRSC-link	$C8C	12	Link to the Screen (Aiming) Collection
+Unknown	$C90	2	Unknown; always the same
+Unknown	$C92	2	Unknown; only the mad bomber use it
+Unknown	$C94	1	Unknown
+Unknown	$C95	1	Unknown
+Unknown	$C96	1	Unknown
+Unknown	$C97	1	Unknown
+Not useed	$C98	1008	Not used
Index: /oup/current/exe/StructDefs/ONCP.txt
===================================================================
--- /oup/current/exe/StructDefs/ONCP.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONCP.txt	(revision 10)
@@ -0,0 +1,12 @@
+Oni Character Particle Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	88
+Particle name	$00	10016	Name of the particle (all entries after the first 00 are useless)
+Particle reference	$10	164	Reference to a BINA file of level 0
+Bodypart	$50	14	Particle is fixed to this bodypart
+Unknown	$52	2	Unknown
+Unknown	$54	4	Unknown
+
Index: /oup/current/exe/StructDefs/ONCV.txt
===================================================================
--- /oup/current/exe/StructDefs/ONCV.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONCV.txt	(revision 10)
@@ -0,0 +1,7 @@
+Oni Character Variant
+File id	$00	12	File id
+Level id	$04	17	Level id
+ONCV-link	$08	12	Link to the next higher Character Variant
+Basic character type	$0C	132	Basic character type
+Upgrade character type	$2C	132	Upgrade character type; used when you play on hard and the "upgrade difficulty" bit in the Character.BINA file is set
+Not used	$4C	1020	Not used
Index: /oup/current/exe/StructDefs/ONFA.txt
===================================================================
--- /oup/current/exe/StructDefs/ONFA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONFA.txt	(revision 10)
@@ -0,0 +1,25 @@
+Imported Flag Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages used	$1C	2	Amount of packages that follow
+Packages possible	$1E	2	Amount of packages that are possible
+*Package		$20	$1C	2	68
+Unknown	$00	9	Unknown
+Unknown	$04	9	Unknown
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown
+Unknown	$20	9	Unknown
+x-position	$24	9	x-position
+y-position	$28	9	y-position (height)
+z-position	$2C	9	z-position
+x-position again	$30	9	x-position again
+y-position again	$34	9	y-position (height) again
+z-position again	$38	9	z-position again
+Unknown	$3C	9	Unknown
+Flag node id	$40	2	Id of the flag node
+Unknown	$42	2	Unknown
Index: /oup/current/exe/StructDefs/ONGS.txt
===================================================================
--- /oup/current/exe/StructDefs/ONGS.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONGS.txt	(revision 10)
@@ -0,0 +1,93 @@
+Oni Game Settings
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	4	Unknown
+Unknown	$20	4	Unknown
+Unknown	$24	9	Unknown
+Unknown	$28	9	Unknown
+Unknown	$2C	9	Unknown
+Not used	$30	1048	Not used
+Unknown	$60	16	Unknown
+Unknown	$64	16	Unknown
+Unknown	$68	16	Unknown
+Unknown	$6C	16	Unknown
+Not used	$70	1048	Not used
+Ammo model reference	$A0	228	Reference to the ammo model
+Cell model reference	$120	228	Reference to the cell model
+Hypo model reference	$1A0	228	Reference to the hypo model
+Shield model reference	$220	228	Reference to the force shield model
+Invis model reference	$2A0	228	Reference to the phase cloak model
+Lsi model reference	$320	228	Reference to the lsi model
+Not used	$3A0	1128	Not used; maybe a canceled model reference
+Ammo texture reference	$420	228	Reference to the texture that surrounds the ammo
+Cell texture reference	$4A0	228	Reference to the texture that surrounds the cell
+Hypo texture reference	$520	228	Reference to the texture that surrounds the hypo
+Shield texture reference	$5A0	228	Reference to the texture that surrounds the force shield
+Invis texture reference	$620	228	Reference to the texture that surrounds the phase cloak
+Lsi texture reference	$6A0	228	Reference to the texture that surrounds the lsi
+Not used	$720	1128	Not used; maybe a canceled texture reference
+Unknown	$7A0	9	Unknown
+Unknown	$7A4	9	Unknown
+Unknown	$7A8	9	Unknown
+Unknown	$7AC	9	Unknown
+Unknown	$7B0	9	Unknown
+Unknown	$7B4	9	Unknown
+Unknown	$7B8	9	Unknown
+Unknown	$7BC	9	Unknown
+Unknown	$7C0	9	Unknown
+Unknown	$7C4	9	Unknown
+Unknown	$7C8	9	Unknown
+Unknown	$7CC	9	Unknown
+Not used	$7D0	1008	Not used
+Empty sound field	$7D8	132	Empty reference to an OSBD file
+Door fail sound	$7F8	132	Reference to the door_fail OSBD file
+Door lock sound	$818	132	Reference to the door_lock OSBD file
+Empty sound field	$838	132	Empty reference to an OSBD file
+Use hypo sound	$858	132	Reference to the use_hypo OSBD file
+Empty sound field	$878	132	Empty reference to an OSBD file
+Inventory fail sound	$898	132	Reference to the inventory_fail  OSBD file
+Receive ammo sound	$8B8	132	Reference to the receive_ammo OSBD file
+Receive cell sound	$8D8	132	Reference to the receive_cell OSBD file
+Receive hypo sound	$8F8	132	Reference to the receive_hypo OSBD file
+Receive lsi sound	$918	132	Reference to the receive_lsi OSBD file
+Compass sound	$938	132	Reference to the compass OSBD file
+Objective new sound	$958	132	Reference to the objective_new OSBD file
+Objective prompt sound	$978	132	Reference to the objective_prompt OSBD file
+Objective complete sound	$998	132	Reference to the objective_complete OSBD file
+Autosave sound	$9B8	132	Reference to the autosave OSBD file
+Empty sound field	$9D8	132	Empty reference to an OSBD file
+Empty sound field	$9F8	132	Empty reference to an OSBD file
+Health low sound	$A18	132	Reference to the health_low OSBD file
+Health over sound	$A38	132	Reference to the health_over OSBD file
+Shield sound	$A58	132	Reference to the shield  OSBD file
+Invis sound	$A78	132	Reference to the invisibility OSBD file
+Empty sound field	$A98	132	Empty reference to an OSBD file
+Unknown	$AB8	9	Unknown
+Unknown	$ABC	9	Unknown
+Unknown	$AC0	9	Unknown
+Unknown	$AC4	9	Unknown
+Unknown	$AC8	9	Unknown
+Unknown	$ACC	9	Unknown
+Unknown	$AD0	9	Unknown
+Unknown	$AD4	9	Unknown
+Unknown	$AD8	9	Unknown
+Unknown	$ADC	9	Unknown
+Unknown	$AE0	9	Unknown
+Unknown	$AE4	9	Unknown
+Unknown	$AE8	9	Unknown
+Unknown	$AEC	9	Unknown
+Unknown	$AF0	9	Unknown
+Unknown	$AF4	9	Unknown
+Unknown	$AF8	9	Unknown
+Unknown	$AFC	9	Unknown
+Packages	$B00	4	Amount of packages that follow
+*Package		$B04	$B00	4	68
+Item name	$00	10032	Name of the item
+First level	$20	2	First level with autoprompting
+Last level	$22	2	Last level with autoprompting
+Raw file anchor	$24	10032	Raw file anchor for the text message (it belongs to the SUBT file)
Index: /oup/current/exe/StructDefs/ONIA.txt
===================================================================
--- /oup/current/exe/StructDefs/ONIA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONIA.txt	(revision 10)
@@ -0,0 +1,11 @@
+Oni Character Impact Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	164
+Particle name	$00	10016	Name of the particle
+Impact reference	$10	228	Reference to an Impt file of level 0
+Sound reference	$90	116	Reference to an OSBD file of level 0
+Unknown	$A0	2	Unknown
+Unknown	$A2	2	Unknown
Index: /oup/current/exe/StructDefs/ONLD.txt
===================================================================
--- /oup/current/exe/StructDefs/ONLD.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONLD.txt	(revision 10)
@@ -0,0 +1,7 @@
+Oni Level Descriptor
+File id	$00	12	File id
+Level id	$04	17	Level id
+Current level	$08	2	Id of current level
+Next level	$0A	2	Id of the level that follows
+Level name	$0C	10064	Name of the level; you'll find it in the list, when you load a level
+Not used	$4C	1020	Not used
Index: /oup/current/exe/StructDefs/ONLV.txt
===================================================================
--- /oup/current/exe/StructDefs/ONLV.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONLV.txt	(revision 10)
@@ -0,0 +1,20 @@
+Oni Level Descriptor
+File id	$00	12	File id
+Level id	$04	17	Level id
+Level name	$08	10064	Name of the level
+AKEV-Link	$48	12	Link to the Environment
+OBOA-Link	$4C	12	Link to the Starting Object Array
+ONMA-Link	$50	12	Link to the Imported Marker Node Array
+ONFA-Link	$54	12	Link to the Imported Flag Node Array
+ONTA-Link	$58	12	Link to the Trigger Array
+ONSK-Link	$5C	12	Link to the Sky Class
+Unknown	$60	12	Unknown; maybe a canceled link; always the same
+AISA-Link	$64	12	Link to the AI Character Setup Array
+AITR-Link	$68	12	Link to the AI Script Trigger Array
+ONSA-Link	$6C	12	Link to the Imported Spawn Array
+OBDC-Link	$70	12	Link to the Door Class Array
+ONOA-Link	$74	12	Link to the Object Gunk Array
+ENVP-Link	$78	12	Link to the Environment Particle Array
+Not used	$7C	1644	Not used
+CRSA-Link	$300	12	Link to the Corpse Array
+Not used	$304	1028	Not used
Index: /oup/current/exe/StructDefs/ONMA.txt
===================================================================
--- /oup/current/exe/StructDefs/ONMA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONMA.txt	(revision 10)
@@ -0,0 +1,13 @@
+Imported Marker Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	88
+Light name	$00	10064	Name of the light
+x-position	$40	9	x-position of the light
+y-position	$44	9	y-position (height) of the light
+z-position	$48	9	z-position of the light
+Unknown	$4C	9	Unknown
+Unknown	$50	9	Unknown
+Unknown	$54	9	Unknown
Index: /oup/current/exe/StructDefs/ONOA.txt
===================================================================
--- /oup/current/exe/StructDefs/ONOA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONOA.txt	(revision 10)
@@ -0,0 +1,9 @@
+Object Gunk Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	8
+Unknown	$00	14	Unknown
+Unknown	$02	14	Unknown
+IDXA-link	$04	12	Link to the Index Array
Index: /oup/current/exe/StructDefs/ONSA.txt
===================================================================
--- /oup/current/exe/StructDefs/ONSA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONSA.txt	(revision 10)
@@ -0,0 +1,7 @@
+Imported Spawn Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	2
+Unknown	$00	2	Unknown
Index: /oup/current/exe/StructDefs/ONSK.txt
===================================================================
--- /oup/current/exe/StructDefs/ONSK.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONSK.txt	(revision 10)
@@ -0,0 +1,39 @@
+Oni Sky Class
+File id	$00	12	File id
+Level id	$04	17	Level id
+TXMP-link	$08	12	Link to the top texture
+TXMP-link	$0C	12	Link to the left texture
+TXMP-link	$10	12	Link to the right texture
+TXMP-link	$14	12	Link to the front texture
+TXMP-link	$18	12	Link to the back texture
+Not used	$1C	1004	Not used; maybe a canceled link
+TXMP-link	$20	12	Link to the sun texture (not used in the game)
+Not used	$24	1004	Not used; maybe a canceled link
+Not used	$28	1004	Not used; maybe a canceled link
+Not used	$2C	1004	Not used; maybe a canceled link
+Not used	$30	1004	Not used; maybe a canceled link
+Not used	$34	1004	Not used; maybe a canceled link
+Not used	$38	1004	Not used; maybe a canceled link
+Not used	$3C	1004	Not used; maybe a canceled link
+Not used	$40	1004	Not used; maybe a canceled link
+TXMP-link	$44	12	Link to the lensflare texture (not used in the game)
+Not used	$48	1004	Not used; maybe a canceled link
+Not used	$4C	1004	Not used; maybe a canceled link
+Not used	$50	1004	Not used; maybe a canceled link
+Not used	$54	1004	Not used; maybe a canceled link
+Unknown	$58	4	Unknown
+Unknown	$5C	16	Unknown
+Unknown	$60	9	Unknown
+Not used	$64	1028	Not used
+Unknown	$80	9	Unknown
+Not used	$84	1028	Not used
+Unknown	$A0	9	Unknown
+Not used	$A4	1028	Not used
+Unknown	$C0	9	Unknown
+Not used	$C4	1028	Not used
+Unknown	$E0	9	Unknown
+Unknown	$E4	9	Unknown
+Unknown	$E8	9	Unknown
+Unknown	$EC	4	Unknown
+Unknown	$F0	4	Unknown
+Not used	$F4	1012	Not used
Index: /oup/current/exe/StructDefs/ONTA.txt
===================================================================
--- /oup/current/exe/StructDefs/ONTA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONTA.txt	(revision 10)
@@ -0,0 +1,8 @@
+Trigger Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1016	Not used
+Packages used	$18	4	Amount of packages that follow
+Packages possible	$1C	4	Amount of packages that are possible
+*Package		$20	$18	4	416
+Unknown	$00	1416	Unknown; never used in Oni
Index: /oup/current/exe/StructDefs/ONVL.txt
===================================================================
--- /oup/current/exe/StructDefs/ONVL.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONVL.txt	(revision 10)
@@ -0,0 +1,7 @@
+Oni Variant List
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+ONCV-link	$00	12	Link to the Character Variant
Index: /oup/current/exe/StructDefs/ONWC.txt
===================================================================
--- /oup/current/exe/StructDefs/ONWC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/ONWC.txt	(revision 10)
@@ -0,0 +1,158 @@
+Oni Weapon Class
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown
+Unknown	$20	9	Unknown
+Unknown	$24	16	Unknown
+TXMP-link	$28	12	Link to the first target texture
+Unknown 	$2C	16	Unknown
+Unknown	$30	9	Unknown
+TXMP-link	$34	12	Link to the second target texture
+Unknown	$38	16	Unknown
+Unknown	$3C	9	Unknown
+TXMP-link	$40	12	Link to the third target texture
+Unknown	$44	16	Unknown
+Unknown	$48	9	Unknown
+Unknown	$4C	4	Unknown
+Unknown	$50	9	Unknown
+TXMP-link	$54	12	Link to the tap_icon texture
+TXMP-link	$58	12	Link to the tap_empty texture
+TXMP-link	$5C	12	Link to the tap_fill texture
+M3GM-link	$60	12	Link to the weapon model
+Weapon name	$64	10032	Name of the weapon
+Unknown	$84	9	Unknown
+Unknown	$88	9	Unknown
+Unknown	$8C	9	Unknown
+Unknown	$90	9	Unknown
+Unknown	$94	9	Unknown
+Unknown	$98	9	Unknown
+Unknown	$9C	9	Unknown
+Unknown	$A0	9	Unknown
+Unknown	$A4	9	Unknown
+Unknown	$A8	9	Unknown
+Unknown	$AC	9	Unknown
+Unknown	$B0	9	Unknown
+Unknown	$B4	9	Unknown
+Unknown	$B8	9	Unknown
+Unknown	$BC	9	Unknown
+Unknown	$C0	2	Unknown; always the same
+Unknown	$C2	2	Unknown
+Unknown	$C4	2	Unknown
+Pause after reload  	$C6	2	Pause after reload in 1/60 seconds
+Shots	$C8	2	Amount of shots
+Packages used	$CA	2	Amount of used packages (the file contains space for 16 packages)
+Shot modes	$CC	2	Number of shot modes
+Pause before reload	$CE	2	Pause before reload in 1/60 seconds
+Unknown	$D0	2	Unknown
+Unknown	$D2	2	Unknown; always zero
+Weapon options 1	$D4	10	Weapon options 1
+Weapon options 2	$D5	10	Weapon options 2
+Weapon options 3	$D6	10	Weapon options 3
+Unknown	$D7	1	Unknown; always the same
+Unknown	$D8	2	Unknown
+Unknown	$DA	2	Unknown; always the same
+Unknown	$DC	9	Unknown
+Unknown	$E0	9	Unknown
+Unknown	$E4	9	Unknown
+Unknown	$E8	9	Unknown
+Unknown	$EC	9	Unknown
+Unknown	$F0	9	Unknown
+Unknown	$F4	9	Unknown
+Unknown	$F8	9	Unknown
+Unknown	$FC	9	Unknown
+Unknown	$100	9	Unknown
+Unknown	$104	9	Unknown
+Unknown	$108	9	Unknown
+Unknown	$10C	9	Unknown
+Unknown	$110	9	Unknown
+Unknown	$114	9	Unknown
+Unknown	$118	9	Unknown
+Unknown	$11C	9	Unknown
+Unknown	$120	9	Unknown
+Range of fire	$124	9	Range of fire
+Unknown	$128	9	Scattering angle ? / slice ?
+Unknown	$12C	9	Unknown; always the same
+Unknown	$130	9	Unknown
+Unknown	$134	9	Unknown
+Unknown	$138	9	Unknown
+Unknown	$13C	2	Unknown; always the same
+Weapon id	$13E	2	Id of the weapon
+Unknown	$140	4	Unknown
+Unknown	$144	9	Unknown
+Unknown	$148	9	Unknown
+Unknown	$14C	9	Unknown
+Unknown	$150	9	Unknown
+Unknown	$154	9	Unknown
+Unknown	$158	9	Unknown; always the same
+Unknown	$15C	9	Unknown; only w11_ba1 use it
+Unknown	$160	9	Unknown; always the same
+Unknown	$164	9	Unknown; always the same
+Unknown	$168	9	Unknown; always the same
+Unknown	$16C	9	Unknown; only w11_ba1 use it
+Unknown	$170	9	Unknown; always the same
+Unknown	$174	9	Unknown; always the same
+Unknown	$178	9	Unknown; always the same
+Unknown	$17C	9	Unknown; only w11_ba1 use it
+Unknown	$180	9	Unknown; always the same
+Unknown	$184	9	Unknown; always the same
+Unknown	$188	9	Unknown; always the same
+Unknown	$18C	9	Unknown; only w11_ba1 use it
+Unknown	$190	9	Unknown; only w11_ba1 use it
+Unknown	$194	9	Unknown; only w11_ba1 use it
+Unknown	$198	9	Unknown; only w11_ba1 use it
+Unknown	$19C	9	Unknown; only w11_ba1 use it
+Unknown	$1A0	9	Unknown; only w11_ba1 use it
+Unknown	$1A4	9	Unknown; only w11_ba1 use it
+Unknown	$1A8	9	Unknown; always the same
+Unknown	$1AC	9	Unknown; only w11_ba1 use it
+Unknown	$1B0	9	Unknown; only w11_ba1 use it
+Unknown	$1B4	9	Unknown; only w11_ba1 use it
+Unknown	$1B8	9	Unknown; always the same
+Unknown	$1BC	2	Unknown; only w11_ba1 use it
+Unknown	$1BE	2	Unknown; only w11_ba1 use it
+Unknown	$1C0	9	Unknown; always the same
+Unknown	$1C4	9	Unknown; only w11_ba1 use it
+Unknown	$1C8	9	Unknown; only w11_ba1 use it
+Unknown	$1CC	9	Unknown; always the same
+Unknown	$1D0	9	Unknown; always the same
+Unknown	$1D4	9	Unknown; always the same
+
+Empty weapon sound	$6D8	132	Reference to an OSBD file
+Unknown	$6F8	4	Unknown
+TXMP-link	$6FC	12	Link to the glow texture
+TXMP-link	$700	12	Link to the glow_ammo texture
+Unknown	$704	9	Unknown
+Unknown	$708	9	Unknown
+Unknown	$70C	9	Unknown
+Unknown	$710	9	Unknown
+Unknown	$714	9	Unknown
+Unknown	$718	9	Unknown
+Not used	$71C	1004	Not used
+
+*Packages		$1D8	$CA	2	64
+Unknown	$00	9	Unknown
+Unknown	$04	9	Unknown
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown
+Unknown	$20	9	Unknown
+Unknown	$24	9	Unknown
+Unknown	$28	9	Unknown
+Unknown	$2C	9	Unknown
+Particle reference	$30	116	Reference to the weapon particle
+Unknown	$40	2	Unknown; always the same
+Unknown	$42	2	Unknown; always the same
+Unknown	$44	2	Unknown
+Shot frequency	$46	2	Shot frequency in 1/60 seconds
+Unknown	$48	2	Unknown
+Unknown	$4A	2	Unknown
+Unknown	$4C	2	Unknown
+Unknown	$4E	2	Unknown
Index: /oup/current/exe/StructDefs/OPge.txt
===================================================================
--- /oup/current/exe/StructDefs/OPge.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OPge.txt	(revision 10)
@@ -0,0 +1,7 @@
+Objective Page
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1002	Not used
+Level	$0A	2	Level
+IGPA-link	$0C	12	Link to the In-Game User Interface Page Array
+Not used	$10	1016	Not used
Index: /oup/current/exe/StructDefs/OSBD.txt
===================================================================
--- /oup/current/exe/StructDefs/OSBD.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OSBD.txt	(revision 10)
@@ -0,0 +1,6 @@
+Oni Sound Binary Data
+File id	$00	12	File id
+Level id	$04	17	Level id
+Size	$08	4	Size of the part in the raw file
+Offset	$0C	11	At this position starts the part in the raw/sep file
+Not used	$10	1016	Not used
Index: /oup/current/exe/StructDefs/OTIT.txt
===================================================================
--- /oup/current/exe/StructDefs/OTIT.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OTIT.txt	(revision 10)
@@ -0,0 +1,22 @@
+Oct Tree Leaf Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	32
+1st child pointer	$00	3	Pointer to the 1st child
+High bit	$03	1	High bit
+2nd child pointer	$04	3	Pointer to the 2nd child
+High bit	$07	1	High bit
+3rd child pointer	$08	3	Pointer to the 3rd child
+High bit	$0B	1	High bit
+4th child pointer	$0C	3	Pointer to the 4th child
+High bit	$0F	1	High bit
+5th child pointer	$10	3	Pointer to the 5th child
+High bit	$13	1	High bit
+6th child pointer	$14	3	Pointer to the 6th child
+High bit	$17	1	High bit
+7th child pointer	$18	3	Pointer to the 7th child
+High bit	$1B	1	High bit
+8th child pointer	$1C	3	Pointer to the 8th child
+High bit	$1F	1	High bit
Index: /oup/current/exe/StructDefs/OTLF.txt
===================================================================
--- /oup/current/exe/StructDefs/OTLF.txt	(revision 10)
+++ /oup/current/exe/StructDefs/OTLF.txt	(revision 10)
@@ -0,0 +1,22 @@
+Oct Tree Interior Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	36
+Unknown	$00	3	Unknown
+High bit	$03	1	High bit
+Unknown	$04	3	Unknown
+High bit	$07	1	High bit
+Unknown	$08	3	Unknown
+High bit	$0B	1	High bit
+Unknown	$0C	3	Unknown
+High bit	$0F	1	High bit
+Unknown	$10	3	Unknown
+High bit	$13	1	High bit
+Unknown	$14	3	Unknown
+High bit	$17	1	High bit
+Unknown	$18	3	Unknown
+High bit	$1B	1	High bit
+Unknown	$1C	9	Unknown
+Unknown	$20	4	Unknown; always the same (?)
Index: /oup/current/exe/StructDefs/PLEA.txt
===================================================================
--- /oup/current/exe/StructDefs/PLEA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/PLEA.txt	(revision 10)
@@ -0,0 +1,10 @@
+Plane Equation Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	32
+Unknown	$00	9	Unknown
+Unknown	$04	9	Unknown
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
Index: /oup/current/exe/StructDefs/PNTA.txt
===================================================================
--- /oup/current/exe/StructDefs/PNTA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/PNTA.txt	(revision 10)
@@ -0,0 +1,19 @@
+3D Point Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1012	Not used
+Minimum x-coordinate	$14	9	Minimum x-coordinate of all packages below
+Minimum y-coordinate	$18	9	Minimum y-coordinate (height) of all packages below
+Minimum z-coordinate	$1C	9	Minimum z-coordinate of all packages below
+Maximum x-coordinate	$20	9	Maximum x-coordinate of all packages below
+Maximum y-coordinate	$24	9	Maximum y-coordinate (height) of all packages below
+Maximum z-coordinate	$28	9	Maximum z-coordinate of all packages below
+Center x-coordinate	$2C	9	x-coordinate of the center [ (max. x-coord. - min. x-coord.) ÷ 2) + min. x-coord. ]
+Center y-coordinate	$30	9	y-coordinate of the center [ (max. y-coord. - min. y-coord.) ÷ 2) + min. y-coord. ]
+Center z-coordinate	$34	9	z-coordinate of the center [ (max. z-coord. - min. z-coord.) ÷ 2) + min. z-coord. ]
+Distance	$38	9	Distance from the center to each of the both points above
+Packages	$3C	4	Amount of packages that follow
+*Package		$40	$3C	4	12
+x-coordinate	$00	9	x-coordinate of the point
+y-coordinate	$04	9	y-coordinate (height) of the point
+z-coordinate	$08	9	z-coordinate of the point
Index: /oup/current/exe/StructDefs/PSPC.txt
===================================================================
--- /oup/current/exe/StructDefs/PSPC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/PSPC.txt	(revision 10)
@@ -0,0 +1,43 @@
+Particle Specification (coordinates of UI element in texture) (see pspc.png)
+
+ID	$00	12
+LevelID	$04	17
+LFT-LT	$08	2	LT Left
+TOP-LT	$0A	2	LT Top
+LFT-HL	$0C	2	HL Left (rubber)
+TOP-HL	$0E	2	HL Top (rubber)
+LFT-LB	$10	2	LB Left
+TOP-LB	$12	2	LB Top
+LFT-VT	$14	2	VT Left (rubber)
+TOP-VT	$16	2	VT Top (rubber)
+LFT-CC	$18	2	CC Left (rubber)
+TOP-CC	$1A	2	CC Top (rubber)
+LFT-VB	$1C	2	VB Left (rubber)
+TOP-VB	$1E	2	VB Top (rubber)
+LFT-RT	$20	2	RT Left
+TOP-RT	$22	2	RT Top
+LFT-HR	$24	2	HR Left (rubber)
+TOP-HR	$26	2	HR Top (rubber)
+LFT-RB	$28	2	RB Left
+TOP-RB	$2A	2	RB Top
+
+RGH-LT	$2C	2	LT Right
+BTM-LT	$2E	2	LT Bottom
+RGH-HL	$30	2	HL Right (rubber)
+BTM-HL	$32	2	HL Bottom (rubber)
+RGH-LB	$34	2	LB Right
+BTM-LB	$36	2	LB Bottom
+RGH-VT	$38	2	VT Right (rubber)
+BTM-VT	$3A	2	VT Bottom (rubber)
+RGH-CC	$3C	2	CC Right (rubber)
+BTM-CC	$3E	2	CC Bottom (rubber)
+RGH-VB	$40	2	VB Right (rubber)
+BTM-VB	$42	2	VB Bottom (rubber)
+RGH-RT	$44	2	RT Right
+BTM-RT	$46	2	RT Bottom
+RGH-HR	$48	2	HR Right (rubber)
+BTM-HR	$4A	2	HR Bottom (rubber)
+RGH-RB	$4C	2	RB Right
+BTM-RB	$4E	2	RB Bottom
+TXMP-Link	$50	12	Corresponding texture
+
Index: /oup/current/exe/StructDefs/PSUI.txt
===================================================================
--- /oup/current/exe/StructDefs/PSUI.txt	(revision 10)
+++ /oup/current/exe/StructDefs/PSUI.txt	(revision 10)
@@ -0,0 +1,48 @@
+Part Specifications UI (User Interface)
+File id	$00	12	File id
+Level id	$04	17	Level id
+PSpc-link	$08	12	Link to the Part Specification
+PSpc-link	$0C	12	Link to the Part Specification
+PSpc-link	$10	12	Link to the Part Specification
+PSpc-link	$14	12	Link to the Part Specification
+PSpc-link	$18	12	Link to the Part Specification
+PSpc-link	$1C	12	Link to the Part Specification
+PSpc-link	$20	12	Link to the Part Specification
+PSpc-link	$24	12	Link to the Part Specification
+PSpc-link	$28	12	Link to the Part Specification
+PSpc-link	$2C	12	Link to the Part Specification
+PSpc-link	$30	12	Link to the Part Specification
+PSpc-link	$34	12	Link to the Part Specification
+PSpc-link	$38	12	Link to the Part Specification
+PSpc-link	$3C	12	Link to the Part Specification
+PSpc-link	$40	12	Link to the Part Specification
+PSpc-link	$44	12	Link to the Part Specification
+PSpc-link	$48	12	Link to the Part Specification
+PSpc-link	$4C	12	Link to the Part Specification
+PSpc-link	$50	12	Link to the Part Specification
+PSpc-link	$54	12	Link to the Part Specification
+PSpc-link	$58	12	Link to the Part Specification
+PSpc-link	$5C	12	Link to the Part Specification
+PSpc-link	$60	12	Link to the Part Specification
+PSpc-link	$64	12	Link to the Part Specification
+PSpc-link	$68	12	Link to the Part Specification
+PSpc-link	$6C	12	Link to the Part Specification
+PSpc-link	$70	12	Link to the Part Specification
+PSpc-link	$74	12	Link to the Part Specification
+PSpc-link	$78	12	Link to the Part Specification
+PSpc-link	$7C	12	Link to the Part Specification
+PSpc-link	$80	12	Link to the Part Specification
+PSpc-link	$84	12	Link to the Part Specification
+PSpc-link	$88	12	Link to the Part Specification
+PSpc-link	$8C	12	Link to the Part Specification
+PSpc-link	$90	12	Link to the Part Specification
+PSpc-link	$94	12	Link to the Part Specification
+PSpc-link	$98	12	Link to the Part Specification
+PSpc-link	$9C	12	Link to the Part Specification
+PSpc-link	$A0	12	Link to the Part Specification
+PSpc-link	$A4	12	Link to the Part Specification
+PSpc-link	$A8	12	Link to the Part Specification
+PSpc-link	$AC	12	Link to the Part Specification
+PSpc-link	$B0	12	Link to the Part Specification
+PSpc-link	$B4	12	Link to the Part Specification
+Not used	$B8	1008	Not used
Index: /oup/current/exe/StructDefs/PSpL.txt
===================================================================
--- /oup/current/exe/StructDefs/PSpL.txt	(revision 10)
+++ /oup/current/exe/StructDefs/PSpL.txt	(revision 10)
@@ -0,0 +1,8 @@
+Part Specification List
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	8
+Unknown	$00	4	Unknown
+PSpc-link	$04	12	Link to the Part Specification
Index: /oup/current/exe/StructDefs/QTNA.txt
===================================================================
--- /oup/current/exe/StructDefs/QTNA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/QTNA.txt	(revision 10)
@@ -0,0 +1,14 @@
+Quad Tree Node Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	16
+Unknown	$00	3	Unknown
+High bit	$03	1	High bit
+Unknown	$04	3	Unknown
+High bit	$07	1	High bit
+Unknown	$08	3	Unknown
+High bit	$0B	1	High bit
+Unknown	$0C	3	Unknown
+High bit	$0F	1	High bit
Index: /oup/current/exe/StructDefs/SNDD.txt
===================================================================
--- /oup/current/exe/StructDefs/SNDD.txt	(revision 10)
+++ /oup/current/exe/StructDefs/SNDD.txt	(revision 10)
@@ -0,0 +1,8 @@
+Sound Data
+File id	$00	12	File id
+Level id	$04	17	Level id
+Wav header	$08	10054	Wav header; don't alter it
+Duration	$3E	2	Duration in 1/60 seconds
+Size	$40	4	Size of the part in the raw file
+Offset	$44	11	At this position starts the part in the raw file
+Not used	$48	1024	Not used
Index: /oup/current/exe/StructDefs/SUBT.txt
===================================================================
--- /oup/current/exe/StructDefs/SUBT.txt	(revision 10)
+++ /oup/current/exe/StructDefs/SUBT.txt	(revision 10)
@@ -0,0 +1,8 @@
+Subtitles
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1016	Not used
+Raw-Link	$18	11	Address of the subtitle data in the .raw-file
+Packages	$1C	4	Amount of packages that follow
+*Packages		$20	$1C	4	4
+Raw-link	$0	11	Start position of the subtitle in the raw file
Index: /oup/current/exe/StructDefs/StNA.txt
===================================================================
--- /oup/current/exe/StructDefs/StNA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/StNA.txt	(revision 10)
@@ -0,0 +1,7 @@
+String Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	4
+TStr-link	$00	12	Link to the String
Index: /oup/current/exe/StructDefs/TRAC.txt
===================================================================
--- /oup/current/exe/StructDefs/TRAC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRAC.txt	(revision 10)
@@ -0,0 +1,11 @@
+Animation Collection
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1016	Not used
+TRAC-link	$18	12	Link to a shared Animation Collection
+Unknown	$1C	2	Unknown
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	12
+Unknown	$00	4	Unknown
+Not used	$04	1004	Not used
+TRAM-link	$08	12	Link to the Animation
Index: /oup/current/exe/StructDefs/TRAM.txt
===================================================================
--- /oup/current/exe/StructDefs/TRAM.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRAM.txt	(revision 10)
@@ -0,0 +1,126 @@
+Totoro Animation Sequence (Totoro is the name of the character animation engine.)
+File id	$00	12	File id
+Level id	$04	17	Level id
+Raw link	$0C	11	Address of the y-position data in the .raw-file
+Raw link	$10	11	Address of the x-z-position data in the .raw-file
+Raw link	$14	11	Address of the attack data in the .raw-file
+Raw link	$18	11	Address of the damage data in the .raw-file
+Raw link	$1C	11	Address of the motion blur data in the .raw-file
+Raw link	$20	11	Address of the shortcut data in the .raw-file
+Raw link	$24	11	Address of the throw data in the .raw-file
+Raw link	$28	11	Address of the footstep data in the .raw-file
+Raw link	$2C	11	Address of the particle data in the .raw-file
+Raw link	$30	11	Address of the position data in the .raw-file
+Raw link	$34	11	Address of the bodypart animation data in the .raw-file
+Raw link	$38	11	Address of the sound data in the .raw-file
+Flags	$3C	4	Flags; it seems that Oni read it as 4 byte string from left to right; I would read it as 4 seperate bitsets
+TRAM link	$40	4	First direct animation link; this animation follows after a left mouse click (punch)
+TRAM link	$44	4	Second direct animation link; this animation follows after a right mouse click (kick)
+Used parts	$48	4	Used parts; used for weapon animations like recoil, reload, draw weapon, etc.
+Replace parts	$4C	4	Replace parts; used for weapon animations like recoil, reload, draw weapon, etc.
+Final rotation	$50	9	Final rotation; stored as multiples of the number "pi" (3.141592...)
+Move direction	$54	2	Move direction
+Attack voice sound	$56	14	Attack voice sound (f.e. Konokos "Rising fury!")
+Extent packages	$138	4	Amount of packages of the extent data
+Raw link	$13C	11	Address of the extent data in the .raw-file
+Attack sound	$140	116	Reference to an attack sound (f.e. "slap") of level 0
+Hard pause	$150	2	Hard pause in 1/60 seconds
+Soft pause	$152	2	Soft pause in 1/60 seconds
+Frames	$15E	2	Frames per second
+Compression	$160	2	Compression size
+Type	$162	2	ID for the animation of the opponent
+Animation Type	$164	2	ID for the animation of the opponent
+From state	$166	2	From state
+To state	$168	2	To state
+Bodyparts	$16A	2	Amount of bodyparts
+Frames	$16C	2	Animation length in frames
+Duration	$16E	2	Duration of the animation in frames
+Varient	$170	2	Varient; It seems that Oni read it as 2 byte string from left to right; I would read it as 2 seperate bitsets or as a short
+Varient end	$172	2	Varient end; It seems that Oni read it as 2 byte string from left to right; I would read it as a short
+Atomic start	$174	2	Atomic start
+Atomic end	$176	2	Atomic end
+End interpolation	$178	2	End interpolation
+Maximal interpolation	$17A	2	Maximal interpolation
+Action frame	$17C	14	Action frame; at this frame starts the "real" animation
+First level	$17E	2	First level; the level where you can use this animation the first time
+Attack packages	$182	1	Amount of packages of the attack data
+Damage packages	$183	1	Amount of packages of the damage data
+Motion blur packages	$184	1	Amount of packages of the motion blur data
+Shortcut packages	$185	1	Amount of packages of the shortcut data
+Footstep packages	$186	1	Amount of packages of the footstep data
+Particle packages	$187	1	Amount of packages of the particle data
+
+
+*Unknown
+Unknown	$08	4	Unknown; always zero
+Unknown	$58	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$5C	9	Unknown; always 1,000,000,000 if the attack part doesn't exist
+Unknown	$60	9	Unknown; always -1,000,000,000 if the attack part doesn't exist
+Unknown	$64	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$68	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$6C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$70	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$74	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$78	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$7C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$80	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$84	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$88	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$8C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$90	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$94	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$98	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$9C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$A0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$A4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$A8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$AC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$B0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$B4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$B8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$BC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$C0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$C4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$C8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$CC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$D0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$D4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$D8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$DC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$E0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$E4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$E8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$EC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$F0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$F4	14	Unknown; always -1 if the attack part doesn't exist
+Unknown	$F6	2	Unknown; always zero
+Unknown	$F8	9	Unknown
+Unknown	$FC	9	Unknown
+Unknown	$100	9	Unknown
+Unknown	$104	9	Unknown
+Unknown	$108	9	Unknown
+Unknown	$10C	9	Unknown
+Unknown	$110	9	Unknown
+Unknown	$114	14	Unknown
+Unknown	$116	1	Unknown
+Unknown	$117	1	Unknown
+Unknown	$118	9	Unknown
+Unknown	$11C	9	Unknown
+Unknown	$120	9	Unknown
+Unknown	$124	9	Unknown
+Unknown	$128	9	Unknown
+Unknown	$12C	9	Unknown
+Unknown	$130	9	Unknown
+Unknown	$134	8	Unknown; always zero
+Unknown	$154	2	Unknown; it seems that it belongs to the sound part
+Unknown	$156	2	Unknown
+Unknown	$158	2	Unknown
+Unknown	$15A	2	Unknown
+Unknown	$15C	2	Unknown
+Unknown	$180	1	Unknown
+Unknown	$181	1	Unknown
+
+
+*Unused
+Not used	$188	10024	Not used
+
Index: /oup/current/exe/StructDefs/TRAM_2.txt
===================================================================
--- /oup/current/exe/StructDefs/TRAM_2.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRAM_2.txt	(revision 10)
@@ -0,0 +1,122 @@
+Totoro Animation Sequence (Totoro is the name of the character animation engine.)
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	4	Unknown; always zero
+Raw link	$0C	11	Address of the y-position data in the .raw-file
+Raw link	$10	11	Address of the x-z-position data in the .raw-file
+Raw link	$14	11	Address of the attack data in the .raw-file
+Raw link	$18	11	Address of the damage data in the .raw-file
+Raw link	$1C	11	Address of the motion blur data in the .raw-file
+Raw link	$20	11	Address of the shortcut data in the .raw-file
+Raw link	$24	11	Address of the throw data in the .raw-file
+Raw link	$28	11	Address of the footstep data in the .raw-file
+Raw link	$2C	11	Address of the particle data in the .raw-file
+Raw link	$30	11	Address of the position data in the .raw-file
+Raw link	$34	11	Address of the bodypart animation data in the .raw-file
+Raw link	$38	11	Address of the sound data in the .raw-file
+Flags 1	$3C	10	Flags 1 in connection to the anim_flags.StNA file
+Flags 2	$3D	10	Flags 2 in connection to the anim_flags.StNA file
+Flags 3	$3E	10	Flags 3 in connection to the anim_flags.StNA file
+Unknown	$3F	1	Unknown; always the same
+TRAM link	$40	12	First direct animation link; this animation follows after a left mouse click (punch)
+TRAM link	$44	12	Second direct animation link; this animation follows after a right mouse click (kick)
+Used parts	$48	4	Used parts; used for weapon animations like recoil, reload, draw weapon, etc.
+Replace parts	$4C	4	Replace parts; used for weapon animations like recoil, reload, draw weapon, etc.
+Final rotation	$50	9	Final rotation; stored as multiples of the number "pi" (3.141592...)
+Move direction	$54	2	Move direction
+Attack voice sound	$56	14	Attack voice sound (f.e. Konokos "Rising fury!")
+Unknown	$58	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$5C	9	Unknown; always 1,000,000,000 if the attack part doesn't exist
+Unknown	$60	9	Unknown; always -1,000,000,000 if the attack part doesn't exist
+Unknown	$64	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$68	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$6C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$70	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$74	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$78	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$7C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$80	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$84	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$88	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$8C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$90	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$94	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$98	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$9C	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$A0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$A4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$A8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$AC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$B0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$B4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$B8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$BC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$C0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$C4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$C8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$CC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$D0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$D4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$D8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$DC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$E0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$E4	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$E8	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$EC	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$F0	9	Unknown; always zero if the attack part doesn't exist
+Unknown	$F4	14	Unknown; always -1 if the attack part doesn't exist
+Unknown	$F6	2	Unknown; always zero
+Unknown	$F8	9	Unknown
+Unknown	$FC	9	Unknown
+Unknown	$100	9	Unknown
+Unknown	$104	9	Unknown
+Unknown	$108	9	Unknown
+Unknown	$10C	9	Unknown
+Unknown	$110	9	Unknown
+Unknown	$114	14	Unknown
+Unknown	$116	1	Unknown
+Unknown	$117	1	Unknown
+Unknown	$118	9	Unknown
+Unknown	$11C	9	Unknown
+Unknown	$120	9	Unknown
+Unknown	$124	9	Unknown
+Unknown	$128	9	Unknown
+Unknown	$12C	9	Unknown
+Unknown	$130	9	Unknown
+Unknown	$134	8	Unknown; always zero
+Extent packages	$138	4	Amount of packages of the extent data
+Raw link	$13C	11	Address of the extent data in the .raw-file
+Attack sound	$140	116	Reference to an attack sound (f.e. "slap") of level 0
+Hard pause	$150	2	Hard pause in 1/60 seconds
+Soft pause	$152	2	Soft pause in 1/60 seconds
+Unknown	$154	2	Unknown; it seems that it belongs to the sound part
+Unknown	$156	2	Unknown
+Unknown	$158	2	Unknown
+Unknown	$15A	2	Unknown
+Unknown	$15C	2	Unknown
+Frames	$15E	2	Frames per second
+Compression	$160	2	Compression size
+Type	$162	2	ID for the animation of the opponent
+Animation Type	$164	2	ID for the animation of the opponent
+From state	$166	2	From state
+To state	$168	2	To state
+Bodyparts	$16A	2	Amount of bodyparts
+Frames	$16C	2	Animation length in frames
+Duration	$16E	2	Duration of the animation in frames
+Varient	$170	2	Varient; It seems that Oni read it as 2 byte string from left to right; I would read it as 2 seperate bitsets or as a short
+Varient end	$172	2	Varient end; It seems that Oni read it as 2 byte string from left to right; I would read it as a short
+Atomic start	$174	2	Atomic start
+Atomic end	$176	2	Atomic end
+End interpolation	$178	2	End interpolation
+Maximal interpolation	$17A	2	Maximal interpolation
+Action frame	$17C	14	Action frame; at this frame starts the "real" animation
+First level	$17E	2	First level; the level where you can use this animation the first time
+Unknown	$180	1	Unknown
+Unknown	$181	1	Unknown
+Attack packages	$182	1	Amount of packages of the attack data
+Damage packages	$183	1	Amount of packages of the damage data
+Motion blur packages	$184	1	Amount of packages of the motion blur data
+Shortcut packages	$185	1	Amount of packages of the shortcut data
+Footstep packages	$186	1	Amount of packages of the footstep data
+Particle packages	$187	1	Amount of packages of the particle data
+Not used	$188	10024	Not used
Index: /oup/current/exe/StructDefs/TRAS.txt
===================================================================
--- /oup/current/exe/StructDefs/TRAS.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRAS.txt	(revision 10)
@@ -0,0 +1,13 @@
+Totoro Aiming Screen
+File id	$00	12	File id
+Level id	$04	17	Level id
+TRAM-link	$08	12	Link to the Aiming Animation
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	2	Unknown
+Unknown	$16	2	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown
+Unknown	$20	2	Unknown
+Unknown	$22	2	Unknown
+Not used	$24	1028	Not used
Index: /oup/current/exe/StructDefs/TRBS.txt
===================================================================
--- /oup/current/exe/StructDefs/TRBS.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRBS.txt	(revision 10)
@@ -0,0 +1,10 @@
+Totoro Body Set
+File id	$00	12	File id
+Level id	$04	17	Level id
+TRCM-link	$08	12	Link to the extra low detailed body array
+TRCM-link	$0C	12	Link to the low detailed body array
+TRCM-link	$10	12	Link to the medium detailed body array
+TRCM-link	$14	12	Link to the high detailed body array
+TRCM-link	$18	12	Link to the extra high detailed body array
+Not used	$1C	1004	Not used
+
Index: /oup/current/exe/StructDefs/TRCM.txt
===================================================================
--- /oup/current/exe/StructDefs/TRCM.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRCM.txt	(revision 10)
@@ -0,0 +1,15 @@
+Totoro Quaternion Body
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	4	Unknown
+Bodyparts	$0C	2	Number of bodyparts
+Not used	$0E	1002	Not used
+Internal file name	$10	10064	Internal file name
+Not used	$50	1004	Old offset link; you can set it to zero if you want
+Not used	$54	1004	Old offset link; you can set it to zero if you want
+Not used	$58	1004	Old offset link; you can set it to zero if you want
+TRGA-link	$5C	12	Link to the Body Geometry Array
+TRTA-link	$60	12	Link to the Body Translation Array
+TRIA-link	$64	12	Link to the Body Index Array
+Not used	$68	1024	Not used
+
Index: /oup/current/exe/StructDefs/TRGA.txt
===================================================================
--- /oup/current/exe/StructDefs/TRGA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRGA.txt	(revision 10)
@@ -0,0 +1,8 @@
+Totoro Quaternion Body Geometry Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	4
+M3GM-link	$00	12	Link to the body geometry
+
Index: /oup/current/exe/StructDefs/TRGE.txt
===================================================================
--- /oup/current/exe/StructDefs/TRGE.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRGE.txt	(revision 10)
@@ -0,0 +1,13 @@
+Trigger Emitter
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	9	Unknown
+Unknown	$0C	9	Unknown
+Unknown	$10	9	Unknown
+Unknown	$14	9	Unknown
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown
+M3GM-link	$20	12	Link to the Geometry
+Unknown	$24	4	Unknown; maybe a canceled link
+Not used	$28	1024	Not used
+
Index: /oup/current/exe/StructDefs/TRIA.txt
===================================================================
--- /oup/current/exe/StructDefs/TRIA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRIA.txt	(revision 10)
@@ -0,0 +1,10 @@
+Totoro Quaternion Body Translation Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	4
+Not used	$00	1001	Oni doesn't need it; you can set it to what you want
+Major joint	$01	1	Major joint
+Minor joint	$02	1	Minor joint
+Not used	$03	1001	Not used
Index: /oup/current/exe/StructDefs/TRIG.txt
===================================================================
--- /oup/current/exe/StructDefs/TRIG.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRIG.txt	(revision 10)
@@ -0,0 +1,19 @@
+Trigger
+File id	$00	12	File id
+Level id	$04	17	Level id
+Unknown	$08	16	Unknown; always the same
+Unknown	$0C	4	Unknown; always the same
+Unknown	$10	4	Unknown; always the same
+Unknown	$14	9	Unknown; always the same
+M3GM-link	$18	12	Link to the Geometry
+Unknown	$1C	4	Unknown; always the same
+Unknown	$20	2	Unknown
+Unknown	$22	2	Unknown
+TRGE-link	$24	12	Link to the Trigger Emitter
+OBAN-link	$28	12	Link to the Object Animation
+Trigger active sound	$2C	132	Reference to an OSBD file
+Trigger hit sound	$4C	132	Reference to an OSBD file
+Unknown	$6C	4	Unknown; always the same
+Unknown	$70	4	Unknown; always the same
+Not used	$74	1012	Not used
+
Index: /oup/current/exe/StructDefs/TRMA.txt
===================================================================
--- /oup/current/exe/StructDefs/TRMA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRMA.txt	(revision 10)
@@ -0,0 +1,8 @@
+Texture Map Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	4
+TXMP-link	$00	12	Link to the Texture
+
Index: /oup/current/exe/StructDefs/TRSC.txt
===================================================================
--- /oup/current/exe/StructDefs/TRSC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRSC.txt	(revision 10)
@@ -0,0 +1,8 @@
+Screen (Aiming) Collection
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	4
+TRAS-link	$00	12	Link to the Aiming Screen
+
Index: /oup/current/exe/StructDefs/TRTA.txt
===================================================================
--- /oup/current/exe/StructDefs/TRTA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TRTA.txt	(revision 10)
@@ -0,0 +1,9 @@
+Totoro Quaternion Body Translation Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1022	Not used
+Packages	$1E	2	Amount of packages that follow
+*Package		$20	$1E	2	12
+x-position	$00	9	x-postition of the bodypart in connection to the TRIA file
+y-position	$04	9	y-postition of the bodypart in connection to the TRIA file
+z-position	$08	9	z-postition of the bodypart in connection to the TRIA file
Index: /oup/current/exe/StructDefs/TSFF.txt
===================================================================
--- /oup/current/exe/StructDefs/TSFF.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TSFF.txt	(revision 10)
@@ -0,0 +1,9 @@
+Font Family
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1016	Not used
+TSFL-link	$18	12	Link to the Font Language
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+TRAS-link	$00	12	Link to the Font
+
Index: /oup/current/exe/StructDefs/TSFL.txt
===================================================================
--- /oup/current/exe/StructDefs/TSFL.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TSFL.txt	(revision 10)
@@ -0,0 +1,9 @@
+Font Language
+File id	$00	12	File id
+Level id	$04	17	Level id
+Char block 1	$08	10064	Char block 1
+Char block 2	$48	10064	Char block 2
+Char block 3	$88	10064	Char block 3
+Char block 4	$C8	10064	Char block 4
+Char block 5	$108	10064	Char block 5
+Not used	$148	1024	Not used
Index: /oup/current/exe/StructDefs/TSFT.txt
===================================================================
--- /oup/current/exe/StructDefs/TSFT.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TSFT.txt	(revision 10)
@@ -0,0 +1,15 @@
+Font
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1006	Not used
+Unknown	$0E	2	Unknown
+Unknown	$10	4	Unknown
+Unknown	$14	2	Unknown
+Unknown	$16	2	Unknown
+Unknown	$18	2	Unknown
+Unknown	$1A	2	Unknown
+TSGA-link	$1C	12	Link to the Glyph Array
+Not used	$20	2020	Not used
+Packages	$41C	4	Amount of packages that follow
+*Package		$420	$41C	4	4
+Unknown	$00	8	Unknown
Index: /oup/current/exe/StructDefs/TSGA.txt
===================================================================
--- /oup/current/exe/StructDefs/TSGA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TSGA.txt	(revision 10)
@@ -0,0 +1,11 @@
+Glyph Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+*Package		$08	$04	$100	20
+ASCII table number	$00	2	ASCII table number
+Unknown	$02	2	Unknown
+Unknown	$04	2	Unknown
+Unknown	$06	4	Unknown
+Unknown	$0A	2	Unknown
+TSTF-reference	$0C	4	Package reference; at this package starts the glyph in the TSFT file
+Unknown	$10	4	Unknown
Index: /oup/current/exe/StructDefs/TStr.txt
===================================================================
--- /oup/current/exe/StructDefs/TStr.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TStr.txt	(revision 10)
@@ -0,0 +1,5 @@
+String
+File id	$00	12	File id
+Level id	$04	17	Level id
+Animation string	$08	10128	Animation string
+Not used	$88	1024	Not used
Index: /oup/current/exe/StructDefs/TURR.txt
===================================================================
--- /oup/current/exe/StructDefs/TURR.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TURR.txt	(revision 10)
@@ -0,0 +1,98 @@
+Turret
+File id	$00	12	File id
+Level id	$04	17	Level id
+Turret name	$08	10064	Name of the turret
+Unknown	$48	4	Unknown; always the same
+Not used	$4C	1008	Not used
+Unknown	$54	2	Unknown; always the same
+Packages used	$56	2	Amount of used packages (the file contains space for 16 packages)
+Unknown	$58	2	Unknown; always the same
+Not used	$5A	1006	Not used
+M3GM-link	$60	12	Link to the Geometry
+Unknown	$64	4	Unknown; always the same; maybe a canceled link
+Unknown	$68	4	Unknown; always the same; maybe a canceled link
+M3GM-link	$6C	12	Link to the Geometry
+Unknown	$70	4	Unknown; always the same; maybe a canceled link
+M3GM-link	$74	12	Link to the Geometry
+Unknown	$78	4	Unknown; always the same; maybe a canceled link
+Unknown	$7C	9	Unknown; always the same if it's a floor turret
+Unknown	$80	9	Unknown; always the same if it's a floor turret
+Unknown	$84	9	Unknown; always the same if it's a floor turret
+Unknown	$88	9	Unknown; always the same
+Unknown	$8C	9	Unknown; always the same
+Unknown	$90	9	Unknown; always the same
+*Packages		$94	$56	2	76
+Particle reference	$00	116	Reference to the weapon particle
+Unknown	$10	4	Unknown; always the same
+Shot frequency	$14	4	Shot frequency in 1/60 seconds
+Unknown	$18	9	Unknown
+Unknown	$1C	9	Unknown
+Unknown	$20	9	Unknown
+Unknown	$24	9	Unknown
+Unknown	$28	9	Unknown
+Unknown	$2C	9	Unknown
+Unknown	$30	9	Unknown
+Unknown	$34	9	Unknown
+Unknown	$38	9	Unknown
+Unknown	$3C	9	Unknown
+Unknown	$40	9	Unknown
+Unknown	$44	9	Unknown
+Not used	$48	1004	Not used; always the same
+
+// oup stops here, because it can't read entries after the end of a package block; hope that Alloc will fix that
+
+Unknown	$554	4	Unknown
+Unknown	$558	9	Unknown
+Unknown	$55C	9	Unknown
+Unknown	$560	9	Unknown
+Unknown	$564	9	Unknown
+Unknown	$568	9	Unknown
+Unknown	$56C	9	Unknown
+Unknown	$570	9	Unknown
+Unknown	$574	9	Unknown
+Unknown	$578	9	Unknown
+Unknown	$57C	4	Unknown; always the same
+Unknown	$580	4	Unknown; always the same
+Unknown	$584	4	Unknown; always the same
+Unknown	$588	9	Unknown
+Unknown	$58C	9	Unknown
+Unknown	$590	9	Unknown
+Unknown	$594	9	Unknown
+Unknown	$598	9	Unknown
+Unknown	$59C	9	Unknown
+Unknown	$5A0	9	Unknown; always the same
+Unknown	$5A4	9	Unknown; always the same
+Unknown	$5A8	9	Unknown; always the same
+Unknown	$5AC	9	Unknown; always the same
+Unknown	$5B0	9	Unknown; always the same
+Unknown	$5B4	9	Unknown; always the same
+Unknown	$5B8	4	Unknown; always the same
+Unknown	$5BC	4	Unknown; always the same
+Unknown	$5C0	4	Unknown; always the same
+Unknown	$5C4	4	Unknown; always the same
+Unknown	$5C8	4	Unknown; always the same
+Unknown	$5CC	9	Unknown; always the same
+Unknown	$5D0	9	Unknown; always the same
+Unknown	$5D4	9	Unknown; always the same
+Unknown	$5D8	9	Unknown; always the same
+Unknown	$5DC	9	Unknown; always the same
+Unknown	$5E0	9	Unknown; always the same
+Unknown	$5E4	4	Unknown; always the same
+Unknown	$5E8	4	Unknown; always the same
+Unknown	$5EC	4	Unknown; always the same
+Unknown	$5F0	9	Unknown; always the same
+Unknown	$5F4	9	Unknown; always the same
+Unknown	$5F8	9	Unknown; always the same
+Unknown	$5FC	9	Unknown; always the same
+Unknown	$600	9	Unknown; always the same
+Unknown	$604	9	Unknown; always the same
+Unknown	$608	4	Unknown; always the same
+Unknown	$60C	9	Unknown; always the same if it's a floor turret
+Unknown	$610	9	Unknown; always the same if it's a floor turret
+Unknown	$614	9	Unknown; always the same if it's a floor turret
+Unknown	$618	9	Unknown; always the same if it's a floor turret
+Unknown	$61C	9	Unknown
+Unknown	$620	9	Unknown
+Active turret sound	$624	132	Reference to an OSBD file
+Unknown	$644	10016	Unknown; always the same
+Not used	$654	1012	Not used
Index: /oup/current/exe/StructDefs/TXAN.txt
===================================================================
--- /oup/current/exe/StructDefs/TXAN.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TXAN.txt	(revision 10)
@@ -0,0 +1,11 @@
+Texture Animation
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1012	Not used
+Loop speed	$14	2	Loop speed
+Unknown	$16	2	Unknown
+Unknown	$18	2	Unknown
+Not used	$1A	1002	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+TXMP link	$00	12	Image which is used for the texture animation
Index: /oup/current/exe/StructDefs/TXCA.txt
===================================================================
--- /oup/current/exe/StructDefs/TXCA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TXCA.txt	(revision 10)
@@ -0,0 +1,8 @@
+Texture Coordinate Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	8
+x-coordinate	$00	9	x-coordinate
+y-coordinate	$04	9	y-coordinate
Index: /oup/current/exe/StructDefs/TXMA.txt
===================================================================
--- /oup/current/exe/StructDefs/TXMA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TXMA.txt	(revision 10)
@@ -0,0 +1,7 @@
+Texture Map Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+TXMP-link	$00	12	Link to the Texture
Index: /oup/current/exe/StructDefs/TXMB.txt
===================================================================
--- /oup/current/exe/StructDefs/TXMB.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TXMB.txt	(revision 10)
@@ -0,0 +1,13 @@
+Texture Map Big
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1008	Not used
+Width	$10	2	Width of the complete texture
+Height	$12	2	Height of the complete texture
+Unknown	$14	4	Unknown; all to zero or FF works too
+Unknown	$18	2	Unknown; maybe the number of columns; all to zero or FF works too
+Unknown	$1A	2	Unknown; maybe the number of rows; all to zero or FF works too
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	4
+TXMP-link	$00	12	Link to the Texture
+
Index: /oup/current/exe/StructDefs/TXMP.txt
===================================================================
--- /oup/current/exe/StructDefs/TXMP.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TXMP.txt	(revision 10)
@@ -0,0 +1,15 @@
+Texture
+ID	$00	12	ID of this file
+LevelID	$04	17	ID of the level this file is in
+FileName	$08	10128	Name of the texture
+MIP Mapping	$88	10	MIP Mapping Bitset
+Depth	$89	10	Depth-Bitset
+Unknown	$8A	2	Unknown; always zero
+Width	$8C	2	x-resolution of image
+Height	$8E	2	y-resolution of image
+Storetype	$90	10	Storetype-Bitset
+TXAN-Link	$94	12	Link to the TXAN-file; only used if the texture is the first image of an texture animation
+TXMP-Link	$98	12	Link to another TXMP-file; only used in connection with shade vertex effects
+Raw-Link	$9C	11	Address of the image data in the .raw-file (only for PC-dat-files)
+Raw-Link	$A0	11	Address of the image data in the .raw-file (only for MAC-dat-files)
+Not used	$A4	1028	Not used
Index: /oup/current/exe/StructDefs/TxtC.txt
===================================================================
--- /oup/current/exe/StructDefs/TxtC.txt	(revision 10)
+++ /oup/current/exe/StructDefs/TxtC.txt	(revision 10)
@@ -0,0 +1,5 @@
+Text Console
+File id	$00	12	File id
+Level id	$04	17	Level id
+IGPA-link	$08	12	Link to the In-Game User Interface Page Array
+Not used	$0C	1020	Not used
Index: /oup/current/exe/StructDefs/VCRA.txt
===================================================================
--- /oup/current/exe/StructDefs/VCRA.txt	(revision 10)
+++ /oup/current/exe/StructDefs/VCRA.txt	(revision 10)
@@ -0,0 +1,9 @@
+3D Vector Array
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1018	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	12
+x-coordinate	$00	9	x-coordinate of the vector
+y-coordinate	$04	9	y-coordinate (height) of the vector
+z-coordinate	$08	9	z-coordinate of the vector
Index: /oup/current/exe/StructDefs/WMCL.txt
===================================================================
--- /oup/current/exe/StructDefs/WMCL.txt	(revision 10)
+++ /oup/current/exe/StructDefs/WMCL.txt	(revision 10)
@@ -0,0 +1,8 @@
+WM (Window Menu) Cursor List
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1020	Not used
+Packages	$1C	4	Amount of packages that follow
+*Package		$20	$1C	4	8
+Unknown	$00	4	Unknown; do not change it, Oni won't start if you do that
+PSpc-link	$04	12	Link to the Part Specification
Index: /oup/current/exe/StructDefs/WMDD.txt
===================================================================
--- /oup/current/exe/StructDefs/WMDD.txt	(revision 10)
+++ /oup/current/exe/StructDefs/WMDD.txt	(revision 10)
@@ -0,0 +1,33 @@
+Window Menu Dialog Data
+File id	$00	12	File id
+Level id	$04	4	Level id
+Window title	$08	10256	Title of the main-window
+Window id	$108	4	Id of the main-window
+Window status	$10C	4	Status of the main-window
+Window design	$110	2	Design of the main-window
+Window position	$112	6	Position of the main-window
+Unknown	$114	4	Unknown; always the same
+Width	$118	2	x-dimension of the main-window
+Height	$11A	2	y-dimension of the main-window
+Packages	$11C	4	Amount of packages that follow
+
+*Package		$120	$11C	4	292
+Caption	$0	10256	Caption of the sub-window
+Type	$100	2	Type
+Target id	$102	2	Id of the target
+Option	$104	2	Option
+Unknown	$106	2	Unknown
+Window design	$108	2	Design of the sub-window
+Visible option	$10A	2	Visible option of the sub-window
+x-position	$10C	2	x-position of the sub-window (from the upper left corner of the main-window)
+y-position	$10E	2	y-position of the sub-window (from the upper left corner of the main-window)
+Width	$110	2	x-dimension of the sub-window
+Height	$112	2	y-dimension of the sub-window
+TSFF-link	$114	12	Link to the Font Family
+Font option	$118	4	Font option
+Font color B	$11C	1	Font color - blue part
+Font color G	$11D	1	Font color - green part
+Font color R	$11E	1	Font color - red part
+Unknown	$11F	1	Unknown
+Unknown	$120	2	Unknown; always the same
+Font size	$122	2	Font size
Index: /oup/current/exe/StructDefs/WMMB.txt
===================================================================
--- /oup/current/exe/StructDefs/WMMB.txt	(revision 10)
+++ /oup/current/exe/StructDefs/WMMB.txt	(revision 10)
@@ -0,0 +1,9 @@
+WM (Window Menu) Menu Bar
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1018	Not used
+Unknown	$1A	2	Unknown
+Packages	$1C	4	Amount of packages that follow
+
+*Package		$20	$1C	4	4
+WMM_-link	$00	12	Link to the Window Menu
Index: /oup/current/exe/StructDefs/WMM_.txt
===================================================================
--- /oup/current/exe/StructDefs/WMM_.txt	(revision 10)
+++ /oup/current/exe/StructDefs/WMM_.txt	(revision 10)
@@ -0,0 +1,12 @@
+WM (Window Menu) Menu
+File id	$00	12	File id
+Level id	$04	17	Level id
+Not used	$08	1018	Not used
+Unknown	$1A	2	Unknown
+Menu name	$1C	10064	Name of the menu
+Packages	$5C	4	Amount of packages that follow
+
+*Package		$60	$5C	4	68
+Menu type	$00	2	Type of the menu
+Return number	$02	2	Number that returns if you choose this menu point
+Menu entry	$04	10064	Entry of the menu
Index: /oup/current/exe/StructDefs/WPge.txt
===================================================================
--- /oup/current/exe/StructDefs/WPge.txt	(revision 10)
+++ /oup/current/exe/StructDefs/WPge.txt	(revision 10)
@@ -0,0 +1,6 @@
+Weapon Page
+File id	$00	12	File id
+Level id	$04	17	Level id
+ONWC-link	$08	12	Link to the Oni Weapon Class
+IGPG-link	$0C	12	Link to the In-Game User Interface Page
+Not used	$10	1016	Not used
Index: /oup/current/irf_oni.onlv.vb
===================================================================
--- /oup/current/irf_oni.onlv.vb	(revision 10)
+++ /oup/current/irf_oni.onlv.vb	(revision 10)
@@ -0,0 +1,545 @@
+Public Type LWOPolygon
+  NumVe As Integer
+  P1 As Integer
+  P2 As Integer
+  P3 As Integer
+  Surfa As Integer
+End Type
+
+Public Type PolDef
+  P1 As Integer
+  P2 As Integer
+  P3 As Integer
+End Type
+
+'Texture Coordinate Entry
+Public Type TXCAentry
+  X As Single
+  Y As Single
+End Type
+
+'Texture Coordinate Lists
+Public Type TXCA            'Length
+  ID As Long                '4
+  Version As Long           '8
+  Filler(1 To 5) As Long    '28
+  NumEntries As Long        '32
+End Type
+
+'Level Data Reference List
+Public Type ONLV            'Length
+  ID As Long                '4
+  Version As Long           '8
+  LevelName As String * 64  '72
+  AKEVid As Long            '76
+  OBOAid As Long            '80
+  ONMAid As Long            '84
+  ONFAid As Long            '88
+  ONTAid As Long            '92
+  ONSKid As Long            '96
+  Unkn As Long              '100
+  AISAid As Long            '104
+  AITRid As Long            '108
+  ONSAid As Long            '112
+  OBDCid As Long            '116
+  ONOAid As Long            '120
+  Fill(1 To 161) As Long    '764
+  CRSAid As Long            '768
+End Type
+
+Public Type AGQG
+  ID As Long
+  unk(1 To 24) As Byte
+  NumEntries As Long
+End Type
+
+Public Type AGQGEntry
+  VertIndex(1 To 4) As Long
+  VertUVIndex(1 To 4) As Long
+  LData_1(1 To 4) As Byte
+  LData_2(1 To 4) As Byte
+  LData_3(1 To 4) As Byte
+  LData_4(1 To 4) As Byte
+  unk(1 To 2) As Long
+End Type
+
+Public Type AGQREntry
+  TexIndex As Integer
+  unk As Integer
+End Type
+
+Public Type TXMA
+   ID As Long
+   shit(1 To 24) As Byte
+   NumEntries As Long
+End Type
+
+Public Type TXMAEntry
+   TXMP_ID As Long
+End Type
+
+
+
+
+
+Public Sub CExportONLV(Optional FileName As String)
+Form1.StatusBar1.SimpleText = "Status: Extracting LEVEL....."
+Dim ID4 As Long
+Dim I As Long
+Dim L As Long
+Dim LwoP() As LWOPolygon
+Dim OniPol2() As PolDef
+Dim NP As Long
+Dim numb As Long
+
+Dim TXMA1 As TXMA
+Dim AGQR1 As TXMA
+Dim TXCA1 As TXCA
+Dim TXCA_E() As TXCAentry
+Dim TXMA_E() As TXMAEntry
+Dim AGQR_E() As AGQREntry
+Dim TexNames() As String
+
+If FileName = "" Then
+  Form1.CD.DialogTitle = "Unpack resource..."
+  Form1.CD.FileName = OniEntry(Curr).szTagName
+  Form1.CD.Filter = "LightWave (*.lwo)|*.lwo"
+  Form1.CD.Flags = &H2 + &H4
+  Form1.CD.ShowSave
+  FileName = Form1.CD.FileName
+  If FileName = "" Then Exit Sub
+End If
+
+DoEvents
+
+Open DatFile For Binary As #1
+  Get 1, OniEntry(Curr).rDataPosition, ONLV
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = ONLV.AKEVid Then
+      Get 1, OniEntry(I).rDataPosition, AKEV
+      Exit For
+    End If
+  Next I
+
+  'Find ID of PNTA
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.PNTAid Then
+       Get 1, OniEntry(I).rDataPosition, PNTA
+       ReDim PNTAentry(PNTA.NumEntries - 1)
+       Get 1, , PNTAentry
+       Exit For
+    End If
+  Next I
+
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.AGQGid Then
+       Get 1, OniEntry(I).rDataPosition, AGQG
+       ReDim AGQGEntry(AGQG.NumEntries - 1)
+       Get 1, , AGQGEntry
+       Exit For
+    End If
+  Next I
+
+  'TXCA
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.TXCAid Then
+       Get 1, OniEntry(I).rDataPosition, TXCA1
+       ReDim TXCA_E(TXCA1.NumEntries - 1)
+       Get 1, , TXCA_E
+       ReDim Preserve TXCA_E(PNTA.NumEntries - 1)
+       Exit For
+    End If
+  Next I
+
+  'TXMA
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.TXMAid Then
+       Get 1, OniEntry(I).rDataPosition, TXMA1
+       ReDim TXMA_E(TXMA1.NumEntries - 1)
+       Get 1, , TXMA_E
+       Exit For
+    End If
+  Next I
+
+  'AGQR
+  For I = 0 To UBound(OniEntry) - 1
+    Get 1, OniEntry(I).rDataPosition, ID4
+    If ID4 = AKEV.AGQRid Then
+       Get 1, OniEntry(I).rDataPosition, AGQR1
+       ReDim AGQR_E(AGQR1.NumEntries - 1)
+       Get 1, , AGQR_E
+       Exit For
+    End If
+  Next I
+
+  ReDim TexNames(TXMA1.NumEntries - 1)
+
+  For I = 0 To TXMA1.NumEntries - 1
+    For L = 0 To UBound(OniEntry) - 1
+      Get 1, OniEntry(L).rDataPosition, ID4
+      If ID4 = TXMA_E(I).TXMP_ID Then
+        TexNames(I) = OniEntry(L).szTagName + Ext
+        Exit For
+      End If
+    Next L
+  Next I
+
+Close
+'Ok
+' so we have: 3D points, Texture coordinates and list of polygons,
+' end reading, now convert data
+I = 0
+Open App.Path + "\lwo.tmp" For Binary As #11
+Form1.StatusBar1.SimpleText = "Status: Extracting LEVEL [Reading Polygons...]"
+Seek 11, 1
+
+'reading polygons.......
+
+NP = AGQG.NumEntries * 2
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  NP = NP - 2
+  Case Else
+    Select Case Mid$(GetPureFile(TexNames(AGQR_E(I).TexIndex)), 1, 5)
+     Case "_DOOR"
+       NP = NP - 2
+     Case Else
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(1))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(2))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(3))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(3))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(4))
+       Put 11, , TestSwapInt(AGQGEntry(I).VertIndex(1))
+    End Select
+  End Select
+Next I
+
+
+
+ReDim OniPol2(NP - 1)
+ReDim LwoP(NP - 1)
+Get 11, 1, OniPol2
+
+For I = 0 To NP - 1
+  LwoP(I).NumVe = ISItoMSI(3)
+  LwoP(I).P1 = OniPol2(I).P1
+  LwoP(I).P2 = OniPol2(I).P2
+  LwoP(I).P3 = OniPol2(I).P3
+  LwoP(I).Surfa = ISItoMSI(1)
+Next I
+
+I = Empty
+
+Close
+
+On Error Resume Next
+  Kill App.Path + "\*.tmp"
+On Error GoTo 0
+
+Form1.StatusBar1.SimpleText = "Status: Extracting LEVEL [Writing...]"
+Form1.ProgressBar1.Max = PNTA.NumEntries
+Form1.ProgressBar1.Value = 0
+If LevelType = 5 Or LevelType = 10 Then
+  FileName = GetPureFile(FileName) + ".raw"
+End If
+
+For I = 0 To PNTA.NumEntries - 1
+   If PNTAentry(I).X > 2000000.1 Then PNTAentry(I).X = 0
+   If PNTAentry(I).Y > 2000000.1 Then PNTAentry(I).Y = 0
+   If PNTAentry(I).Z > 2000000.1 Then PNTAentry(I).Z = 0
+   If PNTAentry(I).X < -2000000.1 Then PNTAentry(I).X = 0
+   If PNTAentry(I).Y < -2000000.1 Then PNTAentry(I).Y = 0
+   If PNTAentry(I).Z < -2000000.1 Then PNTAentry(I).Z = 0
+Next I
+
+Select Case LevelType
+Case 1
+
+Open FileName For Binary As #1
+  Put 1, , "FORM"
+  Put 1, , ISLtoMSL(12 + (PNTA.NumEntries * 12) + 8 + 6 + 8 + (NP * 10))
+  Put 1, , "LWOBPNTS"
+  Put 1, , ISLtoMSL(PNTA.NumEntries * 12)
+  For I = 0 To PNTA.NumEntries - 1
+    Put 1, , SwapFloat(PNTAentry(I).X)
+    Put 1, , SwapFloat(PNTAentry(I).Y)
+    Put 1, , SwapFloat(PNTAentry(I).Z)
+    Form1.ProgressBar1.Value = I
+  Next I
+  Put 1, , "SRFS"
+  Put 1, , ISLtoMSL(6)
+  Put 1, , "Level"
+  Put 1, , CByte(0)
+  Put 1, , "POLS"
+  Put 1, , ISLtoMSL(NP * 10)
+  Put 1, , LwoP
+Close
+Case 6
+
+' Convert Oni level to RAW 3D Binary
+Open GetPureFile(FileName) + ".rwb" For Binary As #1
+For I = 0 To AGQG.NumEntries - 1
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Z
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Z
+Next I
+
+Close
+Case 7
+
+' B3D
+Open GetPureFile(FileName) + ".b3d" For Binary As #1
+Put 1, , "Big3DbyOleg"
+Put 1, , CLng(1067030938)
+Put 1, , "POINTS  "
+Put 1, , CLng(PNTA.NumEntries)
+For I = 0 To PNTA.NumEntries - 1
+  Put 1, , PNTAentry(I).X
+  Put 1, , PNTAentry(I).Y
+  Put 1, , PNTAentry(I).Z
+Next I
+
+Put 1, , "POLYGONS"
+Put 1, , CLng(NP * 2)
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+    'nothing
+  Case Else
+    Select Case Mid$(GetPureFile(TexNames(AGQR_E(I).TexIndex)), 1, 5)
+     Case "_DOOR"
+       'nothing
+     Case Else
+       Put 1, , CLng(3)
+       Put 1, , AGQGEntry(I).VertIndex(1)
+       Put 1, , AGQGEntry(I).VertIndex(2)
+       Put 1, , AGQGEntry(I).VertIndex(3)
+       Put 1, , CLng(0)
+       Put 1, , CLng(3)
+       Put 1, , AGQGEntry(I).VertIndex(3)
+       Put 1, , AGQGEntry(I).VertIndex(4)
+       Put 1, , AGQGEntry(I).VertIndex(1)
+       Put 1, , CLng(0)
+    End Select
+End Select
+Next I
+Put 1, , CLng(0)
+Close
+
+Case 8
+
+'Delete shit from the Oni level
+numb = AGQG.NumEntries
+   ReDim Preserve PNTAentry(PNTA.NumEntries + 3)
+   PNTAentry(PNTA.NumEntries + 0).X = -9
+   PNTAentry(PNTA.NumEntries + 0).Y = 0
+   PNTAentry(PNTA.NumEntries + 0).Z = -3
+   PNTAentry(PNTA.NumEntries + 1).X = -9
+   PNTAentry(PNTA.NumEntries + 1).Y = 0
+   PNTAentry(PNTA.NumEntries + 1).Z = 8
+   PNTAentry(PNTA.NumEntries + 2).X = 11
+   PNTAentry(PNTA.NumEntries + 2).Y = 0
+   PNTAentry(PNTA.NumEntries + 2).Z = -3
+   PNTAentry(PNTA.NumEntries + 3).X = 11
+   PNTAentry(PNTA.NumEntries + 3).Y = 0
+   PNTAentry(PNTA.NumEntries + 3).Z = 8
+
+   If Form1.mnuDelGarbage.Checked = True Then
+   For I = 0 To AGQG.NumEntries - 1
+     Select Case Mid$(GetPureFile(TexNames(AGQR_E(I).TexIndex)), 1, 5)
+     Case "_DOOR"
+        AGQGEntry(I).VertIndex(1) = PNTA.NumEntries + 0
+        AGQGEntry(I).VertIndex(2) = PNTA.NumEntries + 1
+        AGQGEntry(I).VertIndex(3) = PNTA.NumEntries + 2
+        AGQGEntry(I).VertIndex(4) = PNTA.NumEntries + 3
+        'numb = numb - 1
+     End Select
+   Next I
+   End If
+
+   For I = 0 To AGQG.NumEntries - 1
+     Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+     Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+        AGQGEntry(I).VertIndex(1) = PNTA.NumEntries + 0
+        AGQGEntry(I).VertIndex(2) = PNTA.NumEntries + 1
+        AGQGEntry(I).VertIndex(3) = PNTA.NumEntries + 2
+        AGQGEntry(I).VertIndex(4) = PNTA.NumEntries + 3
+        numb = numb - 1
+     End Select
+   Next I
+
+'B3D + materials
+Open GetPureFile(FileName) + ".b3d" For Binary As #1
+Put 1, , "Big3DbyOleg"
+Put 1, , CLng(1067030938)
+Put 1, , "POINTS  "
+Put 1, , CLng(numb * 4)
+
+For I = 0 To AGQG.NumEntries - 1
+  ' Begin polygon
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(1)).Z
+
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(2)).Z
+
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(3)).Z
+
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).X
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Y
+  Put 1, , PNTAentry(AGQGEntry(I).VertIndex(4)).Z
+End Select
+  ' end polygon
+Next I
+
+Put 1, , "POLYGONS"
+Put 1, , CLng(numb * 2)
+L = 0
+ID4 = 0
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , CLng(3)
+  Put 1, , CLng(L)
+  Put 1, , CLng(L + 1)
+  Put 1, , CLng(L + 2)
+  Put 1, , CLng(ID4)
+  Put 1, , CLng(3)
+  Put 1, , CLng(L + 2)
+  Put 1, , CLng(L + 3)
+  Put 1, , CLng(L)
+  Put 1, , CLng(ID4)
+  ID4 = ID4 + 1
+  L = L + 4
+End Select
+Next I
+
+Put 1, , CLng(1)
+Put 1, , "TEX_UV  "
+Put 1, , CLng(numb * 4)
+L = 0
+
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(1)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(1)).Y
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(2)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(2)).Y
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(3)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(3)).Y
+  Put 1, , CLng(L)
+  L = L + 1
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(4)).X
+  Put 1, , TXCA_E(AGQGEntry(I).VertUVIndex(4)).Y
+End Select
+  'Put 1, , CSng((-TXCA_E(I).Y) + 1)
+Next I
+
+L = 0
+Put 1, , "MATERIAL"
+Put 1, , CLng(numb)
+For I = 0 To AGQG.NumEntries - 1
+Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+ Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+  'nothing
+ Case Else
+  Put 1, , CLng(1)
+  Put 1, , CLng(L)
+  Put 1, , CLng(Len(TexNames(AGQR_E(I).TexIndex)))
+  Put 1, , TexNames(AGQR_E(I).TexIndex)
+  L = L + 1
+End Select
+Next I
+Close
+
+Open GetPureFile(FileName) + ".tlist" For Binary As #4
+  For I = 0 To AGQR1.NumEntries - 1
+  Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+   'nothing
+  Case Else
+    Put 4, , AGQR_E(I).TexIndex
+  End Select
+  Next I
+Close
+
+Open GetPureFile(FileName) + ".txt" For Output As #4
+  Print #4, CStr(TXMA1.NumEntries)
+  For I = 0 To TXMA1.NumEntries - 1
+    Print #4, CStr(GetPureFile(TexNames(I)))
+  Next I
+Close
+
+If Form1.mnuB3DLight.Checked = True Then
+Open GetPureFile(FileName) + ".ltcs" For Binary As #4
+  For I = 0 To AGQR1.NumEntries - 1
+  Select Case GetPureFile(TexNames(AGQR_E(I).TexIndex))
+  Case "BLUEGRID02", "_DOOR_FRAME", "", "COLLISION"
+   'nothing
+  Case Else
+    Put 4, , AGQGEntry(I).LData_1
+    Put 4, , AGQGEntry(I).LData_2
+    Put 4, , AGQGEntry(I).LData_3
+    Put 4, , AGQGEntry(I).LData_4
+  End Select
+  Next I
+Close
+End If
+End Select
+
+Form1.ProgressBar1.Value = 0
+Form1.ProgressBar1.Max = UBound(OniEntry)
+
+Form1.StatusBar1.SimpleText = "OK"
+'Dispose
+I = Empty
+NP = Empty
+Erase LwoP
+Erase PNTAentry
+Erase OniPol2
+Erase AGQGEntry
+Erase AGQR_E
+Erase TXMA_E
+Erase TXCA_E
+Erase TexNames
+End Sub
Index: /oup/current/mkarchive.bat
===================================================================
--- /oup/current/mkarchive.bat	(revision 10)
+++ /oup/current/mkarchive.bat	(revision 10)
@@ -0,0 +1,49 @@
+SET RUNWINSCP=JA
+
+SET archivepath=oniunpacker
+SET srcpath=\Dokumente und Einstellungen\Administrator\Desktop\Oni\OniUnPacker
+SET target=C:\Dokumente und Einstellungen\Administrator\Desktop\%archivepath%.rar
+
+SET winrar=C:\Programme\WinRAR\rar.exe a -m5 -r -rr -s
+SET winscp=d:\programme\winscp\winscp3.exe
+
+c:
+cd %srcpath%
+md %archivepath%
+md %archivepath%\src
+md %archivepath%\StructDefs
+md %archivepath%\src\TFileTypeRegistration
+md %archivepath%\src\help
+
+copy /y TFileTypeRegistration\*.* "%archivepath%\src\TFileTypeRegistration"
+copy /y help\*.* "%archivepath%\src\help"
+copy /y *.ico "%archivepath%\src"
+copy /y *.bdsproj "%archivepath%\src"
+copy /y *.cfg "%archivepath%\src"
+copy /y *.dpr "%archivepath%\src"
+copy /y *.res "%archivepath%\src"
+copy /y *.dfm "%archivepath%\src"
+copy /y *.pas "%archivepath%\src"
+copy /y exe\StructDefs\*.txt "%archivepath%\StructDefs"
+copy /y *.txt "%archivepath%"
+copy /y *.dll "%archivepath%"
+copy /y exe\*.exe "%archivepath%"
+
+del "%target%"
+%winrar% "%target%" "%archivepath%"
+
+rmdir /s /q "%archivepath%"
+
+PAUSE
+
+
+copy /y changelog.txt "C:\Dokumente und Einstellungen\Administrator\Desktop\changelog.txt"
+
+
+if "%RUNWINSCP%" == "JA" GOTO WINSCP
+GOTO ENDE
+
+:WINSCP
+start %winscp%
+
+:ENDE
Index: /oup/current/old_sqlite/SQLite3.pas
===================================================================
--- /oup/current/old_sqlite/SQLite3.pas	(revision 10)
+++ /oup/current/old_sqlite/SQLite3.pas	(revision 10)
@@ -0,0 +1,120 @@
+unit SQLite3;
+
+{
+  Simplified interface for SQLite.
+  Updated for Sqlite 3 by Tim Anderson (tim@itwriting.com)
+  Note: NOT COMPLETE for version 3, just minimal functionality
+  Adapted from file created by Pablo Pissanetzky (pablo@myhtpc.net)
+  which was based on SQLite.pas by Ben Hochstrasser (bhoc@surfeu.ch)
+}
+
+interface
+
+const
+// Return values for sqlite3_exec() and sqlite3_step()
+
+SQLITE_OK   =        0;   // Successful result 
+SQLITE_ERROR =       1;   // SQL error or missing database 
+SQLITE_INTERNAL  =   2;   // An internal logic error in SQLite 
+SQLITE_PERM  =       3 ;  // Access permission denied 
+SQLITE_ABORT =       4;   // Callback routine requested an abort 
+SQLITE_BUSY  =       5;   // The database file is locked 
+SQLITE_LOCKED  =     6;   // A table in the database is locked 
+SQLITE_NOMEM =       7;   // A malloc() failed 
+SQLITE_READONLY  =   8;   // Attempt to write a readonly database 
+SQLITE_INTERRUPT  =  9;   // Operation terminated by sqlite3_interrupt()
+SQLITE_IOERR =      10;   // Some kind of disk I/O error occurred 
+SQLITE_CORRUPT =    11;   // The database disk image is malformed 
+SQLITE_NOTFOUND =   12;   // (Internal Only) Table or record not found 
+SQLITE_FULL    =    13;   // Insertion failed because database is full 
+SQLITE_CANTOPEN =   14;   // Unable to open the database file 
+SQLITE_PROTOCOL =   15;   // Database lock protocol error 
+SQLITE_EMPTY  =     16;   // Database is empty 
+SQLITE_SCHEMA  =    17;   // The database schema changed 
+SQLITE_TOOBIG   =   18;   // Too much data for one row of a table 
+SQLITE_CONSTRAINT = 19;   // Abort due to contraint violation 
+SQLITE_MISMATCH =   20;   // Data type mismatch 
+SQLITE_MISUSE  =    21;   // Library used incorrectly 
+SQLITE_NOLFS     =  22;   // Uses OS features not supported on host 
+SQLITE_AUTH   =     23;   // Authorization denied 
+SQLITE_FORMAT =     24;   // Auxiliary database format error 
+SQLITE_RANGE   =    25;   // 2nd parameter to sqlite3_bind out of range 
+SQLITE_NOTADB    =  26;   // File opened that is not a database file 
+SQLITE_ROW   =      100;  // sqlite3_step() has another row ready 
+SQLITE_DONE   =     101;  // sqlite3_step() has finished executing
+
+SQLITE_INTEGER  = 1;
+SQLITE_FLOAT  =  2;
+SQLITE_TEXT = 3;
+SQLITE_BLOB  =   4;
+SQLITE_NULL  =   5;
+ 
+type
+TSQLiteDB     = Pointer;
+TSQLiteResult = ^PChar;
+TSQLiteStmt = Pointer;
+
+function  SQLite3_Open           (dbname: PChar; var db: TSqliteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_open';
+function SQLite3_Close          (db: TSQLiteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_close';
+function  SQLite3_Exec           (db: TSQLiteDB; SQLStatement: PChar; CallbackPtr: Pointer; Sender: TObject; var ErrMsg: PChar): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_exec';
+function  SQLite3_Version        (): PChar; cdecl; external 'sqlite3.dll' name 'sqlite3_libversion';
+function  SQLite3_ErrMsg    (db: TSQLiteDB): PChar; cdecl; external 'sqlite3.dll' name 'sqlite3_errmsg';
+function SQLite3_ErrCode (db: TSQLiteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_errcode';
+procedure SQlite3_Free (P: PChar); cdecl; external 'sqlite3.dll' name 'sqlite3_free';
+function  SQLite3_GetTable       (db: TSQLiteDB; SQLStatement: PChar; var ResultPtr: TSQLiteResult; var RowCount: Cardinal; var ColCount: Cardinal; var ErrMsg: PChar): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_get_table';
+procedure SQLite3_FreeTable      (Table:TSQLiteResult ); cdecl; external 'sqlite3.dll' name 'sqlite3_free_table';
+function  SQLite3_Complete       (P: PChar): boolean; cdecl; external 'sqlite3.dll' name 'sqlite3_complete';
+function  SQLite3_LastInsertRowID(db: TSQLiteDB): int64; cdecl; external 'sqlite3.dll' name 'sqlite3_last_insert_rowid';
+procedure SQLite3_Interrupt         (db: TSQLiteDB); cdecl; external 'sqlite3.dll' name 'sqlite3_interrupt';
+procedure SQLite3_BusyHandler    (db: TSQLiteDB; CallbackPtr: Pointer; Sender: TObject); cdecl; external 'sqlite3.dll' name'sqlite3_busy_handler' ;
+procedure SQLite3_BusyTimeout    (db: TSQLiteDB; TimeOut: integer); cdecl; external 'sqlite3.dll' name 'sqlite3_busy_timeout';
+function  SQLite3_Changes        (db: TSQLiteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_changes';
+function  SQLite3_TotalChanges        (db: TSQLiteDB): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_total_changes';
+function SQLite3_Prepare (db: TSQLiteDB; SQLStatement: PChar; nBytes: integer; var hStmt: TSqliteStmt; var pzTail: PChar): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_prepare';
+function SQLite3_ColumnCount (hStmt: TSqliteStmt): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_column_count';
+function Sqlite3_ColumnName (hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external 'sqlite3.dll' name 'sqlite3_column_name';
+function Sqlite3_ColumnDeclType (hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external 'sqlite3.dll' name 'sqlite3_column_decltype';
+function Sqlite3_Step (hStmt: TSqliteStmt): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_step';
+function SQLite3_DataCount (hStmt: TSqliteStmt): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_data_count';
+
+function Sqlite3_ColumnBlob (hStmt: TSqliteStmt; ColNum: integer):pointer; cdecl; external 'sqlite3.dll' name 'sqlite3_column_blob';
+function Sqlite3_ColumnBytes (hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_column_bytes';
+function Sqlite3_ColumnDouble (hStmt: TSqliteStmt; ColNum: integer): double; cdecl; external 'sqlite3.dll' name 'sqlite3_column_double';
+function Sqlite3_ColumnInt (hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_column_int';
+function Sqlite3_ColumnText (hStmt: TSqliteStmt; ColNum: integer): pchar; cdecl; external 'sqlite3.dll' name 'sqlite3_column_text';
+function Sqlite3_ColumnType (hStmt: TSqliteStmt; ColNum: integer): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_column_type';
+ // function Sqlite3_ColumnInt64 (hStmt: TSqliteStmt; ColNum: integer): SqliteInt64; cdecl; external 'sqlite3.dll' name 'sqlite3_column_int64';
+function SQLite3_Finalize (hStmt: TSqliteStmt): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_finalize';
+function SQLite3_Reset (hStmt: TSqliteStmt): integer; cdecl; external 'sqlite3.dll' name 'sqlite3_reset';
+
+//
+// In the SQL strings input to sqlite3_prepare() and sqlite3_prepare16(),
+// one or more literals can be replace by a wildcard "?" or ":N:" where
+// N is an integer.  These value of these wildcard literals can be set
+// using the routines listed below.
+//
+// In every case, the first parameter is a pointer to the sqlite3_stmt
+// structure returned from sqlite3_prepare().  The second parameter is the
+// index of the wildcard.  The first "?" has an index of 1.  ":N:" wildcards
+// use the index N.
+//
+ // The fifth parameter to sqlite3_bind_blob(), sqlite3_bind_text(), and
+ //sqlite3_bind_text16() is a destructor used to dispose of the BLOB or
+//text after SQLite has finished with it.  If the fifth argument is the
+// special value SQLITE_STATIC, then the library assumes that the information
+// is in static, unmanaged space and does not need to be freed.  If the
+// fifth argument has the value SQLITE_TRANSIENT, then SQLite makes its
+// own private copy of the data.
+//
+// The sqlite3_bind_* routine must be called before sqlite3_step() after
+// an sqlite3_prepare() or sqlite3_reset().  Unbound wildcards are interpreted
+// as NULL.
+//
+
+function SQLite3_BindBlob(hStmt: TSqliteStmt; ParamNum: integer;
+ptrData: pointer; numBytes: integer; ptrDestructor: pointer): integer;
+cdecl; external 'sqlite3.dll' name 'sqlite3_bind_blob';
+
+implementation
+
+end.
Index: /oup/current/old_sqlite/SQLiteTable3.pas
===================================================================
--- /oup/current/old_sqlite/SQLiteTable3.pas	(revision 10)
+++ /oup/current/old_sqlite/SQLiteTable3.pas	(revision 10)
@@ -0,0 +1,885 @@
+unit SQLiteTable3;
+
+{
+  Simple classes for using SQLite's exec and get_table.
+
+  TSQLiteDatabase wraps the calls to open and close an SQLite database.
+  It also wraps SQLite_exec for queries that do not return a result set
+
+  TSQLiteTable wraps sqlite_get_table.
+  It allows accessing fields by name as well as index and can step through a
+  result set with the Next procedure.
+
+  Adapted by Tim Anderson (tim@itwriting.com)
+  Originally created by Pablo Pissanetzky (pablo@myhtpc.net)
+}
+
+interface
+
+uses
+  Windows, SQLite3, Classes, Sysutils;
+
+const
+  dtStr = 0;
+  dtInt = 1;
+  dtBool = 2;
+  dtNumeric = 3;
+  dtBlob = 4;
+
+type
+
+  ESQLiteException = class(Exception)
+  private
+  public
+  end;
+
+  TSQLiteTable = class;
+
+  TSQLiteDatabase = class
+  private
+    fDB: TSQLiteDB;
+    fInTrans: Boolean;
+    procedure RaiseError(s: string; SQL: string);
+
+  public
+    constructor Create(const FileName: string);
+    destructor Destroy; override;
+    function GetTable(const SQL: string): TSQLiteTable;
+    procedure ExecSQL(const SQL: string);
+    procedure UpdateBlob(const SQL: string; BlobData: TStream);
+    procedure BeginTransaction;
+    procedure Commit;
+    procedure Rollback;
+    function TableExists(TableName: string): boolean;
+    function GetLastInsertRowID: int64;
+
+  published
+    property isTransactionOpen: boolean read fInTrans;
+
+  end;
+
+  TSQLiteTable = class
+  private
+    fResults: TList;
+    fRowCount: Cardinal;
+    fColCount: Cardinal;
+    fCols: TStringList;
+    fColTypes: TList;
+    fRow: Cardinal;
+
+    function GetFields(I: Integer): string;
+    function GetEOF: Boolean;
+    function GetBOF: Boolean;
+    function GetColumns(I: Integer): string;
+    function GetFieldByName(FieldName: string): string;
+    function GetFieldIndex(FieldName: string): integer;
+    function GetCount: Integer;
+    function GetCountResult: Integer;
+
+
+  public
+    constructor Create(DB: TSQLiteDatabase; const SQL: string);
+    destructor Destroy; override;
+    function FieldAsInteger(FieldName: string): integer;
+    function FieldAsBool(FieldName: string): boolean;
+    function FieldAsBlob(FieldName: string): TMemoryStream;
+    function FieldAsBlobText(FieldName: string): string;
+    function FieldIsNull(FieldName: string): boolean;
+    function FieldAsString(FieldName: string): string;
+    function FieldAsDouble(FieldName: string): double;
+{    function FieldAsInteger(I: integer): integer;
+    function FieldAsBool(I: integer): boolean;
+    function FieldAsBlob(I: Integer): TMemoryStream;
+    function FieldAsBlobText(I: Integer): string;
+    function FieldIsNull(I: integer): boolean;
+    function FieldAsString(I: Integer): string;
+    function FieldAsDouble(I: Integer): double;
+}    function Next: Boolean;
+    function Previous: Boolean;
+    property EOF: Boolean read GetEOF;
+    property BOF: Boolean read GetBOF;
+    property Fields[I: Integer]: string read GetFields;
+    property FieldByName[FieldName: string]: string read GetFieldByName;
+    property FieldIndex[FieldName: string]: integer read GetFieldIndex;
+    property Columns[I: Integer]: string read GetColumns;
+    property ColCount: Cardinal read fColCount;
+    property RowCount: Cardinal read fRowCount;
+    property Row: Cardinal read fRow;
+    function MoveFirst: boolean;
+    function MoveLast: boolean;
+
+
+    property Count: Integer read GetCount;
+
+    // The property CountResult is used when you execute count(*) queries.
+    // It returns 0 if the result set is empty or the value of the
+    // first field as an integer.
+    property CountResult: Integer read GetCountResult;
+  end;
+
+
+procedure DisposePointer(ptr: pointer); cdecl;
+
+implementation
+
+uses
+  strutils;
+
+
+procedure DisposePointer(ptr: pointer); cdecl;
+begin
+
+  if assigned(ptr) then
+  begin freemem(ptr) end;
+
+end;
+
+//------------------------------------------------------------------------------
+// TSQLiteDatabase
+//------------------------------------------------------------------------------
+
+constructor TSQLiteDatabase.Create(const FileName: string);
+var
+  Msg: pchar;
+  iResult: integer;
+begin
+  inherited Create;
+
+  self.fInTrans := false;
+
+  Msg := nil;
+  try
+    iResult := SQLite3_Open(PChar(FileName), Fdb);
+
+    if iResult <> SQLITE_OK then
+    begin
+      if Assigned(Fdb) then
+      begin
+        Msg := Sqlite3_ErrMsg(Fdb);
+        raise ESqliteException.CreateFmt('Failed to open database "%s" : %s', [FileName, Msg]);
+      end
+      else
+      begin raise ESqliteException.CreateFmt('Failed to open database "%s" : unknown error', [FileName]) end;
+    end;
+
+    //set a few configs
+    self.ExecSQL('PRAGMA SYNCHRONOUS=NORMAL;');
+
+    //this pragma not recommended and may disappear in future
+    //sqlite versions
+    //self.ExecSQL('PRAGMA full_column_names = 1;');
+
+  finally
+    if Assigned(Msg) then
+    begin SQLite3_Free(Msg) end;
+  end;
+
+
+end;
+
+
+//..............................................................................
+
+destructor TSQLiteDatabase.Destroy;
+begin
+
+  if self.fInTrans then
+  begin self.ExecSQL('ROLLBACK;') end; //assume rollback
+
+  if Assigned(fDB) then
+  begin SQLite3_Close(fDB) end;
+
+  inherited;
+end;
+
+function TSQLiteDatabase.GetLastInsertRowID: int64;
+begin
+  result := Sqlite3_LastInsertRowID(self.fDB);
+end;
+
+//..............................................................................
+
+procedure TSQLiteDatabase.RaiseError(s: string; SQL: string);
+//look up last error and raise and exception with an appropriate message
+var
+  Msg: PChar;
+begin
+
+  Msg := nil;
+
+  if sqlite3_errcode(self.fDB) <> SQLITE_OK then
+    Msg := sqlite3_errmsg(self.fDB);
+
+  IF Pos('DROP TABLE ',SQL)>0 THEN Exit;
+
+  if Msg <> nil then
+    raise ESqliteException.CreateFmt(s + ' "%s" : %s', [SQL, Msg])
+  else
+    raise ESqliteException.CreateFmt(s, [SQL, 'No message']);
+
+end;
+
+procedure TSQLiteDatabase.ExecSQL(const SQL: string);
+var
+  Stmt: TSQLiteStmt;
+  NextSQLStatement: Pchar;
+  iStepResult: integer;
+begin
+  try
+
+    if Sqlite3_Prepare(self.fDB, PChar(SQL), -1, Stmt, NextSQLStatement) <> SQLITE_OK then
+    begin RaiseError('Error executing SQL', SQL) end;
+
+    if (Stmt = nil) then
+    begin RaiseError('Could not prepare SQL statement', SQL) end;
+
+    iStepResult := Sqlite3_step(Stmt);
+
+    if (iStepResult <> SQLITE_DONE) then
+    begin RaiseError('Error executing SQL statement', SQL) end;
+
+  finally
+
+    if Assigned(Stmt) then
+    begin Sqlite3_Finalize(stmt) end;
+
+  end;
+end;
+
+procedure TSQLiteDatabase.UpdateBlob(const SQL: string; BlobData: TStream);
+var
+  iSize: integer;
+  ptr: pointer;
+  Stmt: TSQLiteStmt;
+  Msg: Pchar;
+  NextSQLStatement: Pchar;
+  iStepResult: integer;
+  iBindResult: integer;
+begin
+//expects SQL of the form 'UPDATE MYTABLE SET MYFIELD = ? WHERE MYKEY = 1'
+
+  if pos('?', SQL) = 0 then
+  begin RaiseError('SQL must include a ? parameter', SQL) end;
+
+  Msg := nil;
+  try
+
+    if Sqlite3_Prepare(self.fDB, PChar(SQL), -1, Stmt, NextSQLStatement) <> SQLITE_OK then
+    begin RaiseError('Could not prepare SQL statement', SQL) end;
+
+    if (Stmt = nil) then
+    begin RaiseError('Could not prepare SQL statement', SQL) end;
+
+//now bind the blob data
+    iSize := BlobData.size;
+
+    GetMem(ptr, iSize);
+
+    if (ptr = nil) then
+    begin raise ESqliteException.CreateFmt('Error getting memory to save blob', [SQL, 'Error']) end;
+
+    BlobData.position := 0;
+    BlobData.Read(ptr^, iSize);
+
+    iBindResult := SQLite3_BindBlob(stmt, 1, ptr, iSize, @DisposePointer);
+
+    if iBindResult <> SQLITE_OK then
+    begin RaiseError('Error binding blob to database', SQL) end;
+
+    iStepResult := Sqlite3_step(Stmt);
+
+    if (iStepResult <> SQLITE_DONE) then
+    begin RaiseError('Error executing SQL statement', SQL) end;
+
+  finally
+
+    if Assigned(Stmt) then
+    begin Sqlite3_Finalize(stmt) end;
+
+    if Assigned(Msg) then
+    begin SQLite3_Free(Msg) end;
+  end;
+
+end;
+
+//..............................................................................
+
+function TSQLiteDatabase.GetTable(const SQL: string): TSQLiteTable;
+begin
+  Result := TSQLiteTable.Create(Self, SQL);
+end;
+
+procedure TSQLiteDatabase.BeginTransaction;
+begin
+  if not self.fInTrans then
+  begin
+    self.ExecSQL('BEGIN TRANSACTION;');
+    self.fInTrans := true;
+  end
+  else
+  begin raise ESqliteException.Create('Transaction already open') end;
+end;
+
+procedure TSQLiteDatabase.Commit;
+begin
+  self.ExecSQL('COMMIT;');
+  self.fInTrans := false;
+end;
+
+procedure TSQLiteDatabase.Rollback;
+begin
+  self.ExecSQL('ROLLBACK;');
+  self.fInTrans := false;
+end;
+
+function TSQLiteDatabase.TableExists(TableName: string): boolean;
+var
+  sql: string;
+  ds: TSqliteTable;
+begin
+//returns true if table exists in the database
+  sql := 'select [sql] from sqlite_master where [type] = ''table'' and lower(name) = ''' + lowercase(TableName) + ''' ';
+
+  try
+
+    ds := self.GetTable(sql);
+
+    result := (ds.Count > 0);
+
+  finally
+
+    freeandnil(ds);
+
+  end;
+
+end;
+
+
+//------------------------------------------------------------------------------
+// TSQLiteTable
+//------------------------------------------------------------------------------
+
+constructor TSQLiteTable.Create(DB: TSQLiteDatabase; const SQL: string);
+var
+  Stmt: TSQLiteStmt;
+  NextSQLStatement: Pchar;
+  iStepResult: integer;
+
+  ptr: pointer;
+  iNumBytes: integer;
+  thisBlobValue: TMemoryStream;
+  thisStringValue: pstring;
+  thisBoolValue: pBoolean;
+  thisDoubleValue: pDouble;
+  thisIntValue: pInteger;
+  thisColType: pInteger;
+  i: integer;
+  DeclaredColType: Pchar;
+  ActualColType: integer;
+  ptrValue: Pchar;
+
+begin
+
+  try
+
+    self.fRowCount := 0;
+    self.fColCount := 0;
+
+//if there are several SQL statements in SQL, NextSQLStatment points to the
+//beginning of the next one. Prepare only prepares the first SQL statement.
+
+    if Sqlite3_Prepare(Db.fDB, PChar(SQL), -1, Stmt, NextSQLStatement) <> SQLITE_OK then
+    begin Db.RaiseError('Error executing SQL', SQL) end;
+
+    if (Stmt = nil) then
+    begin Db.RaiseError('Could not prepare SQL statement', SQL) end;
+
+    iStepResult := Sqlite3_step(Stmt);
+
+    while (iStepResult <> SQLITE_DONE) do
+    begin
+
+      case iStepResult of
+        SQLITE_ROW:
+          begin
+
+            inc(fRowCount);
+
+            if (fRowCount = 1) then
+            begin
+     //get data types
+              fCols := TStringList.Create;
+              fCols.CaseSensitive := False;
+              fColTypes := TList.Create;
+
+              fColCount := SQLite3_ColumnCount(stmt);
+
+              for i := 0 to Pred(fColCount) do
+              begin
+                fCols.Add(Sqlite3_ColumnName(stmt, i));
+              end;
+
+              for i := 0 to Pred(fColCount) do
+              begin
+
+                new(thisColType);
+                DeclaredColType := Sqlite3_ColumnDeclType(stmt, i);
+
+                if DeclaredColType = nil then begin
+                //use the actual column type instead
+                //seems to be needed for last_insert_rowid
+                  thisColType^ := Sqlite3_ColumnType(stmt, i);
+                end else begin
+                  DeclaredColType := strupper(DeclaredColType);
+                  
+                  if DeclaredColType = 'INTEGER' then
+                  begin thisColType^ := dtInt end
+                  else
+                    if DeclaredColType = 'BOOLEAN' then
+                    begin thisColType^ := dtBool end
+                    else
+                      if (DeclaredColType = 'NUMERIC') or (DeclaredColType = 'FLOAT') or (DeclaredColType = 'DOUBLE') then
+                      begin thisColType^ := dtNumeric end
+                      else
+                        if DeclaredColType = 'BLOB' then
+                        begin thisColType^ := dtBlob end
+                        else
+                        begin thisColType^ := dtStr end;
+                  end;
+
+                fColTypes.Add(thiscoltype);
+              end;
+
+              fResults := TList.Create;
+
+            end;
+
+     //get column values
+            for i := 0 to Pred(ColCount) do
+            begin
+
+              ActualColType := Sqlite3_ColumnType(stmt, i);
+              if (ActualColType = SQLITE_NULL) then
+              begin fResults.Add(nil) end
+              else
+              begin
+                if pInteger(fColTypes[i])^ = dtInt then
+                begin
+                  new(thisintvalue);
+                  thisintvalue^ := Sqlite3_ColumnInt(stmt, i);
+                  fResults.Add(thisintvalue);
+                end
+                else
+                  if pInteger(fColTypes[i])^ = dtBool then
+                  begin
+                    new(thisboolvalue);
+                    thisboolvalue^ := not (Sqlite3_ColumnInt(stmt, i) = 0);
+                    fResults.Add(thisboolvalue);
+                  end
+                  else
+                    if pInteger(fColTypes[i])^ = dtNumeric then
+                    begin
+                      new(thisdoublevalue);
+                      thisdoublevalue^ := Sqlite3_ColumnDouble(stmt, i);
+                      fResults.Add(thisdoublevalue);
+                    end
+                    else
+                      if pInteger(fColTypes[i])^ = dtBlob then
+                      begin
+                        iNumBytes := Sqlite3_ColumnBytes(stmt, i);
+
+                        if iNumBytes = 0 then
+                        begin thisblobvalue := nil end
+                        else
+                        begin
+                          thisblobvalue := TMemoryStream.Create;
+                          thisblobvalue.position := 0;
+                          ptr := Sqlite3_ColumnBlob(stmt, i);
+                          thisblobvalue.writebuffer(ptr^, iNumBytes);
+                        end;
+                        fResults.Add(thisblobvalue);
+
+                      end
+                      else
+                      begin
+                        new(thisstringvalue);
+                        ptrValue := Sqlite3_ColumnText(stmt, i);
+                        setstring(thisstringvalue^, ptrvalue, strlen(ptrvalue));
+                        fResults.Add(thisstringvalue);
+                      end;
+              end;
+
+            end;
+
+
+
+          end;
+
+        SQLITE_BUSY:
+          begin raise ESqliteException.CreateFmt('Could not prepare SQL statement', [SQL, 'SQLite is Busy']) end;
+      else
+        begin Db.RaiseError('Could not retrieve data', SQL) end;
+      end;
+
+      iStepResult := Sqlite3_step(Stmt);
+
+    end;
+
+    fRow := 0;
+
+  finally
+    if Assigned(Stmt) then
+    begin Sqlite3_Finalize(stmt) end;
+  end;
+
+end;
+
+//..............................................................................
+
+destructor TSQLiteTable.Destroy;
+var i: integer;
+  iColNo: integer;
+begin
+
+
+  if Assigned(fResults) then
+  begin for i := 0 to fResults.Count - 1 do
+    begin
+    //check for blob type
+      iColNo := (i mod fColCount);
+      case pInteger(self.fColTypes[iColNo])^ of
+      dtBlob:
+          begin
+          TMemoryStream(fResults[i]).free;
+          end;
+      dtStr:
+          begin
+           if fResults[i] <> nil then
+           begin
+               setstring(string(fResults[i]^), nil, 0);
+               dispose(fResults[i]);
+           end;
+          end;
+      else
+        begin
+        dispose(fResults[i])
+        end;
+      end;
+    end;
+    fResults.Free;
+   end;
+
+    if Assigned(fCols) then
+    begin fCols.Free end;
+
+    if Assigned(fColTypes) then
+    begin for i := 0 to fColTypes.Count - 1 do
+      begin
+        dispose(fColTypes[i]);
+      end end;
+    fColTypes.Free;
+    inherited;
+  end;
+
+//..............................................................................
+
+function TSQLiteTable.GetColumns(I: Integer): string;
+begin
+  Result := fCols[I];
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetCountResult: Integer;
+begin
+  if not EOF then
+  begin Result := StrToInt(Fields[0]) end
+  else
+  begin Result := 0 end;
+end;
+
+function TSQLiteTable.GetCount: Integer;
+begin
+  Result := FRowCount;
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetEOF: Boolean;
+begin
+  Result := fRow >= fRowCount;
+end;
+
+function TSQLiteTable.GetBOF: Boolean;
+begin
+  Result := fRow <= 0;
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetFieldByName(FieldName: string): string;
+begin
+  Result := GetFields(self.GetFieldIndex(FieldName));
+end;
+
+function TSQLiteTable.GetFieldIndex(FieldName: string): integer;
+begin
+
+  if (fCols = nil) then
+  begin
+    raise ESqliteException.Create('Field ' + fieldname + ' Not found. Empty dataset');
+    exit;
+  end;
+
+  if (fCols.count = 0) then
+  begin
+    raise ESqliteException.Create('Field ' + fieldname + ' Not found. Empty dataset');
+    exit;
+  end;
+
+  result := fCols.IndexOf(FieldName);
+
+  if (result < 0) then
+  begin raise ESqliteException.Create('Field not found in dataset: ' + fieldname) end;
+
+end;
+
+//..............................................................................
+
+function TSQLiteTable.GetFields(I: Integer): string;
+var
+  thisvalue: pstring;
+  ptr: pointer;
+  thisboolvalue: pBoolean;
+  thistype: integer;
+begin
+  Result := '';
+
+  if EOF then
+  begin raise ESqliteException.Create('Table is at End of File') end;
+
+//integer and boolean types are not stored in the resultset
+//as strings, so they should be retrieved using the type-specific
+//methods
+
+  thistype := pInteger(self.fColTypes[I])^;
+
+  if (thistype = dtInt) or (thistype = dtNumeric) or (thistype = dtBlob) then
+  begin
+    ptr := self.fResults[(self.frow * self.fColCount) + I];
+
+    if ptr <> nil then
+    begin
+      raise ESqliteException.Create('Use the specific methods for integer, numeric or blob fields');
+    end;
+
+  end
+  else
+    if pInteger(self.fColTypes[I])^ = dtBool then
+    begin
+      thisboolvalue := self.fResults[(self.frow * self.fColCount) + I];
+      if thisboolvalue <> nil then
+      begin if thisboolvalue^ then
+        begin result := '1' end
+        else
+        begin result := '0' end end;
+    end
+
+    else
+
+    begin
+
+      thisvalue := self.fResults[(self.frow * self.fColCount) + I];
+      if (thisvalue <> nil) then
+      begin Result := thisvalue^ end
+      else
+      begin Result := '' end; //return empty string
+    end;
+
+end;
+
+function TSqliteTable.FieldAsBlob(FieldName: string): TMemoryStream;
+var
+  i: Integer;
+begin
+
+  if EOF then
+  begin raise ESqliteException.Create('Table is at End of File') end;
+
+  i:=Self.FieldIndex[FieldName];
+
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+  begin result := nil end
+  else
+    if pInteger(self.fColTypes[I])^ = dtBlob then
+    begin result := TMemoryStream(self.fResults[(self.frow * self.fColCount) + I]) end
+    else
+    begin raise ESqliteException.Create('Not a Blob field') end;
+end;
+
+function TSqliteTable.FieldAsBlobText(FieldName: string): string;
+var
+  MemStream: TMemoryStream;
+  Buffer: PChar;
+begin
+  result := '';
+
+  MemStream := self.FieldAsBlob(FieldName);
+
+  if MemStream <> nil then
+  begin if MemStream.Size > 0 then
+    begin
+      MemStream.position := 0;
+
+      Buffer := stralloc(MemStream.Size + 1);
+      MemStream.readbuffer(Buffer[0], MemStream.Size);
+      (Buffer + MemStream.Size)^ := chr(0);
+      SetString(Result, Buffer, MemStream.size);
+      strdispose(Buffer);
+    end end;
+
+end;
+
+
+function TSqliteTable.FieldAsInteger(FieldName: string): integer;
+var
+  i: Integer;
+begin
+
+  if EOF then
+  begin raise ESqliteException.Create('Table is at End of File') end;
+
+  i:=Self.FieldIndex[FieldName];
+
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+  begin result := 0 end
+  else
+    if pInteger(self.fColTypes[I])^ = dtInt then
+    begin result := pInteger(self.fResults[(self.frow * self.fColCount) + I])^ end
+    else
+      if pInteger(self.fColTypes[I])^ = dtNumeric then
+      begin result := trunc(strtofloat(pString(self.fResults[(self.frow * self.fColCount) + I])^)) end
+      else
+      begin raise ESqliteException.Create('Not an integer or numeric field') end;
+
+end;
+
+function TSqliteTable.FieldAsDouble(FieldName: string): double;
+var
+  i: Integer;
+begin
+
+  if EOF then
+  begin raise ESqliteException.Create('Table is at End of File') end;
+
+  i:=Self.FieldIndex[FieldName];
+
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+  begin result := 0 end
+  else
+    if pInteger(self.fColTypes[I])^ = dtInt then
+    begin result := pInteger(self.fResults[(self.frow * self.fColCount) + I])^ end
+    else
+      if pInteger(self.fColTypes[I])^ = dtNumeric then
+      begin result := pDouble(self.fResults[(self.frow * self.fColCount) + I])^ end
+      else
+      begin raise ESqliteException.Create('Not an integer or numeric field') end;
+
+end;
+
+function TSqliteTable.FieldAsBool(FieldName: string): boolean;
+var
+  i: Integer;
+begin
+
+  if EOF then
+  begin raise ESqliteException.Create('Table is at End of File') end;
+
+  i:=Self.FieldIndex[FieldName];
+
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+  begin result := false end
+  else
+    if pInteger(self.fColTypes[I])^ = dtBool then
+    begin result := pBoolean(self.fResults[(self.frow * self.fColCount) + I])^ end
+    else
+    begin raise ESqliteException.Create('Not a boolean field') end;
+end;
+
+function TSqliteTable.FieldAsString(FieldName: string): string;
+var
+  i: Integer;
+begin
+
+  if EOF then
+  begin raise ESqliteException.Create('Table is at End of File') end;
+
+  i:=Self.FieldIndex[FieldName];
+
+  if (self.fResults[(self.frow * self.fColCount) + I] = nil) then
+  begin result := '' end
+  else
+  begin result := self.GetFields(I) end;
+
+end;
+
+function TSqliteTable.FieldIsNull(FieldName: string): boolean;
+var
+  thisvalue: pointer;
+  i: Integer;
+begin
+
+  if EOF then
+  begin raise ESqliteException.Create('Table is at End of File') end;
+
+  i:=Self.FieldIndex[FieldName];
+
+  thisvalue := self.fResults[(self.frow * self.fColCount) + I];
+  result := (thisvalue = nil);
+end;
+
+//..............................................................................
+
+function TSQLiteTable.Next: boolean;
+begin
+  result := false;
+  if not EOF then
+  begin
+    Inc(fRow);
+    result := true;
+  end;
+end;
+
+function TSQLiteTable.Previous: boolean;
+begin
+  result := false;
+  if not BOF then
+  begin
+    Dec(fRow);
+    result := true;
+  end;
+end;
+
+function TSQLiteTable.MoveFirst: boolean;
+begin
+  result := false;
+  if self.fRowCount > 0 then
+  begin
+    fRow := 0;
+    result := true;
+  end;
+end;
+
+function TSQLiteTable.MoveLast: boolean;
+begin
+  result := false;
+  if self.fRowCount > 0 then
+  begin
+    fRow := fRowCount - 1;
+    result := true;
+  end;
+end;
+
+
+end.
+
Index: /oup/current/old_sqlite/Unit10_leveldb.dfm
===================================================================
--- /oup/current/old_sqlite/Unit10_leveldb.dfm	(revision 10)
+++ /oup/current/old_sqlite/Unit10_leveldb.dfm	(revision 10)
@@ -0,0 +1,61 @@
+object Form10: TForm10
+  Left = 0
+  Top = 0
+  BorderStyle = bsNone
+  Caption = 'Creating DB'
+  ClientHeight = 90
+  ClientWidth = 401
+  Color = clBtnFace
+  Font.Charset = DEFAULT_CHARSET
+  Font.Color = clWindowText
+  Font.Height = -11
+  Font.Name = 'Tahoma'
+  Font.Style = []
+  OldCreateOrder = False
+  Position = poScreenCenter
+  PixelsPerInch = 96
+  TextHeight = 13
+  object group_progress: TGroupBox
+    Left = 0
+    Top = 0
+    Width = 400
+    Height = 89
+    Caption = 'Progress ...'
+    TabOrder = 0
+    object lbl_progress: TLabel
+      Left = 2
+      Top = 32
+      Width = 396
+      Height = 17
+      Align = alTop
+      AutoSize = False
+    end
+    object lbl_estimation: TLabel
+      Left = 2
+      Top = 49
+      Width = 396
+      Height = 17
+      Align = alTop
+      AutoSize = False
+      Caption = 'Estimated finishing time:'
+    end
+    object progress: TProgressBar
+      Left = 2
+      Top = 15
+      Width = 396
+      Height = 17
+      Align = alTop
+      Smooth = True
+      TabOrder = 0
+    end
+    object btn_abortok: TButton
+      Left = 3
+      Top = 64
+      Width = 60
+      Height = 22
+      Caption = 'Abort...'
+      TabOrder = 1
+      OnClick = btn_abortokClick
+    end
+  end
+end
Index: /oup/current/old_sqlite/Unit10_leveldb.pas
===================================================================
--- /oup/current/old_sqlite/Unit10_leveldb.pas	(revision 10)
+++ /oup/current/old_sqlite/Unit10_leveldb.pas	(revision 10)
@@ -0,0 +1,986 @@
+UNIT Unit10_leveldb;
+INTERFACE
+USES
+  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
+  Dialogs, ComCtrls, StdCtrls;
+
+TYPE
+  TForm10 = Class(TForm)
+    group_progress: TGroupBox;
+    progress: TProgressBar;
+    lbl_progress: TLabel;
+    btn_abortok: TButton;
+    lbl_estimation: TLabel;
+    PROCEDURE btn_abortokClick(Sender: TObject);
+  PRIVATE
+    PROCEDURE HandleFile(ext:String; fileid:LongWord; dir_dat2db:Boolean);
+    PROCEDURE stop_convert;
+  PUBLIC
+    PROCEDURE CreateDatabase(FileName:String);
+  END;
+
+
+VAR
+  Form10: TForm10;
+
+IMPLEMENTATION
+{$R *.dfm}
+USES SQLiteTable3, Unit1_main, Unit2_functions, Unit3_data;
+TYPE
+  THandler=PROCEDURE(fileid:LongWord; dir_dat2db:Boolean);
+  TConvertHandlers=RECORD
+    Ext:String[4];
+    needed:Boolean;
+    Handler:THandler;
+  END;
+VAR
+  ConvertHandlers:Array OF TConvertHandlers;
+  loaded_filename:String;
+  converting:Boolean=False;
+  abort:Boolean=False;
+  filestream:TFileStream;
+  dat_stream,mem:TMemoryStream;
+
+PROCEDURE TForm10.HandleFile;
+  VAR
+    i:Byte;
+  BEGIN
+    FOR i:=1 TO Length(ConvertHandlers) DO
+      IF UpperCase(ConvertHandlers[i].Ext)=UpperCase(ext) THEN
+        IF ConvertHandlers[i].needed THEN BEGIN
+          ConvertHandlers[i].Handler(fileid, dir_dat2db);
+          Break;
+        END ELSE
+          Break;
+  END;
+
+PROCEDURE TForm10.CreateDatabase(FileName:String);
+  VAR
+    i,j:LongWord;
+    temps,temps2:String;
+    data:Tdata;
+    absolutebegintime,begintime:Double;
+    step:Byte;
+  CONST
+    steps:Byte=4;
+  PROCEDURE DoStep(stepname:String);
+    BEGIN
+      Inc(step);
+      IF stepname<>'FIN' THEN
+        group_progress.Caption:='Creating DB (Step '+IntToStr(step)+'/'+IntToStr(steps)+': '+stepname+')'
+      ELSE
+        group_progress.Caption:='Creating DB (FINISHED)';
+    END;
+  BEGIN
+    Form10.Visible:=True;
+    Form1.Visible:=False;
+    step:=0;
+    converting:=True;
+    abort:=False;
+    loaded_filename:=FileName;
+    btn_abortok.Caption:='&Abort...';
+    btn_abortok.Default:=False;
+
+    absolutebegintime:=Time;
+
+    DB:=TSQLiteDatabase.Create(FileName);
+    DB.ExecSQL('PRAGMA synchronous = 0;');
+    DB.ExecSQL('PRAGMA temp_store = 2;');
+    DB.ExecSQL('DROP TABLE globals;');
+    DB.ExecSQL('DROP TABLE linkmap;');
+    DB.ExecSQL('DROP TABLE rawmap;');
+    DB.ExecSQL('DROP TABLE datfiles;');
+    DB.ExecSQL('DROP TABLE extlist;');
+    DB.ExecSQL('VACUUM;');
+
+    DoStep('Creating tables');
+    progress.Position:=0;
+    lbl_progress.Caption:='';
+    lbl_estimation.Caption:='Estimated finishing time: unknown';
+    Application.ProcessMessages;
+
+    DB.ExecSQL('CREATE TABLE globals  (id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR (20), value VARCHAR (50) );');
+    DB.ExecSQL('CREATE TABLE linkmap  (id INTEGER PRIMARY KEY AUTOINCREMENT, src_id INTEGER, src_link_offset INTEGER, target_id INTEGER );');
+    DB.ExecSQL('CREATE TABLE rawmap   (id INTEGER PRIMARY KEY AUTOINCREMENT, src_id INTEGER, src_link_offset INTEGER, data BLOB );');
+    DB.ExecSQL('CREATE TABLE datfiles (id INTEGER PRIMARY KEY, extension VARCHAR(4), name VARCHAR(128), contenttype INTEGER, data BLOB );');
+    DB.ExecSQL('CREATE TABLE extlist  (id INTEGER PRIMARY KEY AUTOINCREMENT, ext VARCHAR(4), ident VARCHAR(16) );');
+
+    DB.ExecSQL('INSERT INTO globals (name,value) VALUES ("dbversion","'+dbversion+'");');
+    SetLength(data,Length(dat_header.Ident));
+    FOR i:=0 TO High(dat_header.Ident) DO data[i]:=dat_header.Ident[i];
+    temps:=CreateHexString(data,True);
+    DB.ExecSQL('INSERT INTO globals (name,value) VALUES ("ident","'+temps+'");');
+    data:=LoadDatFile(0);
+    i:=data[7];
+    i:=i DIV 2;
+    DB.ExecSQL('INSERT INTO globals (name,value) VALUES ("lvl","'+IntToStr(i)+'");');
+
+    DoStep('Writing extensionslist');
+    progress.Max:=dat_header.Extensions;
+    Application.ProcessMessages;
+
+    FOR i:=0 TO dat_header.Extensions-1 DO BEGIN
+      SetLength(data,Length(dat_extensionsmap[i].Ident));
+      FOR j:=0 TO High(dat_extensionsmap[i].Ident) DO data[j]:=dat_extensionsmap[i].Ident[j];
+      temps:=CreateHexString(data,True);
+      temps2:=dat_extensionsmap[i].Extension[3]+dat_extensionsmap[i].Extension[2]+dat_extensionsmap[i].Extension[1]+dat_extensionsmap[i].Extension[0];
+      DB.ExecSQL('INSERT INTO extlist (ext,ident) VALUES ("'+temps2+'","'+temps+'");');
+      progress.Position:=i;
+      lbl_progress.Caption:='Extensions done: '+IntToStr(i)+'/'+IntToStr(dat_header.Extensions);
+      Application.ProcessMessages;
+      IF abort THEN BEGIN
+        stop_convert;
+        Exit;
+      END;
+    END;
+    lbl_progress.Caption:='';
+
+    DoStep('Loading .dat into memory');
+    Application.ProcessMessages;
+
+    progress.Position:=0;
+    lbl_progress.Caption:='Files done: '+IntToStr(0)+'/'+IntToStr(dat_header.Files);
+    lbl_estimation.Caption:='Estimated finishing time: unknown';
+
+    filestream:=TFileStream.Create(dat_filename, fmOpenRead);
+    dat_stream:=TMemoryStream.Create;
+    dat_stream.CopyFrom(filestream,0);
+    dat_stream.Seek(0,soFromBeginning);
+    filestream.Free;
+
+    progress.Max:=dat_header.Files;
+    begintime:=Time;
+    DoStep('Writing .dat-fileslist');
+    Application.ProcessMessages;
+
+    FOR i:=0 TO dat_header.Files-1 DO BEGIN
+      DB.ExecSQL('INSERT INTO datfiles (id,extension,name,contenttype) VALUES ('+IntToStr(i)+',"'+dat_files[i].Extension+'","'+dat_files[i].Name+'","'+IntToHex(dat_files[i].FileType,8)+'");');
+      IF (dat_files[i].FileType AND $02)=0 THEN BEGIN
+        dat_stream.Seek(dat_files[i].DatAddr,soFromBeginning);
+        mem:=TMemoryStream.Create;
+        mem.CopyFrom(dat_stream,dat_files[i].Size);
+        mem.Seek(0,soFromBeginning);
+        DB.UpdateBlob('UPDATE datfiles SET data = ? WHERE id='+IntToStr(i)+';',mem);
+        HandleFile(dat_files[i].Extension,i,True);
+        mem.Free;
+      END;
+      IF ( (i MOD 50)=0 ) AND (i>=100) THEN
+        lbl_estimation.Caption:='Estimated finishing time: '+TimeToStr((Time-begintime)/i*dat_header.Files+begintime);
+      IF (i MOD 5)=0 THEN BEGIN
+        progress.Position:=i;
+        lbl_progress.Caption:='Files done: '+IntToStr(i)+'/'+IntToStr(dat_header.Files);
+        Application.ProcessMessages;
+      END;
+      IF abort THEN BEGIN
+        stop_convert;
+        Exit;
+      END;
+    END;
+    progress.Position:=dat_header.Files;
+    lbl_progress.Caption:='Files done: '+IntToStr(dat_header.Files)+'/'+IntToStr(dat_header.Files);
+    lbl_estimation.Caption:='FINISHED (duration: '+TimeToStr(Time-absolutebegintime)+')';
+
+    DoStep('FIN');
+    btn_abortok.Caption:='&OK';
+    btn_abortok.Default:=True;
+
+    loaded_filename:='';
+    converting:=False;
+    dat_stream.Free;
+    DB.Free;
+  END;
+
+PROCEDURE TForm10.stop_convert;
+  BEGIN
+    btn_abortok.Caption:='&Close';
+    btn_abortok.Default:=True;
+    converting:=False;
+    lbl_estimation.Caption:='ABORTED';
+    group_progress.Caption:='Creating DB (ABORTED)';
+    IF MessageBox(Self.Handle, PChar('Delete the unfinished DB-file?'), PChar('Delete file?'), MB_YESNO)=IDYES THEN BEGIN
+      DB.Free;
+      DeleteFile(loaded_filename);
+    END;
+  END;
+
+PROCEDURE TForm10.btn_abortokClick(Sender: TObject);
+  BEGIN
+    IF converting THEN BEGIN
+      IF MessageBox(Self.Handle, PChar('Do you really want to cancel the convert-progress?'), PChar('Warning: Converting'), MB_YESNO)=IDYES THEN
+        abort:=True;
+    END ELSE BEGIN
+      Form10.Visible:=False;
+      Form1.Visible:=True;
+    END;
+  END;
+
+
+PROCEDURE LoadFilePart(offset,size:LongWord; target:Pointer);
+  BEGIN
+    mem.Seek(offset,soFromBeginning);
+    mem.Read(target^,size);
+  END;
+
+PROCEDURE InsertDatLinkToDB(fileid:LongWord; offset:LongWord);
+  VAR
+    link:LongWord;
+  BEGIN
+    LoadFilePart(offset,4,@link);
+    IF link=0 THEN
+      link:=$FFFFFFFF
+    ELSE
+      link:=link DIV 256;
+    DB.ExecSQL('INSERT INTO linkmap (src_id,src_link_offset,target_id) VALUES ('+IntToStr(fileid)+','+IntToStr(offset)+','+IntToStr(link)+');');
+  END;
+
+PROCEDURE InsertRawFileToDB(fileid:LongWord; src_offset,raw_addr,size:LongWord);
+  VAR
+    localmem:TMemoryStream;
+  BEGIN
+    localmem:=TMemoryStream.Create;
+    filestream:=TFileStream.Create(raw_filename,fmOpenRead);
+    filestream.Seek(raw_addr,soFromBeginning);
+    localmem.CopyFrom(filestream,size);
+    filestream.Free;
+    DB.ExecSQL('INSERT INTO rawmap (src_id,src_link_offset) VALUES ('+IntToStr(fileid)+','+IntToStr(src_offset)+');');
+    DB.UpdateBlob('UPDATE rawmap SET data = ? WHERE src_id='+IntToStr(fileid),localmem);
+    localmem.Free;
+  END;
+
+
+
+PROCEDURE AGDB(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    link:LongWord;
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@links);
+      links:=links*2;
+      FOR i:=0 TO links-1 DO BEGIN
+        LoadFilePart($20+i*4,4,@link);
+        InsertRawFileToDB(fileid,$20+i*4,link,1{????????????????????????????????});
+      END;
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE AKEV(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 16 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE AKOT(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 4 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE BINA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    link:LongWord;
+    datasize:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($0C,4,@link);
+      LoadFilePart($08,4,@datasize);
+      InsertRawFileToDB(fileid,$0C,link,datasize);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CBPI(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 56 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CBPM(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 18 DO InsertDatLinkToDB(fileid,$8+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CONS(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 1 DO InsertDatLinkToDB(fileid,$24+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE CRSA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($14,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*1100+$A0);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE DOOR(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+      InsertDatLinkToDB(fileid,$10);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE DPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$40);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE HPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$0C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGHH(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$24);
+      InsertDatLinkToDB(fileid,$28);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGPA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@links);
+      IF links>0 THEN
+        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGPG(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 1 DO InsertDatLinkToDB(fileid,$1C+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IGSA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@links);
+      IF links>0 THEN
+        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IMPT(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$10);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE IPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$0C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE KEYI(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 9 DO InsertDatLinkToDB(fileid,$08+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE M3GA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    links:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@links);
+      IF links>0 THEN
+        FOR i:=0 TO links-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE M3GM(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 6 DO InsertDatLinkToDB(fileid,$0C+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE MTRL(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$10);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OBOA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*240);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OFGA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*12+$04);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONCC(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONCV(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONLV(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 5 DO InsertDatLinkToDB(fileid,$48+i*4);
+      FOR i:=0 TO 5 DO InsertDatLinkToDB(fileid,$64+i*4);
+      InsertDatLinkToDB(fileid,$300);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONOA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*8+$04);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONSK(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+      InsertDatLinkToDB(fileid,$0C);
+      InsertDatLinkToDB(fileid,$10);
+      InsertDatLinkToDB(fileid,$14);
+      InsertDatLinkToDB(fileid,$18);
+      InsertDatLinkToDB(fileid,$20);
+      InsertDatLinkToDB(fileid,$44);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONVL(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE ONWC(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$28);
+      InsertDatLinkToDB(fileid,$34);
+      InsertDatLinkToDB(fileid,$54);
+      InsertDatLinkToDB(fileid,$58);
+      InsertDatLinkToDB(fileid,$5C);
+      InsertDatLinkToDB(fileid,$60);
+      InsertDatLinkToDB(fileid,$6FC);
+      InsertDatLinkToDB(fileid,$700);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$1C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE OSBD(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    link:LongWord;
+    datasize:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($08,4,@datasize);
+      LoadFilePart($0C,4,@link);
+      InsertRawFileToDB(fileid,$0C,link,datasize);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE PSPC(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$50);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE PSPL(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:LongWord;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$24+i*8);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE PSUI(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 43 DO InsertDatLinkToDB(fileid,$08+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE SNDD(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    link:LongWord;
+    datasize:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($40,4,@datasize);
+      LoadFilePart($44,4,@link);
+      InsertRawFileToDB(fileid,$44,link,datasize);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE SUBT(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    baselink,link:LongWord;
+    links:LongWord;
+    i,j:LongWord;
+    data:Tdata;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($18,4,@baselink);
+      LoadFilePart($1C,4,@links);
+      IF links>0 THEN BEGIN
+        FOR i:=0 TO links-1 DO BEGIN
+          LoadFilePart($20+i*4,4,@link);
+          SetLength(data,1024);
+          LoadRawFile(fileid,baselink+link,1024,@data[0]);
+          FOR j:=0 TO 1024 DO BEGIN
+            IF (data[j]=$00) OR (j=1024) THEN BEGIN
+              IF j<1024 THEN
+                InsertRawFileToDB(fileid,$20+i*4,baselink+link,j)
+              ELSE
+                ShowMessage('Error: Didn''t find message-end-marker...');
+              Break;
+            END;
+          END;
+        END;
+      END;
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE STNA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRAC(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    packages:Word;
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$18);
+      LoadFilePart($1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*12+8);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRAM(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:Byte;
+    link:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 11 DO BEGIN
+        LoadFilePart($0C+i*4,4,@link);
+        InsertRawFileToDB(fileid,$0C+i*4,link,1{????????????????????????????????});
+      END;
+      LoadFilePart($13C,4,@link);
+      InsertRawFileToDB(fileid,$13C,link,1{????????????????????????????????});
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRAS(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRBS(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 4 DO InsertDatLinkToDB(fileid,$08+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRCM(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      FOR i:=0 TO 2 DO InsertDatLinkToDB(fileid,$5C+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRGA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:Word;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$20);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRIG(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$18);
+      InsertDatLinkToDB(fileid,$24);
+      InsertDatLinkToDB(fileid,$28);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRMA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:Word;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TRSC(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:Word;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1E,2,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TSFF(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TSFT(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$1C);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TURR(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$60);
+      InsertDatLinkToDB(fileid,$6C);
+      InsertDatLinkToDB(fileid,$74);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXAN(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXMA(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXMB(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXMP(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    link:LongWord;
+    x,y:Word;
+    storetype:Byte;
+    datasize:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($8C,SizeOf(x),@x);
+      LoadFilePart($8E,SizeOf(y),@y);
+      LoadFilePart($90,SizeOf(storetype),@storetype);
+      LoadFilePart($9C,4,@link);
+      CASE storetype OF
+        0,1,2: datasize:=x*y*2;
+        8: datasize:=x*y*4;
+        9: datasize:=x*y DIV 2;
+      END;
+      InsertRawFileToDB(fileid,$9C,link,datasize);
+      InsertDatLinkToDB(fileid,$94);
+      InsertDatLinkToDB(fileid,$98);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE TXTC(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE WMCL(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$24);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE WMMB(fileid:LongWord; dir_dat2db:Boolean);
+  VAR
+    i:LongWord;
+    packages:LongWord;
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      LoadFilePart($1C,4,@packages);
+      IF packages>0 THEN
+        FOR i:=0 TO packages-1 DO InsertDatLinkToDB(fileid,$20+i*4);
+    END ELSE BEGIN
+    END;
+  END;
+PROCEDURE WPGE(fileid:LongWord; dir_dat2db:Boolean);
+  BEGIN
+    IF dir_dat2db THEN BEGIN
+      InsertDatLinkToDB(fileid,$08);
+      InsertDatLinkToDB(fileid,$0C);
+    END ELSE BEGIN
+    END;
+  END;
+
+PROCEDURE InsertHandler(ext:String; needed:Boolean; handler:THandler);
+  BEGIN
+    SetLength(ConvertHandlers,Length(ConvertHandlers)+1);
+    ConvertHandlers[High(ConvertHandlers)].Ext:=ext;
+    ConvertHandlers[High(ConvertHandlers)].needed:=needed;
+    ConvertHandlers[High(ConvertHandlers)].handler:=handler;
+  END;
+
+BEGIN
+  InsertHandler('ABNA',False,NIL);
+//  InsertHandler('AGDB',True,AGDB);
+  InsertHandler('AGDB',False,NIL);
+  InsertHandler('AGQC',False,NIL);
+  InsertHandler('AGQG',False,NIL);
+  InsertHandler('AGQR',False,NIL);
+  InsertHandler('AISA',False,NIL);
+  InsertHandler('AITR',False,NIL);
+  InsertHandler('AKAA',False,NIL);
+  InsertHandler('AKBA',False,NIL);
+  InsertHandler('AKBP',False,NIL);
+  InsertHandler('AKDA',False,NIL);
+  InsertHandler('AKEV',True,AKEV);
+  InsertHandler('AKOT',True,AKOT);
+  InsertHandler('AKVA',False,NIL);
+  InsertHandler('BINA',True,BINA);
+  InsertHandler('CBPI',True,CBPI);
+  InsertHandler('CBPM',True,CBPM);
+  InsertHandler('CONS',True,CONS);
+  InsertHandler('CRSA',True,CRSA);
+  InsertHandler('DOOR',True,DOOR);
+  InsertHandler('DPGE',True,DPGE);
+  InsertHandler('ENVP',False,NIL);
+  InsertHandler('FILM',False,NIL);
+  InsertHandler('HPGE',True,HPGE);
+  InsertHandler('IDXA',False,NIL);
+  InsertHandler('IGHH',True,IGHH);
+  InsertHandler('IGPA',True,IGPA);
+  InsertHandler('IGPG',True,IGPG);
+  InsertHandler('IGSA',True,IGSA);
+  InsertHandler('IMPT',True,IMPT);
+  InsertHandler('IPGE',True,IPGE);
+  InsertHandler('KEYI',True,KEYI);
+  InsertHandler('M3GA',True,M3GA);
+  InsertHandler('M3GM',True,M3GM);
+  InsertHandler('MTRL',True,MTRL);
+  InsertHandler('OBAN',False,NIL);
+  InsertHandler('OBDC',False,NIL);
+  InsertHandler('OBOA',True,OBOA);
+  InsertHandler('OFGA',True,OFGA);
+  InsertHandler('ONCC',True,ONCC);
+  InsertHandler('ONCP',False,NIL);
+  InsertHandler('ONCV',True,ONCV);
+  InsertHandler('ONFA',False,NIL);
+  InsertHandler('ONGS',False,NIL);
+  InsertHandler('ONIA',False,NIL);
+  InsertHandler('ONLD',False,NIL);
+  InsertHandler('ONLV',True,ONLV);
+  InsertHandler('ONMA',False,NIL);
+  InsertHandler('ONOA',True,ONOA);
+  InsertHandler('ONSA',False,NIL);
+  InsertHandler('ONSK',True,ONSK);
+  InsertHandler('ONTA',False,NIL);
+  InsertHandler('ONVL',True,ONVL);
+  InsertHandler('ONWC',True,ONWC);
+  InsertHandler('OPGE',True,OPGE);
+  InsertHandler('OSBD',True,OSBD);
+  InsertHandler('OTIT',False,NIL);
+  InsertHandler('OTLF',False,NIL);
+  InsertHandler('PLEA',False,NIL);
+  InsertHandler('PNTA',False,NIL);
+  InsertHandler('PSPC',True,PSPC);
+  InsertHandler('PSPL',True,PSPL);
+  InsertHandler('PSUI',True,PSUI);
+  InsertHandler('QTNA',False,NIL);
+  InsertHandler('SNDD',True,SNDD);
+  InsertHandler('STNA',True,STNA);
+  InsertHandler('SUBT',True,SUBT);
+  InsertHandler('TRAC',True,TRAC);
+  InsertHandler('TRAM',True,TRAM);
+  InsertHandler('TRAS',True,TRAS);
+  InsertHandler('TRBS',True,TRBS);
+  InsertHandler('TRCM',True,TRCM);
+  InsertHandler('TRGA',True,TRGA);
+  InsertHandler('TRGE',True,TRGE);
+  InsertHandler('TRIA',False,NIL);
+  InsertHandler('TRIG',True,TRIG);
+  InsertHandler('TRMA',True,TRMA);
+  InsertHandler('TRSC',True,TRSC);
+  InsertHandler('TRTA',False,NIL);
+  InsertHandler('TSFF',True,TSFF);
+  InsertHandler('TSFL',False,NIL);
+  InsertHandler('TSFT',True,TSFT);
+  InsertHandler('TSGA',False,NIL);
+  InsertHandler('TSTR',False,NIL);
+  InsertHandler('TURR',True,TURR);
+  InsertHandler('TXAN',True,TXAN);
+  InsertHandler('TXCA',False,NIL);
+  InsertHandler('TXMA',True,TXMA);
+  InsertHandler('TXMB',True,TXMB);
+  InsertHandler('TXMP',True,TXMP);
+  InsertHandler('TXTC',True,TXTC);
+  InsertHandler('VCRA',False,NIL);
+  InsertHandler('WMCL',True,WMCL);
+  InsertHandler('WMDD',False,NIL);
+  InsertHandler('WMM_',False,NIL);
+  InsertHandler('WMMB',True,WMMB);
+  InsertHandler('WPGE',True,WPGE);
+END.
Index: /oup/current/old_sqlite/Unit2_functions.pas
===================================================================
--- /oup/current/old_sqlite/Unit2_functions.pas	(revision 10)
+++ /oup/current/old_sqlite/Unit2_functions.pas	(revision 10)
@@ -0,0 +1,460 @@
+UNIT Unit2_functions;
+INTERFACE
+USES Classes, Dialogs, SysUtils, StrUtils, Math, SQLiteTable3,
+      Unit3_data, Unit4_Exporters, ABSMain{, DB};
+
+TYPE
+  TExportSet=SET OF (DO_dat,DO_raw,DO_convert,DO_toone);
+
+FUNCTION GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringList;
+FUNCTION GetExtensionsList:TStringList;
+
+FUNCTION Decode_Int(buffer:Tdata):LongWord;
+FUNCTION Encode_Int(input:LongWord):Tdata;
+FUNCTION Decode_Float(buffer:Tdata):Single;
+FUNCTION Encode_Float(input:Single):Tdata;
+
+FUNCTION LoadDatInfos(filename:String):Boolean;
+PROCEDURE OpenDatabase(FileName:String);
+
+FUNCTION LoadDatFile(fileid:LongWord):Tdata;
+PROCEDURE UpdateDatFile(fileid:LongWord; data:Tdata);
+FUNCTION LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
+FUNCTION UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
+
+FUNCTION LoadRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
+FUNCTION UpdateRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
+
+FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;
+
+FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
+FUNCTION FormatFileSize(size:LongWord):String;
+FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
+FUNCTION GetWinFileName(name:String):String;
+FUNCTION GetExtractPath:String;
+
+
+IMPLEMENTATION
+
+TYPE
+  TValueSwitcher=Record
+    CASE IsFloat: Boolean OF
+      True: (ValueFloat:Single);
+      False: (ValueInt:LongWord);
+  END;
+
+FUNCTION Decode_Int(buffer:Tdata):LongWord;
+  BEGIN
+    Result:=buffer[0]+buffer[1]*256+buffer[2]*256*256+buffer[3]*256*256*256;
+  END;
+FUNCTION Encode_Int(input:LongWord):Tdata;
+  BEGIN
+    Result[0]:=input MOD 256;
+    input:=input DIV 256;
+    Result[1]:=input MOD 256;
+    input:=input DIV 256;
+    Result[2]:=input MOD 256;
+    input:=input DIV 256;
+    Result[3]:=input MOD 256;
+  END;
+FUNCTION Decode_Float(buffer:Tdata):Single;
+  VAR _valueswitcher:TValueSwitcher;
+  BEGIN
+    _valueswitcher.ValueInt:=Decode_Int(buffer);
+    Result:=_valueswitcher.ValueFloat;
+  END;
+FUNCTION Encode_Float(input:Single):Tdata;
+  VAR _valueswitcher:TValueSwitcher;
+  BEGIN
+    _valueswitcher.ValueFloat:=input;
+    Result:=Encode_Int(_valueswitcher.ValueInt);
+  END;
+
+
+FUNCTION GetFilesList(ext:String; pattern:String; NoEmptyFiles:Boolean):TStringList;
+  VAR
+    i:LongWord;
+    where:String;
+    Tbl:TSQLiteTable;
+  BEGIN
+    SetLength(Result,0);
+    IF opened_state=opened_dat THEN BEGIN
+      FOR i:=0 TO dat_header.Files-1 DO BEGIN
+        IF ( (Length(ext)=0) OR (dat_files[i].Extension=ext) ) AND
+             ( (Length(pattern)=0) OR (Pos(pattern,dat_files[i].Name)>0) ) THEN BEGIN
+          IF NoEmptyFiles THEN BEGIN
+            IF (dat_files[i].FileType AND $02)=0 THEN BEGIN
+              SetLength(Result,Length(Result)+1);
+              Result[High(Result)]:=dat_files[i].FileName;
+            END;
+          END ELSE BEGIN
+            SetLength(Result,Length(Result)+1);
+            Result[High(Result)]:=dat_files[i].FileName;
+          END;
+        END;
+      END;
+    END ELSE BEGIN
+      where:='';
+      IF Length(ext)>0 THEN BEGIN
+        IF Length(where)>0 THEN where:=where+' AND ';
+        where:=where+'(extension="'+ext+'")';
+      END;
+      IF Length(pattern)>0 THEN BEGIN
+        IF Length(where)>0 THEN where:=where+' AND ';
+        where:=where+'(name LIKE "%'+pattern+'%")';
+      END;
+      IF NoEmptyFiles THEN BEGIN
+        IF Length(where)>0 THEN where:=where+' AND ';
+        where:=where+'((contenttype & 2)=0)';
+      END;
+      IF Length(where)>0 THEN where:=' WHERE '+where;
+      Tbl:=DB.GetTable('SELECT id,name,extension FROM datfiles'+where+' ORDER BY id ASC;');
+      IF Tbl.Count>0 THEN BEGIN
+        SetLength(Result,Tbl.Count);
+        i:=0;
+        REPEAT
+          Result[i]:=FormatNumber(Tbl.FieldAsInteger('id'),5,'0')+'-'+Tbl.FieldAsString('name')+'.'+Tbl.FieldAsString('extension');
+          Inc(i);
+          Tbl.Next;
+        UNTIL Tbl.EOF;
+      END;
+    END;
+  END;
+
+FUNCTION GetExtensionsList:TStringList;
+  VAR
+    i:LongWord;
+    Tbl:TSQLiteTable;
+  BEGIN
+    SetLength(Result,0);
+    IF opened_state=opened_dat THEN BEGIN
+      FOR i:=0 TO dat_header.Extensions-1 DO BEGIN
+        SetLength(Result,Length(Result)+1);
+        WITH dat_extensionsmap[i] DO BEGIN
+          Result[High(Result)]:=Extension[3]+Extension[2]+Extension[1]+Extension[0]+' ('+IntToStr(ExtCount)+')';
+        END;
+      END;
+    END ELSE BEGIN
+      Tbl:=DB.GetTable('SELECT extension,count(extension) AS x FROM datfiles GROUP BY extension ORDER BY extension ASC;');
+      IF Tbl.Count>0 THEN BEGIN
+        SetLength(Result,Tbl.Count);
+        i:=0;
+        REPEAT
+          Result[i]:=Tbl.FieldAsString('extension')+' ('+IntToStr(Tbl.FieldAsInteger('x'))+')';
+          Inc(i);
+          Tbl.Next;
+        UNTIL Tbl.EOF;
+      END;
+    END;
+  END;
+
+FUNCTION LoadDatInfos(filename:String):Boolean;
+  VAR i:LongWord;
+    dat_file:TFileStream;
+  BEGIN
+    Result:=True;
+    opened_state:=opened_dat;
+    dat_filename:=filename;
+    raw_filename:=MidStr(filename,1,Length(filename)-3)+'raw';
+    dat_file:=TFileStream.Create(filename, fmOpenRead);
+    dat_file.Read(dat_header,SizeOf(dat_header));
+    FOR i:=0 TO High(dat_header.Ident) DO
+      IF dat_header.Ident[i]<>header_ident1[i] THEN BEGIN
+        Result:=False;
+        Exit;
+      END;
+    SetLength(dat_filesmap,dat_header.Files);
+    SetLength(dat_files,dat_header.Files);
+    FOR i:=0 TO dat_header.Files-1 DO dat_file.Read(dat_filesmap[i],SizeOf(dat_filesmap[i]));
+    FOR i:=0 TO dat_header.Files-1 DO BEGIN
+      dat_files[i].Extension:=dat_filesmap[i].Extension;
+      dat_files[i].Extension:=ReverseString(dat_files[i].Extension);
+      dat_files[i].Size:=dat_filesmap[i].FileSize;
+      dat_files[i].FileType:=dat_filesmap[i].FileType;
+      dat_files[i].DatAddr:=dat_filesmap[i].DataAddr-8+dat_header.DataAddr;
+      IF (dat_filesmap[i].FileType AND $01)=0 THEN BEGIN
+        dat_file.Seek(dat_filesmap[i].NameAddr+dat_header.NamesAddr,soFromBeginning);
+        SetLength(dat_files[i].Name,100);
+        dat_file.Read(dat_files[i].Name[1],100);
+        dat_files[i].Name:=MidStr(dat_files[i].Name,1+4,Pos(#0,dat_files[i].Name)-1-4);
+      END ELSE BEGIN
+        dat_files[i].Name:='';
+      END;
+      dat_files[i].FileName:=FormatNumber(i,5,'0')+'-'+dat_files[i].Name+'.'+dat_files[i].Extension;
+    END;
+    dat_file.Seek($40+dat_header.Files*$14,soFromBeginning);
+    SetLength(dat_namedfilesmap,dat_header.NamedFiles);
+    FOR i:=0 TO dat_header.NamedFiles-1 DO dat_file.Read(dat_namedfilesmap[i],SizeOf(dat_namedfilesmap[i]));
+
+    dat_file.Seek($40+dat_header.Files*$14+dat_header.NamedFiles*$8,soFromBeginning);
+    SetLength(dat_extensionsmap,dat_header.Extensions);
+    FOR i:=0 TO dat_header.Extensions-1 DO dat_file.Read(dat_extensionsmap[i],SizeOf(dat_extensionsmap[i]));
+
+    dat_file.Free;
+  END;
+
+
+FUNCTION LoadDatFile(fileid:LongWord):Tdata;
+  VAR
+    dat_file:TFileStream;
+    Tbl:TSQLiteTable;
+    mem:TMemoryStream;
+  BEGIN
+    IF opened_state=opened_dat THEN BEGIN
+      dat_file:=TFileStream.Create(dat_filename, fmOpenRead);
+      dat_file.Seek(dat_files[fileid].DatAddr,soFromBeginning);
+      SetLength(Result,dat_files[fileid].Size);
+      dat_file.Read(Result[0],dat_files[fileid].Size);
+      dat_file.Free;
+    END ELSE BEGIN
+      Tbl:=DB.GetTable('SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';');
+      IF Tbl.Count>0 THEN BEGIN
+        mem:=Tbl.FieldAsBlob('data');
+        SetLength(Result,mem.Size);
+        mem.Seek(0,soFromBeginning);
+        mem.Read(Result[0],mem.Size);
+        mem.Free;
+      END;
+    END;
+  END;
+PROCEDURE UpdateDatFile(fileid:LongWord; data:Tdata);
+  VAR
+    dat_file:TFileStream;
+    Tbl:TSQLiteTable;
+  BEGIN
+    IF opened_state=opened_dat THEN BEGIN
+      dat_file:=TFileStream.Create(dat_filename, fmOpenReadWrite);
+      dat_file.Seek(dat_files[fileid].DatAddr,soFromBeginning);
+      dat_file.Write(data[0],Length(data));
+      dat_file.Free;
+    END ELSE BEGIN
+    END;
+  END;
+
+FUNCTION LoadDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
+  VAR
+    dat_file:TFileStream;
+    Tbl:TSQLiteTable;
+    mem:TMemoryStream;
+  BEGIN
+    Result:=False;
+    IF opened_state=opened_dat THEN BEGIN
+      dat_file:=TFileStream.Create(dat_filename, fmOpenRead);
+      Result:=True;
+      dat_file.Seek(dat_files[fileid].DatAddr+offset,soFromBeginning);
+      dat_file.Read(target^,size);
+      dat_file.Free;
+    END ELSE BEGIN
+      Tbl:=DB.GetTable('SELECT data FROM datfiles WHERE id='+IntToStr(fileid)+';');
+      IF Tbl.Count>0 THEN BEGIN
+        Result:=True;
+        mem:=Tbl.FieldAsBlob('data');
+        mem.Seek(offset,soFromBeginning);
+        mem.Read(target^,size);
+        mem.Free;
+      END;
+    END;
+  END;
+FUNCTION UpdateDatFilePart(fileid,offset,size:LongWord; target:Pointer):Boolean;
+  VAR
+    dat_file:TFileStream;
+    Tbl:TSQLiteTable;
+  BEGIN
+    Result:=False;
+    IF opened_state=opened_dat THEN BEGIN
+      dat_file:=TFileStream.Create(dat_filename, fmOpenReadWrite);
+      Result:=True;
+      dat_file.Seek(dat_files[fileid].DatAddr+offset,soFromBeginning);
+      dat_file.Write(target^,size);
+      dat_file.Free;
+    END ELSE BEGIN
+    END;
+  END;
+
+FUNCTION LoadRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
+  VAR
+    filestream:TFileStream;
+    raw_addr:LongWord;
+    Tbl:TSQLiteTable;
+    mem:TMemoryStream;
+  BEGIN
+    Result:=False;
+    IF opened_state=opened_dat THEN BEGIN
+      Result:=True;
+      LoadDatFilePart(fileid,datlinkoffset,4,@raw_addr);
+      filestream:=TFileStream.Create(AnsiReplaceStr(dat_filename,'.dat','.raw'),fmOpenRead);
+      filestream.Seek(raw_addr,soFromBeginning);
+      filestream.Read(target^,size);
+      filestream.Free;
+    END ELSE BEGIN
+      Tbl:=DB.GetTable('SELECT data FROM rawmap WHERE (src_id='+IntToStr(fileid)+') AND (src_link_offset='+IntToStr(datlinkoffset)+');');
+      IF Tbl.Count>0 THEN BEGIN
+        Result:=True;
+        mem:=Tbl.FieldAsBlob('data');
+        mem.Seek(0,soFromBeginning);
+        mem.Read(target^,size);
+        mem.Free;
+      END;
+    END;
+  END;
+FUNCTION UpdateRawFile(fileid,datlinkoffset,size:LongWord; target:Pointer):Boolean;
+  VAR
+    filestream:TFileStream;
+    raw_addr:LongWord;
+  BEGIN
+    Result:=False;
+    IF opened_state=opened_dat THEN BEGIN
+      Result:=True;
+      LoadDatFilePart(fileid,datlinkoffset,4,@raw_addr);
+      filestream:=TFileStream.Create(AnsiReplaceStr(dat_filename,'.dat','.raw'),fmOpenReadWrite);
+      filestream.Seek(raw_addr,soFromBeginning);
+      filestream.Write(target^,size);
+      filestream.Free;
+    END ELSE BEGIN
+    END;
+  END;
+
+
+FUNCTION FormatNumber(value:LongWord; width:Byte; leadingzeros:Char):String;
+  BEGIN
+    Result:=AnsiReplaceStr(Format('%'+IntToStr(width)+'u',[value]),' ',leadingzeros);
+  END;
+
+FUNCTION FormatFileSize(size:LongWord):String;
+  BEGIN
+    IF size>=1000*1024*1024 THEN BEGIN
+      Result:=FloatToStrF(size/1024/1024/1024,ffFixed,5,1)+' GB';
+    END ELSE BEGIN
+      IF size>=1000*1024 THEN BEGIN
+        Result:=FloatToStrF(size/1024/1024,ffFixed,5,1)+' MB';
+      END ELSE BEGIN
+        IF size>=1000 THEN BEGIN
+          Result:=FloatToStrF(size/1024,ffFixed,5,1)+' KB';
+        END ELSE BEGIN
+          Result:=IntToStr(size)+' B';
+        END;
+      END;
+    END;
+  END;
+
+FUNCTION CreateHexString(data:Tdata; HexOnly:Boolean):String;
+  VAR
+    string_build,ascii_version:String;
+    i:LongWord;
+  BEGIN
+    string_build:='';
+    ascii_version:='';
+    FOR i:=0 TO High(data) DO BEGIN
+      IF NOT HexOnly THEN
+        IF (i MOD 16)=0 THEN
+          string_build:=string_build+'0x'+IntToHex(i,6)+'  ';
+      string_build:=string_build+IntToHex(data[i],2);
+      IF NOT HexOnly THEN BEGIN
+        IF data[i]>=32 THEN ascii_version:=ascii_version+Chr(data[i])
+        ELSE ascii_version:=ascii_version+'.';
+        IF ((i+1) MOD 2)=0 THEN string_build:=string_build+#32;
+        IF ((i+1) MOD 16)=0 THEN BEGIN
+          string_build:=string_build+#32+ascii_version+CrLf;
+          ascii_version:='';
+        END;
+      END;
+    END;
+    Result:=string_build;
+  END;
+
+
+FUNCTION ExportFile(fileid:LongWord; filename:String; settings:TExportSet; path:String):Integer;
+  VAR
+    i:Byte;
+    extension:String;
+  BEGIN
+    Result:=export_noerror;
+    extension:=RightStr(filename,4);
+    IF DO_toone IN settings THEN BEGIN
+      ExportDatFile(fileid,path+'\'+GetWinFileName(filename));
+    END ELSE BEGIN
+      IF DO_dat IN settings THEN ExportDatFile(fileid,path+'\'+GetWinFileName(filename));
+      IF DO_raw IN settings THEN BEGIN
+        FOR i:=1 TO Length(ExportHandlers)+1 DO BEGIN
+          IF i<=Length(ExportHandlers) THEN BEGIN
+            IF ExportHandlers[i].Ext=extension THEN BEGIN
+              IF ExportHandlers[i].needed THEN BEGIN
+                CASE ExportHandlers[i].Handler(fileid,path+'\'+GetWinFileName(filename),(DO_convert IN settings)) OF
+                  0: Result:=0;
+                ELSE
+                  Result:=export_handlererror;
+                END;
+              END;
+              Break;
+            END;
+          END ELSE BEGIN
+            Result:=export_nohandler;
+          END;
+        END;
+      END;
+    END;
+  END;
+
+
+FUNCTION GetWinFileName(name:String):String;
+  BEGIN
+    Result:=name;
+    Result:=AnsiReplaceStr(Result,'\','__');
+    Result:=AnsiReplaceStr(Result,'/','__');
+    Result:=AnsiReplaceStr(Result,'>','__');
+    Result:=AnsiReplaceStr(Result,'<','__');
+  END;
+
+FUNCTION GetExtractPath:String;
+  BEGIN
+    Result:=ExtractFilePath(dat_filename)+'\extracted_'+ExtractFileName(dat_filename);
+  END;
+
+
+PROCEDURE OpenDatabase(FileName:String);
+  VAR
+    i:Byte;
+    data:Tdata;
+    temps:String;
+    Tbl: TSQLiteTable;
+  BEGIN
+    IF NOT FileExists(FileName) THEN BEGIN
+      ShowMessage('File doesn''t exist!!!');
+      Exit;
+    END;
+    DB:=TSQLiteDatabase.Create(FileName);
+    Tbl:=DB.GetTable('SELECT name,value FROM globals ORDER BY name ASC');
+    REPEAT
+      IF Tbl.FieldAsString('name')='dbversion' THEN BEGIN
+        IF Tbl.FieldAsString('value')<>DBversion THEN BEGIN
+          ShowMessage('Database-file '+CrLf+'"'+FileName+'"'+CrLf+'has wrong version. (Required: '+DBversion+'; found: '+Tbl.FieldAsString('value')+')');
+          Exit;
+        END;
+      END;
+      IF Tbl.FieldAsString('name')='lvl' THEN BEGIN
+        database_level:=StrToInt(Tbl.FieldAsString('value'));
+      END;
+      IF Tbl.FieldAsString('name')='ident' THEN BEGIN
+        temps:=Tbl.FieldAsString('value');
+        FOR i:=0 TO High(database_ident) DO BEGIN
+          CASE temps[(i*2)+1+0] OF
+            '0'..'9': database_ident[i]:=Ord(temps[(i*2)+1+0])-48;
+            'A'..'F': database_ident[i]:=Ord(temps[(i*2)+1+0])-55;
+          END;
+          database_ident[i]:=database_ident[i]*16;
+          CASE temps[(i*2)+1+1] OF
+            '0'..'9': database_ident[i]:=database_ident[i]+Ord(temps[(i*2)+1+0])-48;
+            'A'..'F': database_ident[i]:=database_ident[i]+Ord(temps[(i*2)+1+0])-55;
+          END;
+        END;
+      END;
+      Tbl.Next;
+    UNTIL Tbl.EOF;
+    Tbl.Free;
+    opened_state:=opened_db;
+  END;
+
+
+
+
+END.
Index: /oup/current/selects.txt
===================================================================
--- /oup/current/selects.txt	(revision 10)
+++ /oup/current/selects.txt	(revision 10)
@@ -0,0 +1,3 @@
+SELECT (datfiles.name || "." || datfiles.extension) AS name, count(src_id) AS x, src_id FROM linkmap LEFT JOIN datfiles ON datfiles.id=src_id GROUP BY src_id ORDER BY x DESC
+
+SELECT (datfiles.name || "." || datfiles.extension) AS name, count(src_id) AS x, src_id FROM rawmap LEFT JOIN datfiles ON datfiles.id=src_id GROUP BY src_id ORDER BY x DESC
Index: /oup/current/todo.txt
===================================================================
--- /oup/current/todo.txt	(revision 10)
+++ /oup/current/todo.txt	(revision 10)
@@ -0,0 +1,128 @@
+-Types+Idents nicht in DB sondern Hardcoded, mit IDs für StructViewer
+-StructViewer: statt 12 für dat-links, neuer bereich für typed-dat-links
+
+
+-DB mit MAC-Files (andre offsets in dat für raw-links ...)
+-Faded repacking TXMP (???)
+-DatLinks patchen
+-Non32bit MipMapping (???)
+-32byte paddings
+
+-BinEdit: wenn Backend=ADB: erste 8 Bytes nicht aus file sondern aus fileID+levelID der Connection
+-TOniConnectionADB: FileList cachen!
+-TOniConnectionADB: AddFile, SetLevelID, etc
+
+-Compo: TBitSetEdit mit 8 CheckBoxes + Captions
+-ValueEdit: TBitSetEdit
+
+-StructViewer: TBitSetEdit?
+-Structs: Nach Paketen wieder Global?
+-Idents: Unterschied für Sep-Linked und SNDD
+-NamedLinks: Überprüfung auf 0 files? (level0.dat)
+-Links: Wenn level0 dann OUP mit level0 laden?
+
+-Patching: History Geyser 2006-04-30 - 04:07:00
+
+-Exports: FileExists => Abfrage
+
+-TOniImage: Statt Floor (bei farben) Round
+
+-RawParts: AGDB immer 32 bytes
+
+-DatEdit: Komplette .dat im Hex + Treeview der verschiedenen Parts etc
+
+-FileLists: Sort By ID, Name, Extension ...
+
+-Class für TForm mit FileList etc? (Form1_CreateContext mit dieser baseclass?)
+
+-FileNames: Form_***, Unit_***
+
+-Signed vs Unsigned
+
+-PNG statt/zusätzlich zu BMP
+
+-Noob-protection in Settings (Hex-Editing deaktiviert)
+-AppSettings: Erst initialisieren mit defaults, dann .ini lesen
+
+-Exporters (-> TOniImage etc)
+
+-Option: show files without first 8 bytes. special-struct-def-loading (substract 8 from every entry's offset)
+
+-Open über ein Menüpunkt: Decide upon Extension
+
+-Wiki etc: Links für benutzte Componenten
+-SourceCode docu (eg: http://www.time2help.com/)
+-ProgHelp
+-Localization (eg: http://dybdahl.dk/dxgettext/)
+
+-Close File/DB: Menu geht nach rechts
+
+-StructViewer: Strings bis 0x00, BitSets besser darstellen? (SSG: 18.04.06/10:52:58),
+  Dat-Link value="Not used" wenn not-used, SUBT-Packages: Value=0???,
+  file-ID-value dblclick=edit / anderes=follow,
+  "typed"-file-id-links?,
+  0 packages -> crash?
+
+-Floats: "." statt ","?
+
+-Preview: Export?
+
+-Dateityp-Name anzeigen (SUBT -> Subtitles etc)
+
+-DatOpen: Erst Childs schließen, dann OpenDialog, dnan alte .dat schließen?
+
+-IGSt: Bei DEAD: OUP hangs (ValueViewer:String?)
+
+-History:Geyser:14.04.06 15:11:45, 16.04.06 15:21:29
+
+-Bug bei SetNewValue mit String
+
+-Preview PSpc (!!!)
+-Preview: Models? 3D-Data?
+
+-Export etc: If dest-file exists zZt anhängen, stattdessen neuschreiben?!
+-Export: dat+raw eines Files in eine datei
+
+-Get files die bestimmten content haben (string etc)
+
+-Cursor Sanduhr bei Wartezeiten (db-access etc)
+
+-RawMap: was ist laut link+size used bereich, was nicht
+-StructViewer Raw: DynamicInfos aus .dat
+
+-Exporter: Checkboxes für was man im einzelnen will (zb Checkbox "in eine Datei ja/nein")
+
+-HELP
+
+-Hex: Paste
+
+-Datei von einem Tool in andrem Tool öffnen
+
+
+-Persist.dat editor
+
+
+-SELECT [src_id],MIN(datfiles.[name]),SUM(rawmap.[size]) FROM rawmap INNER  JOIN datfiles ON datfiles.[id]=[src_id] GROUP BY [src_id] ORDER BY [src_id] ASC
+
+-Extrahier-Ordner-Option (mit Platzhalter für .dat-Name)
+
+-About
+
+-BinEdit: Zusatzfunktionen wie: Suche, 
+-BinEdit: Bild/Menu/Button irgendwas zum speichern
+
+-Extractor: Wohin?
+
+-FileCompare: Ergebnis=Tabelle, jede Zeile eine differenz-addresse, spalten = werte an addr. für compared files
+
+-TXMP-Replace: MultiReplace
+
+-Move-Freischalter (Mindestlvl eingabe)
+
+-Löschen einer Datei auf die gelinkt wird: Liste der Links und sicherheitsfrage
+
+-Filebox-Context: Extract etc
+
+-STRG+C auf Dateilisten etc für kopieren des Namens
+
+-REPACKING: testen lvl0: 690-collisions.txmp einbauen, script: collisions-zeug
