Compare commits

...

71 Commits
1.5.2 ... 1.6.5

Author SHA1 Message Date
Matt Nadareski
86a9846300 Bump version 2024-05-15 15:10:58 -04:00
Matt Nadareski
db877d253c Update Models, fix build 2024-05-15 14:59:55 -04:00
Matt Nadareski
0acf1e3b08 Handle bounds-defying reads 2024-05-15 13:38:44 -04:00
Matt Nadareski
362ed3a9b6 Protect against odd end-of-stream issues 2024-05-15 13:08:51 -04:00
Matt Nadareski
758878a229 Bump version 2024-05-15 12:02:21 -04:00
Matt Nadareski
ffb6dfc333 Update packages 2024-05-13 16:29:53 -04:00
Matt Nadareski
66da74e00a Fix resource table issues with NE 2024-05-12 11:46:05 -04:00
Matt Nadareski
d41a0045cb Fix input paths for test program 2024-05-09 21:54:30 -04:00
Matt Nadareski
b65629ba0e Combine magic and extension checks; helps with complex situations 2024-05-09 21:34:58 -04:00
Matt Nadareski
9518e6d1a0 Unicode (UTF-16) not UTF-8 2024-05-08 12:09:11 -04:00
Matt Nadareski
4f374ee885 Only read resources that are valid 2024-05-08 12:02:48 -04:00
Matt Nadareski
afa239056e Handle future model fix 2024-05-07 08:55:54 -04:00
Matt Nadareski
886825af11 Bump version 2024-05-07 05:17:06 -04:00
Matt Nadareski
198de925aa Update IO 2024-05-07 05:13:30 -04:00
Matt Nadareski
3f7b71e9a5 Bump version 2024-05-06 22:23:45 -04:00
Matt Nadareski
95baaf8603 Update SabreTools.IO 2024-05-06 22:12:14 -04:00
Matt Nadareski
3673264bab Bump version 2024-04-28 19:37:10 -04:00
Matt Nadareski
64fb5a6b63 Update SabreTools.IO 2024-04-28 19:32:06 -04:00
Matt Nadareski
e9c959ccdb Update SabreTools.IO 2024-04-28 17:39:30 -04:00
Matt Nadareski
4b7487e92e More rudimentary ZIP64 fixes 2024-04-28 00:24:35 -04:00
Matt Nadareski
52dbcffd8e Add shortcut if any other valid PKZIP blocks found 2024-04-27 23:57:32 -04:00
Matt Nadareski
24ae354bc2 Fix an indicator for ZIP64 2024-04-27 23:50:03 -04:00
Matt Nadareski
b30b91fd91 Remove redunant fix in StringBuilderExtensions 2024-04-27 23:48:55 -04:00
Matt Nadareski
efb63afc74 Fix PKZIP data printing 2024-04-27 23:45:33 -04:00
Matt Nadareski
16706f7169 Force writing values with proper width 2024-04-27 23:42:37 -04:00
Matt Nadareski
d7c32676b5 Add PKZIP printer implementation 2024-04-27 23:40:02 -04:00
Matt Nadareski
c8c45446bc Add PKZIP archive extra data record parsing 2024-04-27 23:01:50 -04:00
Matt Nadareski
f4de2e27d7 Notes cleanup 2024-04-27 22:49:09 -04:00
Matt Nadareski
970fcbd93b Add PKZIP shell wrapper 2024-04-27 22:45:49 -04:00
Matt Nadareski
57d1cd7f1e Initial code for PKZIP deserialization 2024-04-27 22:41:22 -04:00
Matt Nadareski
522fc372fa Fix instance of wrong extension 2024-04-27 22:23:33 -04:00
Matt Nadareski
7141690fcb Add override for compression handling 2024-04-27 22:04:52 -04:00
Matt Nadareski
c7d9177e68 Allow decompression to be skipped 2024-04-27 22:04:38 -04:00
Matt Nadareski
00b3ea40d9 Bump version 2024-04-26 21:33:56 -04:00
Matt Nadareski
c9afe939dc Update packages 2024-04-26 21:32:55 -04:00
Matt Nadareski
4171ae6516 Update build scripts, action 2024-04-26 21:27:58 -04:00
Matt Nadareski
35a42c49d5 Uncomment large amount of items but return null explicitly 2024-04-24 19:18:38 -04:00
Matt Nadareski
e4dbf56b49 Integrate test program data into main library 2024-04-24 19:15:28 -04:00
Matt Nadareski
76eeb10c47 Update README 2024-04-24 19:04:05 -04:00
Matt Nadareski
9fa73ad54f Rename PrintExtensions to Printer 2024-04-24 19:04:01 -04:00
Matt Nadareski
6034a4fd06 Port Printing into Serialization 2024-04-24 18:53:10 -04:00
Matt Nadareski
9d15310b04 Bump version 2024-04-24 16:17:19 -04:00
Matt Nadareski
f04ec3e465 Remove unused test files from porting 2024-04-24 14:38:47 -04:00
Matt Nadareski
0071e7a462 Create GetTestFilePath helper method 2024-04-24 13:50:36 -04:00
Matt Nadareski
d697461cc2 Reduce unncessary line space 2024-04-24 13:26:39 -04:00
Matt Nadareski
517ff00a0f Rename test classes to be more explicit 2024-04-24 13:25:37 -04:00
Matt Nadareski
d06017c045 Copy serialization tests from SabreTools.Test, fix issues 2024-04-24 13:23:51 -04:00
Matt Nadareski
1b819d96a5 Bump version 2024-04-24 10:17:14 -04:00
Matt Nadareski
ad2bfc31bc Update SabreTools.Models 2024-04-24 10:15:27 -04:00
Matt Nadareski
66b4f12fb3 Port one more extension from UnshieldSharp 2024-04-24 00:39:27 -04:00
Matt Nadareski
40de2575bb Add last extension property from UnshieldSharp 2024-04-24 00:33:24 -04:00
Matt Nadareski
be4a95fe91 Handle nullable better 2024-04-24 00:30:03 -04:00
Matt Nadareski
c685b5e679 Add extension properties from UnshieldSharp 2024-04-24 00:29:27 -04:00
Matt Nadareski
99baeba735 Make Linux publish script executable 2024-04-23 22:27:35 -04:00
Matt Nadareski
bc6b6d39da Add publish scripts 2024-04-23 22:27:26 -04:00
Matt Nadareski
2bb814e170 Remove now-unnecessary code 2024-04-23 22:22:04 -04:00
Matt Nadareski
3bf78c78e3 Bump version 2024-04-23 21:53:36 -04:00
Matt Nadareski
e38ecaec4c Fix build 2024-04-23 21:49:57 -04:00
Matt Nadareski
af40c78b56 Handle more directly-marshalled types 2024-04-23 21:45:54 -04:00
Matt Nadareski
12b206f9fa Update SabreTools.Models 2024-04-23 21:07:42 -04:00
Matt Nadareski
2cc51ba089 Fix build, oops 2024-04-23 21:05:50 -04:00
Matt Nadareski
52f0846d5d Add and fix some deserializers 2024-04-23 21:00:10 -04:00
Matt Nadareski
3fa8848e77 Make more parsing methods public 2024-04-23 15:38:33 -04:00
Matt Nadareski
41276e3d7e Port more helpers 2024-04-23 15:38:21 -04:00
Matt Nadareski
4cef93c95e Port some accessors from UnshieldSharp 2024-04-23 15:27:07 -04:00
Matt Nadareski
cdd999ee03 Fix other instances of string reading 2024-04-23 15:18:18 -04:00
Matt Nadareski
4f253323db Fix IS-CAB deserialization 2024-04-23 15:14:18 -04:00
Matt Nadareski
351f749e20 Add ISAv3 deserializer 2024-04-23 15:12:42 -04:00
Matt Nadareski
1e83fc4b9a Update packages 2024-04-23 15:12:39 -04:00
Matt Nadareski
c532bd1063 Bump version 2024-04-18 12:16:02 -04:00
Matt Nadareski
e4631a8176 Update SabreTools.IO 2024-04-18 12:04:54 -04:00
121 changed files with 650028 additions and 1869 deletions

53
.github/workflows/build_test.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Build Test
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
project: [Test]
runtime: [win-x86, win-x64, linux-x64, osx-x64] #[win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
framework: [net8.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0]
conf: [Release, Debug]
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet publish ${{ matrix.project }}/${{ matrix.project }}.csproj -f ${{ matrix.framework }} -r ${{ matrix.runtime }} -c ${{ matrix.conf == 'Release' && 'Release -p:DebugType=None -p:DebugSymbols=false' || 'Debug'}} --self-contained true --version-suffix ${{ github.sha }} ${{ (startsWith(matrix.framework, 'net5') || startsWith(matrix.framework, 'net6') || startsWith(matrix.framework, 'net7') || startsWith(matrix.framework, 'net8')) && '-p:PublishSingleFile=true' || ''}}
- name: Archive build
run: zip -r ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip ${{ matrix.project }}/bin/${{ matrix.conf }}/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}
path: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip
- name: Upload to rolling
uses: ncipollo/release-action@v1.14.0
with:
allowUpdates: True
artifacts: ${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip
body: 'Last built commit: ${{ github.sha }}'
name: 'Rolling Release'
prerelease: True
replacesArtifacts: True
tag: "rolling"
updateOnlyUnreleased: True

View File

@@ -6,7 +6,7 @@ Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTo
## Interfaces
Below is a table representing the various interfaces that are implemented within this library.
Below is a table representing the various conversion interfaces that are implemented within this library.
| Interface Name | Source Type | Destination Type |
| --- | --- | --- |
@@ -19,7 +19,13 @@ Below is a table representing the various interfaces that are implemented within
| `IStreamSerializer` | Model | `Stream?` |
| `IStringDeserializer` | `string?` representation | Model |
| `IStringSerializer` | Model | `string?` representation |
| `IWrapper` | N/A | N/A |
Below is a table representing the various non-conversion interfaces that are implemented within this library.
| Interface Name | Purpose |
| --- | --- |
| `IPrinter` | Provides a formatted output for a model |
| `IWrapper` / `IWrapper<T>` | Wraps a model or set of models to provide additional functionality |
## Namespaces
@@ -29,5 +35,6 @@ Below is a table of all namespaces within the library and what they represent
| --- | --- |
| `SabreTools.Serialization.CrossModel` | Convert between models; mainly used for metadata files converting to and from a common, `Dictionary`-based model |
| `SabreTools.Serialization.Deserializers` | Convert from external sources to models |
| `SabreTools.Serialization.Printers` | Export model information in a formatted manner |
| `SabreTools.Serialization.Serializers` | Convert from models to external sources |
| `SabreTools.Serialization.Wrappers` | Classes that wrap serialization and models to allow for including extension properties |

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,91 @@
using System;
using System.IO;
using System.Security.Cryptography;
using SabreTools.Serialization.Serializers;
using Xunit;
namespace SabreTools.Serialization.Test
{
public class MetadataSerializationTests
{
[Fact]
public void OpenMSXSeserializeTest()
{
// Create the object for serialization
var dat = GenerateOpenMSX();
// Deserialize the file
var stream = OpenMSX.SerializeStream(dat) as MemoryStream;
// Validate the values
Assert.NotNull(stream);
byte[] hash = SHA1.HashData(stream.GetBuffer());
string hashstr = BitConverter.ToString(hash).Replace("-", string.Empty);
Assert.Equal("CCBFAAB56BAAF6BE56A85918055784A615379659", hashstr);
}
#region Payload Generators
/// <summary>
/// Generate a consistent OpenMSX SoftwareDb for testing
/// </summary>
private static Models.OpenMSX.SoftwareDb GenerateOpenMSX()
{
var original = new Models.OpenMSX.Original
{
Value = "false",
Content = "Original Name",
};
var rom = new Models.OpenMSX.Rom
{
Start = "0x0000",
Type = "Game",
Hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709",
Remark = "Comment",
};
var megaRom = new Models.OpenMSX.MegaRom
{
Start = "0x1000",
Type = "Software",
Hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709",
Remark = "Comment",
};
var sccPlusCart = new Models.OpenMSX.SCCPlusCart
{
Start = "0x2000",
Type = "Utility",
Hash = "da39a3ee5e6b4b0d3255bfef95601890afd80709",
Remark = "Comment",
};
var dump = new Models.OpenMSX.Dump[]
{
new Models.OpenMSX.Dump { Original = original, Rom = rom },
new Models.OpenMSX.Dump { Rom = megaRom },
new Models.OpenMSX.Dump { Rom = sccPlusCart },
};
var software = new Models.OpenMSX.Software
{
Title = "Software Title",
GenMSXID = "00000", // Not required
System = "MSX 2",
Company = "Imaginary Company, Inc.",
Year = "19xx",
Country = "Imaginaria",
Dump = dump,
};
return new Models.OpenMSX.SoftwareDb
{
Timestamp = "1234567890",
Software = [software],
};
}
#endregion
}
}

View File

@@ -0,0 +1,38 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\SabreTools.Serialization\SabreTools.Serialization.csproj" />
</ItemGroup>
<ItemGroup>
<None Remove="TestData\*" />
</ItemGroup>
<ItemGroup>
<Content Include="TestData\*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="SabreTools.Models" Version="1.4.8" />
<PackageReference Include="xunit" Version="2.8.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,228 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Source: https://ia902607.us.archive.org/4/items/adventuresofsher00doylrich/adventuresofsher00doylrich_files.xml
-->
<files>
<file name="__ia_thumb.jpg" source="original">
<mtime>1657820174</mtime>
<size>23393</size>
<md5>33ca910055358d18e116ea66a0abdf04</md5>
<crc32>aad0f2dc</crc32>
<sha1>fc6d673ef7fbe974bba88b8275c737eeb20b5ba8</sha1>
<format>Item Tile</format>
<rotation>0</rotation>
</file>
<file name="_cloth_detection.log" source="derivative">
<cloth_cover_detection_module_version>1.2</cloth_cover_detection_module_version>
<format>Cloth Cover Detection Log</format>
<original>scandata.zip</original>
<mtime>1682523106</mtime>
<size>717</size>
<md5>3ed8a80448263ebfad242b8fa5a1a18d</md5>
<crc32>d886dce1</crc32>
<sha1>4f8d103cf07c29e1d3bb8273870f1daca4a89f26</sha1>
</file>
<file name="adventuresofsher00doylrich.djvu" source="derivative">
<format>DjVu</format>
<original>adventuresofsher00doylrich_djvu.xml</original>
<mtime>1288609616</mtime>
<size>11176526</size>
<md5>52ccad905110bc7f3c0fe032ef744fa1</md5>
<crc32>91973508</crc32>
<sha1>aa5214400b60e3b68f5eaa9733e10af4bcfe4e8d</sha1>
</file>
<file name="adventuresofsher00doylrich.gif" source="derivative">
<format>Animated GIF</format>
<original>adventuresofsher00doylrich_jp2.zip</original>
<mtime>1288593173</mtime>
<size>334379</size>
<md5>4d56403c12771ed7e396f6187d95502d</md5>
<crc32>1a8585c1</crc32>
<sha1>6062155959dd69f279a489b3761afa0a1638173d</sha1>
</file>
<file name="adventuresofsher00doylrich.pdf" source="derivative">
<pdf_module_version>0.0.22</pdf_module_version>
<format>Text PDF</format>
<original>adventuresofsher00doylrich_page_numbers.json</original>
<mtime>1682525473</mtime>
<size>26126569</size>
<md5>98ad55b9989671f823228055bfbca465</md5>
<crc32>cdc5f40d</crc32>
<sha1>e358dd22e04f7efcd4dfc8a6c2d714a0e0a8297c</sha1>
</file>
<file name="adventuresofsher00doylrich_archive.torrent" source="metadata">
<btih>4b5bbf39f9e489f66e0c70a9ac45af495b31a2ba</btih>
<mtime>1688944719</mtime>
<size>17197</size>
<md5>91aa4822d1552ef8bd08b27b14d8af4d</md5>
<crc32>10a3d397</crc32>
<sha1>9f5d4b652ac6903e218c8ff8e854482ab3d31b99</sha1>
<format>Archive BitTorrent</format>
</file>
<file name="adventuresofsher00doylrich_chocr.html.gz" source="derivative">
<ocr>tesseract 5.3.0-3-g9920</ocr>
<ocr_parameters>lang-eng;two-pass-disabled;pass-dpi-disabled;autonomous-mode-disabled;binarisation-method-otsu</ocr_parameters>
<ocr_module_version>0.0.21</ocr_module_version>
<ocr_detected_script>Latin</ocr_detected_script>
<ocr_detected_script_conf>0.8867</ocr_detected_script_conf>
<ocr_detected_lang>en</ocr_detected_lang>
<ocr_detected_lang_conf>1.0000</ocr_detected_lang_conf>
<format>chOCR</format>
<original>adventuresofsher00doylrich_jp2.zip</original>
<mtime>1682523054</mtime>
<size>8326755</size>
<md5>cda085dadcc74ca4bbeb768b69e7b28b</md5>
<crc32>faa3bbc1</crc32>
<sha1>0ceffd2d58757e30ccfcc84ff6805093e32607b3</sha1>
</file>
<file name="adventuresofsher00doylrich_dc.xml" source="original">
<format>Dublin Core</format>
<mtime>1682518166</mtime>
<size>1712</size>
<md5>bb3294746c4d5bb8102f8426454b26fb</md5>
<crc32>7c20c9c9</crc32>
<sha1>2bc134939b5f044396c56af740ad55029978859e</sha1>
</file>
<file name="adventuresofsher00doylrich_djvu.txt" source="derivative">
<format>DjVuTXT</format>
<original>adventuresofsher00doylrich_djvu.xml</original>
<mtime>1682523254</mtime>
<size>613882</size>
<md5>022b57b4017bbd8e6564c6e0968ad063</md5>
<crc32>2828f839</crc32>
<sha1>1535e2f509fc3a81c377d2b7270d21a95af71d65</sha1>
</file>
<file name="adventuresofsher00doylrich_djvu.xml" source="derivative">
<format>Djvu XML</format>
<original>adventuresofsher00doylrich_hocr.html</original>
<mtime>1682523185</mtime>
<size>8593952</size>
<md5>6faee3cd4ba7b3eaca3a2f5f4e8414f6</md5>
<crc32>51713c61</crc32>
<sha1>16dc73c2bdce4705c37d86a798d83fb780929928</sha1>
</file>
<file name="adventuresofsher00doylrich_files.xml" source="original">
<format>Metadata</format>
<md5>f39ff302a7965a1a077f3c4962f5d2e9</md5>
<summation>md5</summation>
</file>
<file name="adventuresofsher00doylrich_hocr.html" source="derivative">
<hocr_char_to_word_module_version>1.1.0</hocr_char_to_word_module_version>
<hocr_char_to_word_hocr_version>1.1.15</hocr_char_to_word_hocr_version>
<ocr_parameters>lang-eng;two-pass-disabled;pass-dpi-disabled;autonomous-mode-disabled;binarisation-method-otsu</ocr_parameters>
<ocr_module_version>0.0.21</ocr_module_version>
<ocr_detected_script>Latin</ocr_detected_script>
<ocr_detected_script_conf>0.8867</ocr_detected_script_conf>
<ocr_detected_lang>en</ocr_detected_lang>
<ocr_detected_lang_conf>1.0000</ocr_detected_lang_conf>
<format>hOCR</format>
<original>adventuresofsher00doylrich_chocr.html.gz</original>
<mtime>1682523150</mtime>
<size>15785810</size>
<md5>afbb8a9c1e6c25b3755fa6345153b13d</md5>
<crc32>e79c31fd</crc32>
<sha1>8b7cd7fd2010544783277f502c4103310dc2e2c4</sha1>
</file>
<file name="adventuresofsher00doylrich_hocr_pageindex.json.gz" source="derivative">
<hocr_pageindex_module_version>1.0.0</hocr_pageindex_module_version>
<hocr_pageindex_hocr_version>1.1.15</hocr_pageindex_hocr_version>
<format>OCR Page Index</format>
<original>adventuresofsher00doylrich_hocr.html</original>
<mtime>1682523219</mtime>
<size>4232</size>
<md5>aec425c66ef34149cff679b8998c2a36</md5>
<crc32>9a6e2f76</crc32>
<sha1>cc91c1eb055652ab6c9de878c6b54e8b95bddad1</sha1>
</file>
<file name="adventuresofsher00doylrich_hocr_searchtext.txt.gz" source="derivative">
<hocr_fts_text_module_version>1.1.0</hocr_fts_text_module_version>
<hocr_fts_text_hocr_version>1.1.15</hocr_fts_text_hocr_version>
<word_conf_0_10>531</word_conf_0_10>
<word_conf_11_20>242</word_conf_11_20>
<word_conf_21_30>298</word_conf_21_30>
<word_conf_31_40>321</word_conf_31_40>
<word_conf_41_50>389</word_conf_41_50>
<word_conf_51_60>450</word_conf_51_60>
<word_conf_61_70>671</word_conf_61_70>
<word_conf_71_80>1059</word_conf_71_80>
<word_conf_81_90>3102</word_conf_81_90>
<word_conf_91_100>103350</word_conf_91_100>
<format>OCR Search Text</format>
<original>adventuresofsher00doylrich_hocr.html</original>
<mtime>1682523242</mtime>
<size>224594</size>
<md5>2e1011def53909a247f73af66420e0c3</md5>
<crc32>32dddf59</crc32>
<sha1>f303467ce8f109a1d9cf49f2038c9a1d43e3c63e</sha1>
</file>
<file name="adventuresofsher00doylrich_jp2.zip" source="derivative">
<format>Single Page Processed JP2 ZIP</format>
<original>adventuresofsher00doylrich_raw_jp2.zip</original>
<mtime>1288593129</mtime>
<size>203319748</size>
<md5>2acbe6b61d35d8bd093127f0cef724c9</md5>
<crc32>66bcf599</crc32>
<sha1>a8801760eec5442176281584bd6242868f81cde5</sha1>
<filecount>364</filecount>
</file>
<file name="adventuresofsher00doylrich_marc.xml" source="original">
<format>MARC</format>
<md5>e951175fb1ee03c706ab6ee34754a92c</md5>
<mtime>1682518056</mtime>
<size>7679</size>
<crc32>3538b620</crc32>
<sha1>8fd493fa0971c2f7c2fdb1d84e0ec4234b878ff4</sha1>
</file>
<file name="adventuresofsher00doylrich_meta.xml" source="original">
<format>Metadata</format>
<mtime>1682525557</mtime>
<size>3790</size>
<md5>e98cb44acdb4e4f070fddb8b1f328d93</md5>
<crc32>04ee4346</crc32>
<sha1>c687fc00d20b516b0cf19225296e984cbfe7c315</sha1>
</file>
<file name="adventuresofsher00doylrich_metasource.xml" source="original">
<format>MARC Source</format>
<md5>7099c2013db04ef8a7277386ce74de54</md5>
<mtime>1682518056</mtime>
<size>527</size>
<crc32>6fa5d977</crc32>
<sha1>34ed3e366ed809a1a39a265373b9cf5b8cc06f0c</sha1>
</file>
<file name="adventuresofsher00doylrich_page_numbers.json" source="derivative">
<format>Page Numbers JSON</format>
<original>adventuresofsher00doylrich_djvu.xml</original>
<mtime>1682523259</mtime>
<size>67337</size>
<md5>f9179733924fa4566f0e9a05c8c276dd</md5>
<crc32>2bd8369f</crc32>
<sha1>e4104152caa990c72f986eb63c660239f0111feb</sha1>
</file>
<file name="adventuresofsher00doylrich_raw_jp2.zip" source="original">
<format>Single Page Raw JP2 ZIP</format>
<md5>d2a1137d4f8fed61be945f878444923b</md5>
<mtime>1204986411</mtime>
<size>370667543</size>
<crc32>12eda51c</crc32>
<sha1>402b01b5a734ae4f857991c0977ba629a8606932</sha1>
<filecount>364</filecount>
</file>
<file name="adventuresofsher00doylrich_reviews.xml" source="original">
<mtime>1688944715</mtime>
<size>9412</size>
<md5>ff0c9653a7aa865ea01e032e8b657736</md5>
<crc32>7634dbbc</crc32>
<sha1>f93a8206d6836f08c19dd023eb552bed2106cad9</sha1>
<format>Metadata</format>
</file>
<file name="scandata.zip" source="original">
<format>Scribe Scandata ZIP</format>
<md5>506fdf9aa054fbc7e9e2577d05d5e7cf</md5>
<mtime>1682523105</mtime>
<size>55175976</size>
<crc32>232ce248</crc32>
<sha1>9adf53bc1b8e7be5afe3526d2ab64f9696058488</sha1>
<filecount>11</filecount>
</file>
</files>

View File

@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="UTF-8"?>
<files>
<file name="I have grown so used to you - J. Frank Hopkins.gif" source="derivative">
<format>Animated GIF</format>
<original>I have grown so used to you - J. Frank Hopkins.mp4</original>
<mtime>1446681646</mtime>
<size>83293</size>
<md5>d60eddbc1d9915dc3a49889890c172d1</md5>
<crc32>30fe3c3e</crc32>
<sha1>80f7f6b523965b9dc4f997a775d03aab7f6dfcfb</sha1>
</file>
<file name="I have grown so used to you - J. Frank Hopkins.mp4" source="original">
<mtime>1446681528</mtime>
<size>69339907</size>
<md5>867ad802b751623b409eb833a15d0b80</md5>
<crc32>dbc81bfe</crc32>
<sha1>5e860bdb6cad0b7f974ebe9ea391e26f4cd8c714</sha1>
<format>MPEG4</format>
<length>140.42</length>
<height>720</height>
<width>1280</width>
</file>
<file name="I have grown so used to you - J. Frank Hopkins.ogv" source="derivative">
<format>Ogg Video</format>
<original>I have grown so used to you - J. Frank Hopkins.mp4</original>
<mtime>1446682043</mtime>
<size>10548875</size>
<md5>9a9dc6524b8ca0be68d1b0c3e9b2d0b2</md5>
<crc32>5a17284d</crc32>
<sha1>36b7e06adf4cf4f8fc159dba380dae9e632e410a</sha1>
<length>140.42</length>
<height>300</height>
<width>533</width>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins.thumbs/I have grown so used to you - J. Frank Hopkins_000001.jpg" source="derivative">
<format>Thumbnail</format>
<original>I have grown so used to you - J. Frank Hopkins.mp4</original>
<mtime>1446681658</mtime>
<size>8382</size>
<md5>dbb3838f9e348938ffabf8570809bd1b</md5>
<crc32>ca0b9e96</crc32>
<sha1>1efa60020eb9b0441256d00d51c1ef208cb50047</sha1>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins.thumbs/I have grown so used to you - J. Frank Hopkins_000045.jpg" source="derivative">
<format>Thumbnail</format>
<original>I have grown so used to you - J. Frank Hopkins.mp4</original>
<mtime>1446681676</mtime>
<size>8244</size>
<md5>295c4e5fe1b56e0438008c60d28213b7</md5>
<crc32>441108d4</crc32>
<sha1>388801815d2aa0fa98c4a75589f73faeb958071f</sha1>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins.thumbs/I have grown so used to you - J. Frank Hopkins_000075.jpg" source="derivative">
<format>Thumbnail</format>
<original>I have grown so used to you - J. Frank Hopkins.mp4</original>
<mtime>1446681693</mtime>
<size>8321</size>
<md5>94a0c9ae786011773c29be2bb844bd70</md5>
<crc32>f09fea6a</crc32>
<sha1>439476ad109f2f1edd0b85c2c04b5c6dfdfe0bce</sha1>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins.thumbs/I have grown so used to you - J. Frank Hopkins_000105.jpg" source="derivative">
<format>Thumbnail</format>
<original>I have grown so used to you - J. Frank Hopkins.mp4</original>
<mtime>1446681710</mtime>
<size>8342</size>
<md5>a284cbd6a9288e29b7b03118c6658816</md5>
<crc32>62785a42</crc32>
<sha1>44dd6f1df0c681f410076035bc7b8b3bae81bff4</sha1>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins.thumbs/I have grown so used to you - J. Frank Hopkins_000135.jpg" source="derivative">
<format>Thumbnail</format>
<original>I have grown so used to you - J. Frank Hopkins.mp4</original>
<mtime>1446681726</mtime>
<size>8586</size>
<md5>0f0d08441fc414794063b7e07d5d0947</md5>
<crc32>dc6e44cf</crc32>
<sha1>cfac85033a4d0a45cc1a5c8ffd2fb37263ecfa8e</sha1>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins_archive.torrent" source="metadata">
<btih>65d70d3788efdc9fba994ac2abf4a82c3f3d3864</btih>
<mtime>1688963806</mtime>
<size>5514</size>
<md5>5279f6df87259e51a00ef537cc91ce9b</md5>
<crc32>eedeca57</crc32>
<sha1>26830f2b391cd8ed60f5d793d87016a0f1496bdc</sha1>
<format>Archive BitTorrent</format>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins_files.xml" source="original">
<format>Metadata</format>
<md5>954d2f3d58262e80c87a2f623a59200e</md5>
<summation>md5</summation>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins_meta.sqlite" source="original">
<mtime>1446681548</mtime>
<size>12288</size>
<md5>1da7d006f8f27b4fc9a1fd74941095cf</md5>
<crc32>1308a8d9</crc32>
<sha1>f31849351ed620108d7f3bb4af5aa5e40b4cdb7b</sha1>
<format>Metadata</format>
</file>
<file name="IHaveGrownSoUsedToYouJ.FrankHopkins_meta.xml" source="original">
<mtime>1682350692</mtime>
<size>1161</size>
<format>Metadata</format>
<md5>740d1aa686af09659361ce8c10b6fcfe</md5>
<crc32>3d03262a</crc32>
<sha1>9272d98773615f94040f799d2341ba45c13d6218</sha1>
</file>
<file name="__ia_thumb.jpg" source="original">
<mtime>1656366463</mtime>
<size>9378</size>
<md5>34dd181b0af401cfc3205b503ab63f48</md5>
<crc32>72e288dc</crc32>
<sha1>6bafe89be5f45e68eb641ae3aca960baa759bfe5</sha1>
<format>Item Tile</format>
<rotation>0</rotation>
</file>
</files>

View File

@@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8"?>
<files>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a.jpg" source="derivative">
<format>JPEG</format>
<original>78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a.tif</original>
<mtime>1501911616</mtime>
<size>1326621</size>
<md5>b50a8cc01a720df337cebbcb69e1cddf</md5>
<crc32>b50088ba</crc32>
<sha1>672d2922dff5a0954558b97d13301394870a6cc5</sha1>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a.tif" source="original">
<mtime>1501911368</mtime>
<size>37016416</size>
<md5>77176ab4e12418558aefa6f4b709737a</md5>
<crc32>3bbd199a</crc32>
<sha1>64beda28ffd02a67b4c69e33e4b18a808b63453e</sha1>
<format>TIFF</format>
<matrix_number>69660BB</matrix_number>
<collection-catalog-number>GBIA0011964A</collection-catalog-number>
<publisher>Decca</publisher>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a.zip" source="original">
<mtime>1684102561</mtime>
<size>575486142</size>
<md5>bd7f9d1d873b870c8b83f8b82ee6c503</md5>
<crc32>d1186398</crc32>
<sha1>1405bf17b31c0f25652399e820faa001922930a2</sha1>
<format>ZIP</format>
<filecount>9</filecount>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_archive.torrent" source="metadata">
<btih>2abc74cbab976a03ca6afdcffb9fecfbf19c6f70</btih>
<mtime>1688008658</mtime>
<size>31306</size>
<md5>6cc1a4bac4d031f48ffe313a39ffc65f</md5>
<crc32>fddb76db</crc32>
<sha1>3c880e5814be545914d7a1a61239bfe821505b7c</sha1>
<format>Archive BitTorrent</format>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_files.xml" source="original">
<format>Metadata</format>
<md5>7bc8555ee3daef91f32efcfe143cf29b</md5>
<summation>md5</summation>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_itemimage.jpg" source="original">
<mtime>1501911384</mtime>
<size>335881</size>
<md5>929d45f445e54b72d511a663e7324b86</md5>
<crc32>5266d154</crc32>
<sha1>f01dfce276cb1ca73148b964b290ee92063ea4b2</sha1>
<format>Item Image</format>
<rotation>0</rotation>
<matrix_number>69660BB</matrix_number>
<collection-catalog-number>GBIA0011964A</collection-catalog-number>
<publisher>Decca</publisher>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_meta.sqlite" source="original">
<mtime>1684102571</mtime>
<size>72704</size>
<format>Metadata</format>
<md5>38976e41f16009ed5e00723fabc9a4e6</md5>
<crc32>0e30e5ef</crc32>
<sha1>2bcad0eb21e2f77b54883d736faefa33f3cf787e</sha1>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_meta.xml" source="original">
<mtime>1688008490</mtime>
<size>2917</size>
<format>Metadata</format>
<md5>c5326c9a2198274fc206032da9301193</md5>
<crc32>ca42acd0</crc32>
<sha1>6eac8fecd728dafabef951da785ed2200d351dea</sha1>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_reviews.xml" source="original">
<mtime>1659982866</mtime>
<size>948</size>
<md5>b67e874d814cf6988e2beb6b243ddc17</md5>
<crc32>73b94665</crc32>
<sha1>74a01e64dd82da073163f5f457525ab3b84e7497</sha1>
<format>Metadata</format>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_roles.json" source="original">
<mtime>1501911433</mtime>
<size>80</size>
<md5>bd244561b4d7c40c7bdd2d71a401829d</md5>
<crc32>e2515f39</crc32>
<sha1>93eccc18266c503b84dd47840c41baf2b0a361a5</sha1>
<format>JSON</format>
<matrix_number>69660BB</matrix_number>
<collection-catalog-number>GBIA0011964A</collection-catalog-number>
<publisher>Decca</publisher>
</file>
<file name="78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a_thumb.jpg" source="derivative">
<format>JPEG Thumb</format>
<original>78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a.tif</original>
<mtime>1501911615</mtime>
<size>9138</size>
<md5>952296a31ff7efd183e2b74cf253640a</md5>
<crc32>b616ba9c</crc32>
<sha1>153f229b49cd4434605f3739576586bf5d7c9582</sha1>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored.afpk" source="derivative">
<format>Columbia Peaks</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored.flac</original>
<mtime>1599685667</mtime>
<size>29912</size>
<md5>5383c38733d9e66b747ec8102ddd0a75</md5>
<crc32>3bb2ece6</crc32>
<sha1>64bce8d6decac71824583cf12853d3e2c97d0206</sha1>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored.asr.srt" source="derivative">
<format>SubRip</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored.asr.vtt</original>
<mtime>1688008632</mtime>
<size>1973</size>
<md5>63a556629e33cc233dba249218af648b</md5>
<crc32>477180f5</crc32>
<sha1>d82d685af20ce28d21ab1eaa2a5efbf1bf354261</sha1>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored.asr.vtt" source="derivative">
<format>Web Video Text Tracks</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored_intermediate_asr.json</original>
<mtime>1688008577</mtime>
<size>1925</size>
<md5>c1b6808ac66b1fb89b6bf1517f6e9ed1</md5>
<crc32>349354b8</crc32>
<sha1>5fe6aa67644046ab07d61ce3644d388f575649e9</sha1>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored.flac" source="original">
<mtime>1599685214</mtime>
<size>48528837</size>
<md5>2a2ab6af18cdad6f572bb634c4155a44</md5>
<crc32>c1996233</crc32>
<sha1>5cb6761e6e24c5545006dd127ce5e44483707982</sha1>
<format>24bit Flac</format>
<track>02</track>
<length>184.55</length>
<height>0</height>
<width>0</width>
<title>I Don't Want to Set the World on Fire (restored)</title>
<creator>Durham</creator>
<album>I Don't Want to Set the World on Fire</album>
<artist>Ink Spots;Seiler;Marcus;Benjemen;Durham</artist>
<comment>https://archive.org/details/78_i-dont-want-to-set-the-world-on-fire_ink-spots-seiler-marcus-benjemen-durham_gbia0011964a/I+Don%27t+Want+to+Set+the+World+on+Fire+-+Ink+Spots.flac\</comment>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored.mp3" source="derivative">
<creator>Ink Spots;Seiler;Marcus;Benjemen;Durham</creator>
<title>I Don't Want to Set the World on Fire (restored)</title>
<track>02</track>
<album>I Don't Want to Set the World on Fire</album>
<bitrate>125</bitrate>
<format>VBR MP3</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored.flac</original>
<mtime>1599685494</mtime>
<size>2996749</size>
<md5>dc56351ccd39b09ced0a130fdcd8b2fc</md5>
<crc32>38e842b0</crc32>
<sha1>3e37080b5abde1be08f20072ca6fcd3f387dca15</sha1>
<length>184.58</length>
<height>640</height>
<width>640</width>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored.png" source="derivative">
<format>PNG</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored.flac</original>
<mtime>1599685521</mtime>
<size>35307</size>
<md5>4bc62df3610dde296218e9782bf9cab1</md5>
<crc32>ab0f45cf</crc32>
<sha1>c3e0ce23e6990e1deabec942ff71e3178cf18310</sha1>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored_intermediate_asr.json" source="derivative">
<format>Intermediate ASR JSON</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored_whisper_asr.json</original>
<mtime>1688008526</mtime>
<size>2672</size>
<md5>5bdd50eff7abadfe6a7d764c20dc35d9</md5>
<crc32>78a58328</crc32>
<sha1>044c53e7cef9fd1536c484c71aa3e75b1306be3c</sha1>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored_spectrogram.png" source="derivative">
<format>Spectrogram</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored.flac</original>
<mtime>1599685546</mtime>
<size>116769</size>
<md5>2ea631450681b8d955a9fcf669891d4a</md5>
<crc32>e32c035a</crc32>
<sha1>fcb550c1596a93528802646f072cd1b19c1b139b</sha1>
</file>
<file name="I Don_t Want to Set the World on Fire - Ink Spots-restored_whisper_asr.json" source="derivative">
<whisper_asr_module_version>20230611.01</whisper_asr_module_version>
<whisper_version>20230314</whisper_version>
<whisper_model_name>small.en</whisper_model_name>
<whisper_model_hash>sha256:f953ad0fd29cacd07d5a9eda5624af0f6bcf2258be67c92b79389873d91e0872</whisper_model_hash>
<asr_detected_lang>en</asr_detected_lang>
<asr_detected_lang_conf>0.85381597280502</asr_detected_lang_conf>
<asr_transcribed_lang>en</asr_transcribed_lang>
<format>Whisper ASR JSON</format>
<original>I Don_t Want to Set the World on Fire - Ink Spots-restored.mp3</original>
<mtime>1688008489</mtime>
<size>28875</size>
<md5>3b7a44eb35530253c8f22e55542a9eed</md5>
<crc32>c800afa0</crc32>
<sha1>770e390e635b714058d148b06a92fffd3181e2ba</sha1>
</file>
<file name="__ia_thumb.jpg" source="original">
<mtime>1634652950</mtime>
<size>12863</size>
<md5>bde829c30a7951d22eb88ad4c33f866c</md5>
<crc32>e2abeb1a</crc32>
<sha1>ac449c1db692c6c8e5af636012da5d275c000a4d</sha1>
<format>Item Tile</format>
<rotation>0</rotation>
</file>
</files>

View File

@@ -0,0 +1,195 @@
<?xml version="1.0" encoding="UTF-8"?>
<files>
<file name="__ia_thumb.jpg" source="original">
<mtime>1688105563</mtime>
<size>19642</size>
<md5>2dc43777ab13cabd2324e25d8c69a790</md5>
<crc32>e7f10d45</crc32>
<sha1>1ed3cb724f1470cbb5056169fc731c642e36fc1b</sha1>
<format>Item Tile</format>
<rotation>0</rotation>
</file>
<file name="header/header_0000.jp2" source="original">
<mtime>1686986524</mtime>
<size>12013083</size>
<md5>5928785725ea03932b3fd496d3f4c75e</md5>
<crc32>53f8e9a7</crc32>
<sha1>3af69d2c09d993d0f7bc81b7a2edfdd1f9b8446d</sha1>
<format>JPEG 2000</format>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42.pdf" source="derivative">
<pdf_module_version>0.0.23</pdf_module_version>
<format>Text PDF</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_page_numbers.json</original>
<mtime>1688105470</mtime>
<size>98013235</size>
<md5>8c206bd0aaf82698b3d502b233c6c2f8</md5>
<crc32>ac64d257</crc32>
<sha1>e6b7dfbde34f6a494f7795cd0edcb5676a8c37da</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_archive.torrent" source="metadata">
<btih>bf04ea0f7c2dca19cf748e529611f497e6cba150</btih>
<mtime>1688105603</mtime>
<size>21259</size>
<md5>0a3685a7ab0a0d0f9fdb4b913d31f8fd</md5>
<crc32>70eb691b</crc32>
<sha1>413c499bc001947b82030585c855958693cd2f78</sha1>
<format>Archive BitTorrent</format>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_chocr.html.gz" source="derivative">
<ocr>tesseract 5.3.0-3-g9920</ocr>
<ocr_parameters>lang-eng;two-pass-disabled;pass-dpi-disabled;autonomous-mode-disabled;binarisation-method-otsu</ocr_parameters>
<ocr_module_version>0.0.21</ocr_module_version>
<ocr_detected_script>Latin</ocr_detected_script>
<ocr_detected_script_conf>0.7458</ocr_detected_script_conf>
<ocr_detected_lang>en</ocr_detected_lang>
<ocr_detected_lang_conf>1.0000</ocr_detected_lang_conf>
<format>chOCR</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_jp2.zip</original>
<mtime>1688102450</mtime>
<size>11484860</size>
<md5>8fcb1864fd839ef3dcc6039b669b8f36</md5>
<crc32>87f7f712</crc32>
<sha1>15abc19f5cf46ccc4e8f1a5796ce6302869bffe5</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_djvu.txt" source="derivative">
<format>DjVuTXT</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_djvu.xml</original>
<mtime>1688103469</mtime>
<size>759494</size>
<md5>febe8a4594d3ef07af32f3fbed4d2764</md5>
<crc32>98136b35</crc32>
<sha1>5fe48b18f19568906680f8dd4936ec81ec143f9e</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_djvu.xml" source="derivative">
<format>Djvu XML</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_hocr.html</original>
<mtime>1688103134</mtime>
<size>10726635</size>
<md5>e06813d99e1adf8d6fff350899b5f846</md5>
<crc32>35fd1344</crc32>
<sha1>418da8f3cd5a9f6aac998ee5f0fa68a828aa78a8</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_files.xml" source="original">
<format>Metadata</format>
<md5>640a9c2fe776c10777911979bc04994a</md5>
<summation>md5</summation>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_frame-md.json" source="original">
<mtime>1686986516</mtime>
<size>224</size>
<md5>0f68d8e584bd1aea80a889525a00b547</md5>
<crc32>2e83a589</crc32>
<sha1>7fe89fdd2aa69246f30c34c73e57814f62154994</sha1>
<format>JSON</format>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_hocr.html" source="derivative">
<hocr_char_to_word_module_version>1.1.0</hocr_char_to_word_module_version>
<hocr_char_to_word_hocr_version>1.1.15</hocr_char_to_word_hocr_version>
<ocr_parameters>lang-eng;two-pass-disabled;pass-dpi-disabled;autonomous-mode-disabled;binarisation-method-otsu</ocr_parameters>
<ocr_module_version>0.0.21</ocr_module_version>
<ocr_detected_script>Latin</ocr_detected_script>
<ocr_detected_script_conf>0.7458</ocr_detected_script_conf>
<ocr_detected_lang>en</ocr_detected_lang>
<ocr_detected_lang_conf>1.0000</ocr_detected_lang_conf>
<format>hOCR</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_chocr.html.gz</original>
<mtime>1688102642</mtime>
<size>20717059</size>
<md5>2313d8cbe745bf4994b86be8f09b241b</md5>
<crc32>e3b89eb2</crc32>
<sha1>b5d6e6d025dca7315307aee1032e3470eb797ac4</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_hocr_pageindex.json.gz" source="derivative">
<hocr_pageindex_module_version>1.0.0</hocr_pageindex_module_version>
<hocr_pageindex_hocr_version>1.1.15</hocr_pageindex_hocr_version>
<format>OCR Page Index</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_hocr.html</original>
<mtime>1688103151</mtime>
<size>203</size>
<md5>aaf29479ec4d752ab5011ef1629a1de0</md5>
<crc32>de6755b7</crc32>
<sha1>d71e9705a5f1abb4eadcd920b06a961bf0eb293c</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_hocr_searchtext.txt.gz" source="derivative">
<hocr_fts_text_module_version>1.1.0</hocr_fts_text_module_version>
<hocr_fts_text_hocr_version>1.1.15</hocr_fts_text_hocr_version>
<word_conf_0_10>5195</word_conf_0_10>
<word_conf_11_20>2390</word_conf_11_20>
<word_conf_21_30>3139</word_conf_21_30>
<word_conf_31_40>3258</word_conf_31_40>
<word_conf_41_50>3191</word_conf_41_50>
<word_conf_51_60>3213</word_conf_51_60>
<word_conf_61_70>3776</word_conf_61_70>
<word_conf_71_80>5252</word_conf_71_80>
<word_conf_81_90>13153</word_conf_81_90>
<word_conf_91_100>85216</word_conf_91_100>
<format>OCR Search Text</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_hocr.html</original>
<mtime>1688103216</mtime>
<size>309695</size>
<md5>3d209f772e41f56191cb37ac04f8965a</md5>
<crc32>ea3470ec</crc32>
<sha1>c425dbfdf9900a6f1cb594e4e4403333c2ef4f36</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_itemimage.png" source="original">
<mtime>1686986511</mtime>
<size>33159468</size>
<md5>5e8e1ffe981317426081234ade24073e</md5>
<crc32>b8456619</crc32>
<sha1>2ffdc308b639959bbd13ddadbab8f8d4b847fbba</sha1>
<format>Item Image</format>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_jp2.zip" source="original">
<mtime>1686986495</mtime>
<size>231100229</size>
<md5>eac76d5be19d38caee6cdcee2b9ff936</md5>
<crc32>c2ce4d1c</crc32>
<sha1>858120c8724f345b206961abe508291565816b7d</sha1>
<preview-image>n0</preview-image>
<format>Single Page Processed JP2 ZIP</format>
<filecount>13</filecount>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_meta.sqlite" source="original">
<mtime>1686986699</mtime>
<size>40960</size>
<md5>385dd15968e9ce2a38ac48a2838e8c48</md5>
<crc32>192d70cb</crc32>
<sha1>09ab56c0b9b3eff6b0725364a4fd070705b80d2e</sha1>
<format>Metadata</format>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_meta.xml" source="original">
<mtime>1688105483</mtime>
<size>3028</size>
<md5>5ff8508ae78bdb3bbe56ab9de53b43bb</md5>
<crc32>1b81e6e4</crc32>
<sha1>30cc20a8cd9a9d726408f795b0fcc3db73459185</sha1>
<format>Metadata</format>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_page_numbers.json" source="derivative">
<format>Page Numbers JSON</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_djvu.xml</original>
<mtime>1688103557</mtime>
<size>2277</size>
<md5>a1bc72e8504b217ccd46c678745982f4</md5>
<crc32>634b90ea</crc32>
<sha1>680343d1c42c0732cdc9c8b8c355e5985aab5d6a</sha1>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_rotations.json" source="original">
<mtime>1686986519</mtime>
<size>1334</size>
<md5>37f40a3e763cda634832781f6f1d6775</md5>
<crc32>328b653d</crc32>
<sha1>f43ce2a767ee70f0c2cb2e004891f699213e27a1</sha1>
<format>JSON</format>
</file>
<file name="per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_scandata.xml" source="derivative">
<format>Scandata</format>
<original>per_chicago-daily-tribune_the-chicago-daily-tribun_1883-04-13_42_djvu.xml</original>
<mtime>1688103552</mtime>
<size>4478</size>
<md5>cfc96ac86bda784dd477131a9ce78d85</md5>
<crc32>35d000b3</crc32>
<sha1>45d344b009d902373579fd8939a1730b70a10ae4</sha1>
</file>
</files>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,12 @@
#Romname;Title;Emulator;Cloneof;Year;Manufacturer;Category;Players;Rotation;Control;Status;DisplayCount;DisplayType;AltRomname;AltTitle;Extra;Buttons;Favourite;Tags;PlayedCount;PlayedTime;FileIsAvailable
005;005;advmame;;1981;Sega;Maze / Shooter Small;2P alt;270;joystick (4-way),joystick (4-way);imperfect;1;raster;;;;1;;;0;;1
alpine;Alpine Ski (set 1);advmame;;1982;Taito Corporation;Sports / Skiing;2P alt;270;joystick (2-way),joystick (2-way);good;1;raster;;;;1;;;0;;1
amidar;Amidar;advmame;;1982;Konami;Maze / Outline;2P alt;90;joystick (4-way),joystick (4-way);good;1;raster;;;;1;;;0;;1
anteater;Anteater;advmame;;1982;Tago Electronics;Maze / Collect;2P alt;90;joystick (4-way);good;1;raster;;;;1;;;0;;1
armorcar;Armored Car (set 1);advmame;;1981;Stern Electronics;Maze / Collect;2P alt;90;joystick (4-way),joystick (4-way);good;1;raster;;;;2;;;0;;1
assault;Assault (Rev B);advmame;;1988;Namco;Shooter / Driving;1P;90;double joystick (4-way),double joystick (4-way);good;1;raster;;;;1;;;0;;1
astrob;Astro Blaster (version 3);advmame;;1981;Sega;Shooter / Gallery;2P alt;270;joystick (2-way),joystick (2-way);imperfect;1;raster;;;;2;;;0;;1
astrof;Astro Fighter (set 1);advmame;;1979;Data East;Shooter / Gallery;2P alt;90;joystick (2-way),joystick (2-way);imperfect;1;raster;;;;1;;;0;;1
attckufo;Attack UFO;advmame;;1980;Ryoto Electric Co.;Shooter / Gallery;2P alt;270;joystick (2-way),joystick (2-way);good;1;raster;;;;1;;;0;;1
bagman;Bagman;advmame;;1982;Valadon Automation;Platform / Run Jump;2P alt;270;joystick (4-way),joystick (4-way);good;1;raster;;;;1;;;0;;1
ballbomb;Balloon Bomber;advmame;;1980;Taito;Shooter / Gallery;2P alt;270;joystick (2-way),joystick (2-way);imperfect;1;raster;;;;1;;;0;;1

View File

@@ -0,0 +1,887 @@
clrmamepro (
name "Other Emulated Arcade Games"
description "Other Emulated Arcade Games (20030817)"
category "Arcade"
version "20030817"
author "#RomManager"
)
# Some sets in this dat are partial because only the sound is emulated.
# They're included here because I don't have the infos for the other roms of the set
# Please contact me if you have found such informations, or complete romsets for them.
game (
name bm1stmix
description "Beatmania [DJMAME 08-07-2003]"
year 1997
manufacturer "Konami"
rom ( name 753jaa03.19a size 524288 crc 0xf2b2bce8 sha1 61d31b111f35e7dde89965fa43ba627c12aff11c )
rom ( name 753jaa04.20a size 524288 crc 0x85a18f9d sha1 ecd0ab4f53e882b00176dacad5fac35345fbea66 )
rom ( name 753jaa05.22a size 524288 crc 0x749b1e87 sha1 1c771c19f152ae95171e4fd51da561ba4ec5ea87 )
rom ( name 753jaa06.24a size 524288 crc 0x6d86b0fd sha1 74a255dbb1c83131717ea1fe335f12aef81d9fcc )
rom ( name 753jaa07.22d size 524288 crc 0xf03ab5d8 sha1 2ad902547908208714855aa0f2b7ed493452ee5f )
rom ( name 753jaa08.23d size 524288 crc 0x6559f0c8 sha1 0d6ec4bdc22c02cb9fb8de36b0a8f7a6c983440e )
rom ( name 753jaa09.25d size 524288 crc 0xb50c3dbb sha1 6022ea249aad0793b2279699e68087b4bc9b4ef1 )
rom ( name 753jaa10.27d size 524288 crc 0x391f4bfd sha1 791c9889ea3ce639bbfb87934a1cad9aa3c9ccde )
rom ( name 753jab01.6a size 524288 crc 0x25bf8629 sha1 2be73f9dd25cae415c6443f221cc7d38d5555ae5 )
rom ( name 753jab02.8a size 524288 crc 0x6ab951de sha1 a724ede03b74e9422c120fcc263e2ebcc3a3e110 )
disk ( name 753jaa11.chd md5 260c9b72f4a03055e3abad61c6225324 )
)
game (
name bm2ndmix
description "Beatmania 2nd MIX (Rev.B) [DJMAME 08-07-2003]"
year 1998
manufacturer "Konami"
rom ( name 853jaa03.19a size 524288 crc 0x1462ed23 sha1 fdfda3060c8d367ac2e8e43dedaba8ab9012cc77 )
rom ( name 853jaa04.20a size 524288 crc 0x98c9b331 sha1 51f24b3c3773c53ff492ed9bad17c9867fd94e28 )
rom ( name 853jaa05.22a size 524288 crc 0x0da3fef9 sha1 f9ef24144c00c054ecc4650bb79e74c57c6d6b3c )
rom ( name 853jaa06.24a size 524288 crc 0x6a66978c sha1 460178a6f35e554a157742d77ed5ea6989fbcee1 )
rom ( name 853jaa07.22d size 524288 crc 0x728c0010 sha1 18888b402e0b7ccf63c7b3cb644673df1746dba7 )
rom ( name 853jaa08.23d size 524288 crc 0x926fc37c sha1 f251cba56ca201f0e748112462116cff218b66da )
rom ( name 853jaa09.25d size 524288 crc 0x8584e21e sha1 3d1ca6de00f9ac07bbe7cd1e67093cca7bf484bb )
rom ( name 853jaa10.27d size 524288 crc 0x9cb92d98 sha1 6ace4492ba0b5a8f94a9e7b4f7126b31c6254637 )
rom ( name 853jab01.6a size 524288 crc 0xc8df72c0 sha1 6793b587ba0611bc3da8c4955d6a87e47a19a223 )
rom ( name 853jab02.8a size 524288 crc 0xbf6ace08 sha1 29d3fdf1c73a73a0a66fa5a4c4ac3f293cb82e37 )
disk ( name 853jaa11.chd md5 37281741b748bea7dfa711a956649d1e )
)
game (
name bm2ndmxa
description "Beatmania 2nd MIX (Rev.A) [DJMAME 08-07-2003]"
year 1998
manufacturer "Konami"
cloneof bm2ndmix
romof bm2ndmix
rom ( name 853jaa01.6a size 524288 crc 0x4f0bf5d0 sha1 4793bb411e85f2191eb703a170c16cf163ea79e7 )
rom ( name 853jaa02.8a size 524288 crc 0xe323925b sha1 1f9f52a7ab6359b617e87f8b3d7ac4269885c621 )
rom ( name 853jaa03.19a size 524288 crc 0x1462ed23 sha1 fdfda3060c8d367ac2e8e43dedaba8ab9012cc77 )
rom ( name 853jaa04.20a size 524288 crc 0x98c9b331 sha1 51f24b3c3773c53ff492ed9bad17c9867fd94e28 )
rom ( name 853jaa05.22a size 524288 crc 0x0da3fef9 sha1 f9ef24144c00c054ecc4650bb79e74c57c6d6b3c )
rom ( name 853jaa06.24a size 524288 crc 0x6a66978c sha1 460178a6f35e554a157742d77ed5ea6989fbcee1 )
rom ( name 853jaa07.22d size 524288 crc 0x728c0010 sha1 18888b402e0b7ccf63c7b3cb644673df1746dba7 )
rom ( name 853jaa08.23d size 524288 crc 0x926fc37c sha1 f251cba56ca201f0e748112462116cff218b66da )
rom ( name 853jaa09.25d size 524288 crc 0x8584e21e sha1 3d1ca6de00f9ac07bbe7cd1e67093cca7bf484bb )
rom ( name 853jaa10.27d size 524288 crc 0x9cb92d98 sha1 6ace4492ba0b5a8f94a9e7b4f7126b31c6254637 )
disk ( name 853jaa11.chd md5 37281741b748bea7dfa711a956649d1e )
)
game (
name bm3rdmix
description "Beatmania 3rd MIX (Rev.B) [DJMAME 08-07-2003]"
year 1998
manufacturer "Konami"
rom ( name 825jaa03.19a size 524288 crc 0xecd62652 sha1 bceab4052dce2c843358f0a98aacc6e1124e3068 )
rom ( name 825jaa04.20a size 524288 crc 0x437a576f sha1 f30fd15d4f0d776e9b29ccfcd6e26861fb42e51a )
rom ( name 825jaa05.22a size 524288 crc 0x9f9a3369 sha1 d8b20127336af89b9e886289fb4f5a2e0db65f9b )
rom ( name 825jaa06.24a size 524288 crc 0xe7a3991a sha1 6c8cb481e721428e1365f784e97bb6f6d421ed5a )
rom ( name 825jab01.6a size 524288 crc 0x934fdcb2 sha1 b88bada065b5464c579039c2e403c061e6eeb356 )
rom ( name 825jab02.8a size 524288 crc 0x6012c488 sha1 df32db41942c2fe2b2aa7439900372e22ea54c3c )
rom ( name 825jab07.22d size 524288 crc 0x1a515c82 sha1 a0c908d449aa45cb3a90a42c97429f10873e884b )
rom ( name 825jab08.23d size 524288 crc 0x82731b07 sha1 c0d391fcd94c6b2225fca338c0c5db5d35e2d8bc )
rom ( name 825jab09.25d size 524288 crc 0x1407ba5d sha1 e7a0d190326589f4d94e83cb7c85dd4e91f4efad )
rom ( name 825jab10.27d size 524288 crc 0x2afd0a10 sha1 1b8b868ac5720bb1b376f4eb8952efb190257bda )
)
game (
name bm3rdmxa
description "Beatmania 3rd MIX (Rev.A) [DJMAME 08-07-2003]"
year 1998
manufacturer "Konami"
cloneof bm3rdmix
romof bm3rdmix
rom ( name 825jaa01.6a size 524288 crc 0xcf7494a5 sha1 994df0644817f44d135a16f04d8dae9ec73e3728 )
rom ( name 825jaa02.8a size 524288 crc 0x5f787fe2 sha1 5944da21141802d96594cf77880682e97d014ca1 )
rom ( name 825jaa03.19a size 524288 crc 0xecd62652 sha1 bceab4052dce2c843358f0a98aacc6e1124e3068 )
rom ( name 825jaa04.20a size 524288 crc 0x437a576f sha1 f30fd15d4f0d776e9b29ccfcd6e26861fb42e51a )
rom ( name 825jaa05.22a size 524288 crc 0x9f9a3369 sha1 d8b20127336af89b9e886289fb4f5a2e0db65f9b )
rom ( name 825jaa06.24a size 524288 crc 0xe7a3991a sha1 6c8cb481e721428e1365f784e97bb6f6d421ed5a )
rom ( name 825jaa07.22d size 524288 crc 0xa96cf46c sha1 c8540b452dcb15f5873ca629fa62657a5a3bb02c )
rom ( name 825jaa08.23d size 524288 crc 0x06d56c3b sha1 19cd15ab0869773e6a16b1cad48c53bec2f60b0b )
rom ( name 825jaa09.25d size 524288 crc 0xd3e65669 sha1 51abf452da60794fa47c05d11c08b203dde563ff )
rom ( name 825jaa10.27d size 524288 crc 0x44d184f3 sha1 28f3ec33a29164a6531f53db071272ccf015f66d )
disk ( name 825jaa11.chd md5 3276e3ed57f1a6d9a18365054b0439ba )
)
game (
name bm4thmix
description "Beatmania 4th MIX [DJMAME 08-07-2003]"
year 1999
manufacturer "Konami"
rom ( name 847jaa01.6a size 524288 crc 0x81138a1b sha1 ebe211126f871e541881e1670f56d50b058dead3 )
rom ( name 847jaa02.8a size 524288 crc 0x4eeb0010 sha1 942303dfb19a4a78dd74ad24576031760553a661 )
rom ( name 847jaa03.19a size 524288 crc 0xf447d140 sha1 cc15b80419940d127a77765508f877421ed86ee2 )
rom ( name 847jaa04.20a size 524288 crc 0xedc3e286 sha1 341b1dc6ee1562b1ddf235a66ac96b94c482b67c )
rom ( name 847jaa05.22a size 524288 crc 0xda165b5e sha1 e46110590e6ab89b55f6abfbf6c53c99d28a75a9 )
rom ( name 847jaa06.24a size 524288 crc 0x8bfc2f28 sha1 f8869867945d63d9f34b6228d95c5a61b193eed2 )
rom ( name 847jab07.22d size 524288 crc 0xc159e7c4 sha1 96af0c29b2f1fef494b2223179862d16f26bb33f )
rom ( name 847jab08.23d size 524288 crc 0x8ff084d6 sha1 50cff8c701e33f2630925c1a9ae4351076912acd )
rom ( name 847jab09.25d size 524288 crc 0x2e4ac9fe sha1 bbd4c6e0c82fc0be88f851e901e5853b6bcf775f )
rom ( name 847jab10.27d size 524288 crc 0xc78516f5 sha1 1adf5805c808dc55de14a9a9b20c3d2cf7bf414d )
disk ( name 847jaa11.chd md5 47cb5c1b856aa11cf38f0c7ea4a7d1c3 )
)
game (
name bm5thmix
description "Beatmania 5th MIX [DJMAME 08-07-2003]"
year 1999
manufacturer "Konami"
rom ( name 981jaa01.6a size 524288 crc 0x03bbe7e3 sha1 7d4ec3bc7719a3f1b81df309b5c74afaffde42ba )
rom ( name 981jaa02.8a size 524288 crc 0xf4e59923 sha1 a4983435e3f2243ea9ccc2fd5439d86c30b6f604 )
rom ( name 981jaa03.19a size 524288 crc 0x8b7e6d72 sha1 d470377e20e4d4935af5e57d081ce24dd9ea5793 )
rom ( name 981jaa04.20a size 524288 crc 0x5139988a sha1 2b1eb97dcbfbe6bba1352a02cf0036e9a721ab39 )
rom ( name 981jaa05.22a size 524288 crc 0xf370fdb9 sha1 3a2bbdda984f2630e8ae505a8db259d9162e07a3 )
rom ( name 981jaa06.24a size 524288 crc 0xda6e3813 sha1 9163bd2cfb0a32798e797c7b4eea21e28772a206 )
rom ( name 981jaa07.22d size 524288 crc 0xf6c72998 sha1 e78af5b515b224c534f47abd6477dd97dc521b0d )
rom ( name 981jaa08.23d size 524288 crc 0xaa4ff682 sha1 3750e1e81b7c1a4fb419076171f20e4c36b1c544 )
rom ( name 981jaa09.25d size 524288 crc 0xd96d4e1c sha1 379aa4e82cd06490645f54dab1724c827108735d )
rom ( name 981jaa10.27d size 524288 crc 0x06bee0e4 sha1 6eea8614cb01e7079393b9976b6fd6a52c14e3c0 )
disk ( name 981jaa11.chd md5 0058bbdcb5db054adff1c4148ef4211e )
)
game (
name bm6thmix
description "Beatmania 6th MIX [DJMAME 08-07-2003]"
year 2001
manufacturer "Konami"
rom ( name a21jaa01.6a size 524288 crc 0x6d7ccbe3 sha1 633c69c14dfd70866664b94095fa5f21087428d8 )
rom ( name a21jaa02.8a size 524288 crc 0xf10076fa sha1 ab9f3e75a36fdaccec411afd77f588f040db139d )
rom ( name a21jaa03.19a size 524288 crc 0xca806266 sha1 6b5f9d5089a992347745ab6af4dadaac4e3b0742 )
rom ( name a21jaa04.20a size 524288 crc 0x71124e79 sha1 d9fd8f662ac9c29daf25acd310fd0f27051dea0b )
rom ( name a21jaa05.22a size 524288 crc 0x818e34e6 sha1 8a9093b92392a065d0cf94d56195a6f3ca611044 )
rom ( name a21jaa06.24a size 524288 crc 0x36f2043b sha1 d2846cc10173662029da7c5d686cf89299be2be5 )
rom ( name a21jaa07.22d size 524288 crc 0x841d83e1 sha1 c85962abcc955e8f11138e03002b16afd3791f0a )
rom ( name a21jaa08.23d size 524288 crc 0x4e561919 sha1 4b91560d9ba367c848d784db760f042d5d76e003 )
rom ( name a21jaa09.25d size 524288 crc 0x181e6f70 sha1 82c7ca3068ace9a66b614ead4b90ea6fe4017d51 )
rom ( name a21jaa10.27d size 524288 crc 0x1ac33595 sha1 3173bb8dc420487c4d427e779444a98aad37d51e )
disk ( name a21jaa11.chd md5 e50ff33d5b9eb179265ff6cd7824824e )
)
game (
name bm7thmix
description "Beatmania 7th MIX [DJMAME 08-07-2003]"
year 2001
manufacturer "Konami"
rom ( name b07jaa03.19a size 524288 crc 0x3e30af3f sha1 f092c4156bc7d0a0309171fd1e00a6d4c33cb08f )
rom ( name b07jaa04.20a size 524288 crc 0x190a4a83 sha1 f7ae2d3ccd98f99fdae61c1a2145f993c4064ebd )
rom ( name b07jaa05.22a size 524288 crc 0x415a6363 sha1 b3edbcd293006c3738a10680ecfa66e105028786 )
rom ( name b07jaa06.24a size 524288 crc 0x46c59a43 sha1 ba58432bf7df394b5c633e63bcf2321bc320f023 )
rom ( name b07jaa07.22d size 524288 crc 0xb2908dc7 sha1 22e36afef9a03681928d37a8ffe50078d04525ce )
rom ( name b07jaa08.23d size 524288 crc 0xcbbefecf sha1 ed1347d1a8fd59677e4290b8cd568ddf505a7265 )
rom ( name b07jaa09.25d size 524288 crc 0x2530cedb sha1 94b38b4fe198b26a2ff4d99d2cb28a0f935fe940 )
rom ( name b07jaa10.27d size 524288 crc 0x6b75ba9c sha1 aee922adc3bc0296ae6e08e461b20a9e5e72a2df )
rom ( name b07jab01.6a size 524288 crc 0x433d0074 sha1 5a9709ce200cbff340063469956d1c55a46810d9 )
rom ( name b07jab02.8a size 524288 crc 0x794773af sha1 c823deb077f6515d7701de84d324c3d367719819 )
disk ( name b07jab11.chd md5 0e9440787ca69567792095085e2a3619 )
)
game (
name bmclubmx
description "Beatmania Club MIX [DJMAME 08-07-2003]"
year 2000
manufacturer "Konami"
rom ( name 993jaa01.6a size 524288 crc 0xb314af94 sha1 6448554e1d565ee1558d13f484b5fa0018ac3667 )
rom ( name 993jaa02.8a size 524288 crc 0x0aa9f16a sha1 508d41e141997ba07443c4ab98454cec515d731c )
rom ( name 993jaa03.19a size 524288 crc 0x00394778 sha1 3631a42ed0c8ee572e7faafdaacce9fc2b372d25 )
rom ( name 993jaa04.20a size 524288 crc 0x2522f3b0 sha1 1ab8618b732f1402fc7bfb141630873d4c706d34 )
rom ( name 993jaa05.22a size 524288 crc 0x4e340947 sha1 a0a7f3b222a292b07bc5c7acd61547ea2bdbad43 )
rom ( name 993jaa06.24a size 524288 crc 0xc0a711d6 sha1 ab581c5215c4db6dbf58b47f54834fe81e8a569b )
rom ( name 993jaa07.22d size 524288 crc 0x4fc588cf sha1 00fb73002b6b5ae414eef320169e379b94ee33a1 )
rom ( name 993jaa08.23d size 524288 crc 0xb6c88e9e sha1 e3b76e782b9507dad2bdb9de1a34d125f6100cc8 )
rom ( name 993jaa09.25d size 524288 crc 0xe1a172dd sha1 42e850c055dc5bfccf6b6989f9f3a945fce13006 )
rom ( name 993jaa10.27d size 524288 crc 0x9d113a2d sha1 eee94a5f7015c49aa630b8df0c8e9d137d238811 )
disk ( name 993jaa11.chd md5 e26eb62d7cf3357585f5066da6063143 )
)
game (
name bmcompm2
description "Beatmania complete MIX 2 [DJMAME 08-07-2003]"
year 2000
manufacturer "Konami"
rom ( name 988jaa01.6a size 524288 flags nodump sha1 - )
rom ( name 988jaa02.8a size 524288 flags nodump sha1 - )
rom ( name 988jaa03.19a size 524288 flags nodump sha1 - )
rom ( name 988jaa04.20a size 524288 flags nodump sha1 - )
rom ( name 988jaa05.22a size 524288 flags nodump sha1 - )
rom ( name 988jaa06.24a size 524288 flags nodump sha1 - )
rom ( name 988jaa07.22d size 524288 flags nodump sha1 - )
rom ( name 988jaa08.23d size 524288 flags nodump sha1 - )
rom ( name 988jaa09.25d size 524288 flags nodump sha1 - )
rom ( name 988jaa10.27d size 524288 flags nodump sha1 - )
disk ( name 988jaa11.chd md5 cc21d58d6bee58f1c4baf08f345fe2c5 )
)
game (
name bmcompmx
description "Beatmania complete MIX [DJMAME 08-07-2003]"
year 1999
manufacturer "Konami"
rom ( name 858jaa03.19a size 524288 crc 0x8559f457 sha1 133092994087864a6c29e9d51dcdbef2e2c2a123 )
rom ( name 858jaa04.20a size 524288 crc 0x770824d3 sha1 5c21bc39f8128957d76be85bc178c96976987f5f )
rom ( name 858jaa05.22a size 524288 crc 0x9ce769da sha1 1fe2999f786effdd5e3e74475e8431393eb9403d )
rom ( name 858jaa06.24a size 524288 crc 0x0cde6584 sha1 fb58d2b4f58144b71703431740c0381bb583f581 )
rom ( name 858jaa07.22d size 524288 crc 0x7d183f46 sha1 7a1b0ccb0407b787af709bdf038d886727199e4e )
rom ( name 858jaa08.23d size 524288 crc 0xc731dc8f sha1 1a937d76c02711b7f73743c9999456d4408ad284 )
rom ( name 858jaa09.25d size 524288 crc 0x0b4ad843 sha1 c01e15053dd1975dc68db9f4e6da47062d8f9b54 )
rom ( name 858jaa10.27d size 524288 crc 0x00b124ee sha1 435d28a327c2707833a8ddfe841104df65ffa3f8 )
rom ( name 858jab01.6a size 524288 crc 0x92841eb5 sha1 3a9d90a9c4b16cb7118aed2cadd3ab32919efa96 )
rom ( name 858jab02.8a size 524288 crc 0x7b19969c sha1 3545acabbf53bacc5afa72a3c5af3cd648bc2ae1 )
disk ( name 858jaa11.chd md5 e7b26f6f03f807a32b2e5e291324d582 )
)
game (
name bmcorerm
description "Beatmania CORE REMIX [DJMAME 08-07-2003]"
year 2000
manufacturer "Konami"
rom ( name a05jaa01.6a size 524288 crc 0xcd6f1fc5 sha1 237cbc17a693efb6bffffd6afb24f0944c29330c )
rom ( name a05jaa02.8a size 524288 crc 0xfe07785e sha1 14c652008cb509b5206fb515aad7dfe36a6fe6f4 )
rom ( name a05jaa03.19a size 524288 crc 0x8b88932a sha1 df20f8323adb02d07b835da98f4a29b3142175c9 )
rom ( name a05jaa04.20a size 524288 crc 0xcc72629f sha1 f95d06f409c7d6422d66a55c0452eb3feafc6ef0 )
rom ( name a05jaa05.22a size 524288 crc 0xe241b22b sha1 941a76f6ac821e0984057ec7df7862b12fa657b8 )
rom ( name a05jaa06.24a size 524288 crc 0x77eb08a3 sha1 fd339aaec06916abfc928e850e33480707b5450d )
rom ( name a05jaa07.22d size 524288 crc 0x4d79646d sha1 5f1237bbd3cb09b27babf1c5359ef6c0d80ae3a9 )
rom ( name a05jaa08.23d size 524288 crc 0xf067494f sha1 ef031b5501556c1aa047a51604a44551b35a8b99 )
rom ( name a05jaa09.25d size 524288 crc 0x1504d62c sha1 3c31c6625bc089235a96fe21021239f2d0c0f6e1 )
rom ( name a05jaa10.27d size 524288 crc 0x99d75c36 sha1 9599420863aa0a9492d3caeb03f8ac5fd4c3cdb2 )
disk ( name a05jaa11.chd md5 180f7b1b2145fab2d2ba717780f2ca26 )
)
game (
name bmfinal
description "Beatmania THE FINAL [DJMAME 08-07-2003]"
year 2002
manufacturer "Konami"
rom ( name c01jaa01.6a size 524288 crc 0xa64eeff7 sha1 377eee1f41e3072f9154a7c17ec4c4f3fb63ea4a )
rom ( name c01jaa02.8a size 524288 crc 0x599bdac5 sha1 f85aff020c92fcd3c2a42036615226b54e5bee98 )
rom ( name c01jaa03.19a size 524288 crc 0x1c9c6eb7 sha1 bd1a9d8ed78095328817f599f52d9d34e09e9275 )
rom ( name c01jaa04.20a size 524288 crc 0x4e5aa665 sha1 22f3888a29497ff0a801cce620ca0373268e5cd9 )
rom ( name c01jaa05.22a size 524288 crc 0x37dab217 sha1 66b07c36e7749a4c9d9dfaca633958a4922c4562 )
rom ( name c01jaa06.24a size 524288 crc 0xd35c6818 sha1 ce608603ea3662f8cda5cf958a676d64a0f74645 )
rom ( name c01jaa07.22d size 524288 crc 0x3e70f506 sha1 d3cd0b48383bf2514b7f47fade8549ea8e3c5555 )
rom ( name c01jaa08.23d size 524288 crc 0x535e6065 sha1 131f7eec4179145781bbd23474202f4eaf9cefd0 )
rom ( name c01jaa09.25d size 524288 crc 0x45cf93b1 sha1 7c5082bcd1fe15761a0a965e25dda121904ff1bd )
rom ( name c01jaa10.27d size 524288 crc 0xc9927749 sha1 c2644877bda483e241381265e723ea8ab8357761 )
disk ( name c01jaa11.chd md5 8bb7e6b6bc63cac8a4f2997307c25748 )
)
game (
name "boogwing"
description "Boogie Wings / The Great Ragtime Show [sound only] [M1 v0.7.2]"
year "1992"
manufacturer "Data East Corporation"
rom ( name kn06.18p size 65536 crc 0x3e8bc4e1 md5 96598bfa19b4c6a3d0820d37610f106c sha1 7e4c357afefa47b8f101727e06485eb9ebae635d )
rom ( name mbd-09.16p size 524288 crc 0xf44f2f87 md5 aec9026003daf08468f59570b2449140 sha1 d941520bdfc9e6d88c45462bc1f697c18f33498e )
rom ( name mbd-10.17p size 524288 crc 0xf159f76a md5 aaee9f2c53cf7551ed9155ef6a58b6d9 sha1 0b1ea69fecdd151e2b1fa96a21eade492499691d )
)
game (
name "bubbletr"
description "Bubble Trouble [sound only] [M1 v0.7.2]"
year "1992"
manufacturer "Namco"
rom ( name "btl-snd0.bin" size 131072 crc 46a5c625 )
rom ( name "btl-voi1.bin" size 524288 crc 08b3a089 )
)
game (
name "densdeg2"
description "Densya De Go! 2 [sound only] [M1 v0.7.2]"
year "1998"
manufacturer "Taito"
rom ( name e52-23.034 size 2097152 crc 0xebe2dcef md5 e6104313948f853a8ecd1bd18ec72d92 sha1 16ae41e0f3bb242cbc2922f53cacbd99961a3f97 )
rom ( name e52-24.035 size 2097152 crc 0xa9a678da md5 921b4c8a36ecd14eb7f01e4d0b88fcfa sha1 b980ae644ef0312acd63b017028af9bf2b084c29 )
rom ( name e52-29.030 size 262144 crc 0x6010162a md5 b04a28cbac20ae12113fb7c35f4ed6f8 sha1 f14920b26887f5387b3e261b63573d850195982a )
rom ( name e52-30.031 size 262144 crc 0x2881af4a md5 a18886c09fbdbf48e4d3de482f6bdf32 sha1 5918f6508b3cd3bef3751e3bda2a48152569c1cd )
)
game (
name "densdego"
description "Densya De Go! [sound only] [M1 v0.7.2]"
year "1997"
manufacturer "Taito"
rom ( name e35-19.034 size 2097152 crc 0xebe2dcef md5 e6104313948f853a8ecd1bd18ec72d92 sha1 16ae41e0f3bb242cbc2922f53cacbd99961a3f97 )
rom ( name e35-20.035 size 2097152 crc 0xa1d4b30d md5 9caf73184e7f0009c29dabcb3bbe864c sha1 e02f613b93d3b3ee1eb23f5b7f62c5448ed3966d )
rom ( name e35-25.030 size 262144 crc 0x8104de13 md5 a64d6ce68282462ce06a10707980cf52 sha1 e518fbaf91704cf5cb8ffbb4833e3adba8c18658 )
rom ( name e35-26.031 size 262144 crc 0x61821cc9 md5 ace8158a5f29774f78d2ac32f3fcc187 sha1 87cd5bd3bb22c9f4ca4b6d96f75434d48418321b )
)
game (
name "gprider"
description "GP Rider [sound only] [M1 v0.7.2]"
year "1990"
manufacturer "Sega"
rom ( name epr13388.bin size 65536 crc 0x706581e4 md5 47c13b07b33f483aca9c78eae5af3d26 sha1 51c9dbf2bf0d6b8826de24cd33596f5c95136870 )
rom ( name opr13389.bin size 131072 crc 0x4e4c758e md5 62000b02dad71e40dd424e8ab6fc997c sha1 181750dfcdd6d5b28b063c980c251991163d9474 )
rom ( name opr13390.bin size 131072 crc 0x8c93cd05 md5 26da18d369f44f581bda80fb30a0a299 sha1 bb08094abac6c104eddf14f634e9791f03122946 )
rom ( name opr13391.bin size 131072 crc 0x8c30c867 md5 809395811c011076730078b05769f14e sha1 0d735291b1311890938f8a1143fae6af9feb2a69 )
)
game (
name "gt97"
description "Golden Tee Golf '97 [sound only] [M1 v0.7.2]"
year "1997"
manufacturer "Incredible Technologies"
rom ( name gt97_s1.bin size 524288 crc 0x9fc8d818 md5 678cb578d23cbf72deec43b26665029b sha1 61c0bf2807b1ca8db123cc236f83543b6b33ac0b )
rom ( name gt97nr.u88 size 131072 crc 0x2cee9e98 md5 ffb07e422db94a602fb965e01593ba68 sha1 02edac7abab2335c1cd824d1d9b26aa32238a2de )
rom ( name gt97s0.bin size 1048576 crc 0xf4c9eebb md5 2ea87cf31d960a786d3a6bfae00a1e05 sha1 7e765fb894706b30c1bbd4353e921e7a456cf521 )
)
game (
name hmcompm2
description "Hiphopmania complete MIX 2 [DJMAME 08-07-2003]"
year 2000
manufacturer "Konami"
cloneof bmcompm2
romof bmcompm2
rom ( name 988uaa01.6a size 524288 crc 0x5e5cc6c0 sha1 0e7cd601d4543715cbc9f65e6fd48837179c962a )
rom ( name 988uaa02.8a size 524288 crc 0xe262984a sha1 f47662e40f91f2addb1a4b649923c1d0ee017341 )
rom ( name 988uaa03.19a size 524288 crc 0xd0f204c8 sha1 866baac5a6d301d5b9cf0c14e9937ee5f435db77 )
rom ( name 988uaa04.20a size 524288 crc 0x74c6b3ed sha1 7d9b064bab3f29fc6435f6430c71208abbf9d861 )
rom ( name 988uaa05.22a size 524288 crc 0x6b9321cb sha1 449e5f85288a8c6724658050fa9521c7454a1e46 )
rom ( name 988uaa06.24a size 524288 crc 0xda6e0c1e sha1 4ef37db6c872bccff8c27fc53cccc0b269c7aee4 )
rom ( name 988uaa07.22d size 524288 crc 0x9217870d sha1 d0536a8a929c41b49cdd053205165bfb8150e0c5 )
rom ( name 988uaa08.23d size 524288 crc 0x77777e59 sha1 33b5508b961a04b82c9967a3326af6bbd838b85e )
rom ( name 988uaa09.25d size 524288 crc 0xc2ad6810 sha1 706388c5acf6718297fd90e10f8a673463a0893b )
rom ( name 988uaa10.27d size 524288 crc 0xdab0f3c9 sha1 6fd899e753e32f60262c54ab8553c686c7ef28de )
disk ( name 988jaa11.chd md5 cc21d58d6bee58f1c4baf08f345fe2c5 )
)
game (
name hmcompmx
description "Hiphopmania complete MIX [DJMAME 08-07-2003]"
year 1999
manufacturer "Konami"
cloneof bmcompmx
romof bmcompmx
rom ( name 858uaa03.19a size 524288 crc 0x52b51a5e sha1 9f01e2fcbe5a9d7f80b377c5e10f18da2c9dcc8e )
rom ( name 858uaa04.20a size 524288 crc 0xa336cee9 sha1 0e62c0c38d86868c909b4c1790fbb7ecb2de137d )
rom ( name 858uaa05.22a size 524288 crc 0x2e14cf83 sha1 799b2162f7b11678d1d260f7e1eb841abda55a60 )
rom ( name 858uaa06.24a size 524288 crc 0x2be07788 sha1 5cc2408f907ca6156efdcbb2c10a30e9b81797f8 )
rom ( name 858uaa07.22d size 524288 crc 0x9d7c8ea0 sha1 5ef773ade7ab12a5dc10484e8b7711c9d76fe2a1 )
rom ( name 858uaa08.23d size 524288 crc 0xf21c3f45 sha1 1d7ff2c4161605b382d07900142093192aa93a48 )
rom ( name 858uaa09.25d size 524288 crc 0x99519886 sha1 664f6bd953201a6e2fc123cb8b3facf72766107d )
rom ( name 858uaa10.27d size 524288 crc 0x20aa7145 sha1 eeff87eb9a9864985d751f45e843ee6e73db8cfd )
rom ( name 858uab01.6a size 524288 crc 0xf9c16675 sha1 f2b50a3544f43af6fd987256a8bd4125b95749ef )
rom ( name 858uab02.8a size 524288 crc 0x4e8f1e78 sha1 88d654de4377b584ff8a5e1f8bc81ffb293ec8a5 )
disk ( name 858jaa11.chd md5 e7b26f6f03f807a32b2e5e291324d582 )
)
game (
name "pdrift"
description "Power Drift [sound only] [M1 v0.7.2]"
year "1988"
manufacturer "Sega"
rom ( name 11754.bin size 524288 crc 0xebeb8484 md5 3a60a2abd9de0fa5fdc827c6fe0aa5a5 sha1 269f33cb1a9be126bada858e25291385d48686a2 )
rom ( name 11755.bin size 131072 crc 0x6ab0646e md5 6c87b5256270bab377fed3b33484223f sha1 1a02466e617644e0d7b0311297b2bd128829ba4e )
)
game (
name popn1
description "Pop'n Music 1 [DJMAME 08-07-2003]"
year 1998
manufacturer "Konami"
rom ( name 803jaa01.6a size 524288 flags baddump crc 0xb5b5a6c1 sha1 45f57e7b3ca201355f0e0e9f607c3ad031eaf7f8 )
rom ( name 803jaa02.8a size 524288 flags baddump crc 0x27460aec sha1 e803553f643f982c59ed7485580b1b49cd9a9b9c )
rom ( name 803jaa03.19a size 524288 crc 0xd80315f6 sha1 070ea8d00aeecce1e357be5a9c434ef46f57a7e9 )
rom ( name 803jaa04.20a size 524288 crc 0xf7b9ac82 sha1 898fbe229a3fdea5988d46359d030c3ec35eaafd )
rom ( name 803jaa05.22a size 524288 flags baddump crc 0x2902f6df sha1 658ccae9a67196a310bd69870c350058d2911feb )
rom ( name 803jaa06.24a size 524288 flags baddump crc 0x508f326a sha1 a55c17f88b5856a754f00a6e32b6f60685a88bec )
rom ( name 803jaa07.22d size 524288 crc 0xb9c12071 sha1 8f67965d5c8e7c9bfac528a77a9e7c8e0d8b17c8 )
rom ( name 803jaa08.23d size 524288 crc 0xa263f819 sha1 b479a215282212e9253e4085640c0638a4036e31 )
rom ( name 803jaa09.25d size 524288 crc 0x0b8f22fa sha1 21df493dbe50520a784dc2a141de638926ea4be4 )
rom ( name 803jaa10.27d size 524288 crc 0x094c5cbc sha1 603417f2ca197731ccccbce9117bec8fcd2e8fa3 )
disk ( name 803jaa11.chd md5 54a8ac87857d81740621c622e27736d7 )
)
game (
name popn2
description "Pop'n Music 2 [DJMAME 08-07-2003]"
year 1998
manufacturer "Konami"
rom ( name 831jaa01.6a size 524288 crc 0xaabe8689 sha1 18e74c81710228c91ab9eb554b63d9bd69b93ec8 )
rom ( name 831jaa02.8a size 524288 crc 0xd6214cac sha1 d51d277e9b5d0233d1c6bdfec40c32587f84b31a )
rom ( name 831jaa03.19a size 524288 crc 0xa07aeb72 sha1 4d957c15d1b989e955249c34b0aa5679fb3e4fbf )
rom ( name 831jaa04.20a size 524288 crc 0x9277d1d2 sha1 6946845973f0ce15db383032343f6852873698eb )
rom ( name 831jaa05.22a size 524288 crc 0xf3b63033 sha1 c3c6de0d8c749ddf4926040637f03b11c2a21b99 )
rom ( name 831jaa06.24a size 524288 crc 0x43564e9c sha1 54b792b8aaf22876f9eb806e31b86af4b354bcf6 )
rom ( name 831jaa07.22d size 524288 crc 0x25af75f5 sha1 c150514a3bc6f3f88a5b98ef0db5440e2c5fec2d )
rom ( name 831jaa08.23d size 524288 crc 0x3b1b5629 sha1 95b6bed5c5218a3bfb10996cd9af31bd7e08c1c4 )
rom ( name 831jaa09.25d size 524288 crc 0xae7838d2 sha1 4f8a6793065c6c1eb08161f65b1d6246987bf47e )
rom ( name 831jaa10.27d size 524288 crc 0x85173cb6 sha1 bc4d86bf4654a9a0a58e624f77090854950f3993 )
)
game (
name popn3
description "Pop'n Music 3 [DJMAME 08-07-2003]"
year 1999
manufacturer "Konami"
rom ( name 980jaa01.6a size 524288 crc 0xffd37d2c sha1 2a62ccfdb77a10356dbf08d6daa84faa3ff5d93a )
rom ( name 980jaa02.8a size 524288 crc 0x00b15e1b sha1 7725b244b2964952e52a266aff697a8632830c97 )
rom ( name 980jaa03.19a size 524288 crc 0x3674ba5b sha1 8741a43b099936c5f8add33d487b511c1ee8d21b )
rom ( name 980jaa04.20a size 524288 crc 0x32e8ca33 sha1 5aab1cb334e57667e146516125574f4f14676104 )
rom ( name 980jaa05.22a size 524288 crc 0xd31072e4 sha1 c23c0e21fb22fe82b9a76d28bf2896dfec6bdc9b )
rom ( name 980jaa06.24a size 524288 crc 0xd2bbcf36 sha1 4f44c5d8df5dabf2956bdf33739a97b0645b5a5d )
rom ( name 980jaa07.22d size 524288 crc 0x770732d0 sha1 f4330952d1e54658077e315ebd3cfd35e267219c )
rom ( name 980jaa08.23d size 524288 crc 0x64ba3895 sha1 3e4654c970d6fffe46b4e1097c1a6cda196ec92a )
rom ( name 980jaa09.25d size 524288 crc 0x1cb4d84e sha1 9669585c6a2825aeae6e47dd03458624b4c44721 )
rom ( name 980jaa10.27d size 524288 crc 0x7776b87e sha1 662b7cd7cb4fb8f8bab240ef543bf9a593e23a03 )
disk ( name 980jaa11.chd md5 6e5cc17a6bc75cac0256192cc700215c )
)
game (
name popnstex
description "Pop'n Stage EX [DJMAME 08-07-2003]"
year 1999
manufacturer "Konami"
rom ( name 970jba01.6a size 524288 crc 0x8fa0c957 sha1 12d1d6f15e19955c663ebdfcb16d5f6d209c0f76 )
rom ( name 970jba02.8a size 524288 crc 0x7adb00a0 sha1 70a86897ab6cbc3f34be51f7f078644de697e331 )
rom ( name 970jba03.19a size 524288 crc 0xe5d15d3c sha1 bdbd3c59e3377e071b199eea6cfb2ad84d37e971 )
rom ( name 970jba04.20a size 524288 crc 0x687f9beb sha1 6baac0aa2db3af9e34469b1719ccff3643fd85f7 )
rom ( name 970jba05.22a size 524288 crc 0x3bedc09c sha1 d0806bb54a3e620a987d61c6a5f04a2e1fc613a8 )
rom ( name 970jba06.24a size 524288 crc 0x1673a771 sha1 2768434f1c94543f69d40165e68d325ae5d553cd )
rom ( name 970jba07.22d size 524288 crc 0x6fd06bdb sha1 1dc621923e0871d2d5171753f5ddb97786ab12bd )
rom ( name 970jba08.23d size 524288 crc 0x28256891 sha1 2069f52d596acbf355f205bb8d69cefc4cce3542 )
rom ( name 970jba09.25d size 524288 crc 0x5d2bda52 sha1 d03c135ac04437b54e4d267ae168fe7ebb9e5b65 )
rom ( name 970jba10.27d size 524288 crc 0xedc4a245 sha1 30bbd7bf0299a064119c535abb9be69d725aa130 )
disk ( name 970jba11.chd md5 1616905838fdb2b521d53499c6c2a7a4 )
)
game (
name "puzloop2"
description "Puzz Loop 2 [sound only] [M1 v0.7.2]"
year "2001"
manufacturer "Mitchell"
rom ( name "pl2.s5" size 4194304 crc 43c5ff97 )
)
game (
name "raidendx"
description "Raiden DX [sound only] [M1 v0.7.2]"
year "1994"
manufacturer "Seibu Kaihatsu"
rom ( name dx-5.bin size 65536 crc 0x8c46857a md5 b9eb64c2121be006a4f58128a6c268a4 sha1 8b269cb20adf960ba4eb594d8add7739dbc9a837 )
)
game (
name "rushhero"
description "Rushing Heroes [sound only] [M1 v0.7.2]"
year "1997"
manufacturer "Konami"
rom ( name 605a06.9m size 131072 crc 0x9ca03dce md5 916ea18a9c3d6003c00d2e72c2e04757 sha1 008106e864d8390d7ae8645a2fe06d0eaaa746e0 )
rom ( name 605a07.7m size 131072 crc 0x3116a8b0 md5 e6de6f5e9147ce5b968764ada1fd34ba sha1 f0899d7027464d9aad45ffa6a464288a51a80dc1 )
rom ( name 605a23.7r size 4194304 crc 0x992c4751 md5 2888bcb6eeda141c41c86054e6db0eb1 sha1 18ecfc21138f9dc62f0658750808bbef649510f7 )
)
game (
name "scudrace"
description "Scud Race [sound only] [M1 v0.7.2]"
year "1996"
manufacturer "Sega"
rom ( name "epr19612.2" size 131072 crc 13978fd4 )
rom ( name "mp19603.57" size 2097152 crc b1b1765f )
rom ( name "mp19604.58" size 2097152 crc 6ac85b49 )
rom ( name "mp19605.59" size 2097152 crc bec891eb )
rom ( name "mp19606.60" size 2097152 crc adad46b2 )
)
game (
name "sfchamp"
description "Super Football Champ [sound only] [M1 v0.7.2]"
year "1996"
manufacturer "Taito"
rom ( name e18-01.15 size 2097152 crc 0xdbd1408c md5 58d6559780ecc033dc71a765054eb1f5 sha1 ef81064f2f95e5ae25eb1f10d1e78f27f9e294f5 )
rom ( name e18-09.22 size 131072 crc 0xbb5a5319 md5 bacad16dbed046e34cd62e7a4ce63512 sha1 0bb700cafc157d3af663cc9bebb8167487ff2852 )
)
game (
name "stcc"
description "Sega Touring Car Championship [sound only] [M1 v0.7.2]"
year "1996"
manufacturer "Sega"
rom ( name "sega-tc.u32" size 2097152 crc 643059fa )
rom ( name "sega-tc.u34" size 2097152 crc ae798313 )
)
game (
name lastrsrt
description "Last Resort [sound only] [Hoot]"
year 1992
manufacturer "SNK"
rom ( name n046001a.1f8 size 524288 crc 0x0722da38 md5 d2a6b5a0ab580b2e86d36cc1f168867b sha1 66a9b463d5277908b3a01c03de82b3de9118f2cb )
rom ( name n046001a.1fc size 524288 crc 0x670ce3ec md5 463fceb184c774dc37bac50dc338fe21 sha1 9004aa85d4a9b0ecf9cf9357b073ed55a98fdb02 )
rom ( name n046001b.1f8 size 524288 crc 0x2e39462b md5 c65ad0b3fa6bad8a3ad74639f77c4b31 sha1 b0a9b1a3377bf0369f3020192505c46ca52927d6 )
rom ( name n046001b.1fc size 524288 crc 0x7944754f md5 a1738cd090a4dea0c0687a5cb1d76b4c sha1 d42a46c5127c6c62041ebffb0007af8a24abd360 )
)
game (
name spmonaco
description "Super Monaco Gp [sound only] [Hoot]"
year 1989
manufacturer "Sega"
rom ( name epr12436.bin size 65536 crc 0x16ec5f0a md5 21f47e64f22dc8445bbc2db6c36fc8f9 sha1 307b7388b5c36fd4bc2a61f7941db44858e03c5c )
rom ( name epr12437.bin size 131072 crc 0xa1c7e712 md5 8518b8cf65ece64c367bbba09f47ad3b sha1 fa7fa8c39690ae5dab8b28af5aeed5ffae2cd6de )
rom ( name epr12438.bin size 131072 crc 0x6573d46b md5 7bd05a490afc0d0a859ba9ae97fffbfd sha1 c4a4a0ea35250eff28a5bfd5e9cd372f52fd1308 )
rom ( name epr12439.bin size 131072 crc 0x13bf6de5 md5 34d527b465c27a6c1f801a3e2f8fb526 sha1 92228a05ec33d606491a1da98c4989f69cddbb49 )
)
game (
name wrunsuzu
description "Winning Run Suzuka GP (Uininguran GP) [sound only] [Hoot]"
year 1989
manufacturer "Namco"
rom ( name wrt-snd0.bin size 131072 crc 0xde04b794 md5 3293c0b7c029b6a49c5bc32ff4f8a1b2 sha1 191f4d79ac2375d7060f3d83ec753185e92f28ea )
rom ( name wrt-voi1.bin size 524288 crc 0x7dcccb31 md5 f3b0d763eef197c1004be3ca32ea6833 sha1 4441b37691434b13eae5dee2d04dc12a56b04d2a )
rom ( name wrt-voi3.bin size 524288 crc 0xa198141c md5 cd863e4c258e219d8b5e69064ab8e362 sha1 b4ca352e6aedd9d7a7e5e39e840f1d3a7145900e )
)
game (
name skytargt
description "Sky Target [sound only] [Nebula Jukebox v2.5]"
year 1995
manufacturer "Sega"
rom ( name ep18408.30 size 524288 crc 0x6deb9657 md5 8c3cd35e61722d25067dfe32fabed26a sha1 30e1894432a0765c64b93dd5ca7ca17ef58ac6c0 )
rom ( name mp18421.37 size 2097152 crc 0x00522390 md5 4a1a5c94a8a6d0b81f02a76cb3460739 sha1 5dbbf2ba008adad36929fcecb7c2c1e5ffd12618 )
rom ( name mp18422.36 size 2097152 crc 0xb4f3cea6 md5 1bee68cccc18ec8a281eba782d39f7ae sha1 49669be09e10dfae7fddce0fc4e415466cb29566 )
rom ( name mp18423.32 size 2097152 crc 0xc356d765 md5 c19e9fef787087c44347cca46768721c sha1 ae69c9d4e333579d826178d2863156dc784aedef )
rom ( name mp18424.31 size 2097152 crc 0x590a4338 md5 b5346e9b6c8da6bc7e5b5f625d05991a sha1 826f167d7a4f5d30466b2f75f0123187c29c2d69 )
)
game (
name ki2_l11
description "Killer Instinct 2 (ROMs L1.1) [U64emu 3.05]"
year 1996
manufacturer "Nintendo/Rareware/Midway"
rom ( name ki2-l11.u98 size 524288 crc 0x0cb8de1e md5 6b4899050567a6dc193dd29ad8a963f5 sha1 fe447f4b1d29b524f57c5ba1890652ef6afff88a )
)
game (
name ki_l15d
description "Killer Instinct (ROM L1.5d) [U64emu 3.05]"
year 1994
manufacturer "Nintendo/Rareware/Midway"
rom ( name u98-l15d size 524288 crc 0x7b65ca3d md5 6a63e4bbdef8ea9f0d26f7244341ca08 sha1 607394d4ba1713f38c2cb5159303cace9cde991e )
)
game (
name anteater
description "Anteater [YAAME v0.3]"
year 1982
manufacturer "[Stern] (Tago license)"
rom ( name ra6-5f2 size 2048 crc 0x1e2824b1 md5 a9cac2cad1c5b4e67c743568e6cc807e sha1 9527937db618505181f4d5a22bc532977a767232 )
rom ( name ra6-5h2 size 2048 crc 0x784319b3 md5 0b0b1cb67098bbb68c6325a938ddbe68 sha1 0c3612a428d0906b07b35782cc0f84fda13aab73 )
)
game (
name "bace"
description "Balloon Ace (PacMan HW) [ESMame 0.69u3]"
year "2003"
manufacturer "D.Widel"
rom ( name "5e" size 4096 crc 6da99c7b )
rom ( name "5f" size 4096 crc b81cdc64 )
rom ( name "boot1" size 4096 crc 8b60ff7c )
rom ( name "boot2" size 4096 crc 25d8361a )
rom ( name "boot3" size 4096 crc fc38d994 )
rom ( name "boot4" size 4096 crc 5853f341 )
rom ( name "boot5" size 4096 crc f154670a )
rom ( name "boot6" size 4096 crc f154670a )
)
game (
name "dderby"
description "Death Derby (PacMan HW) [ESMame 0.69u3]"
year "2003"
manufacturer "D.Widel"
rom ( name "5e" size 4096 crc 7e2c0a53 )
rom ( name "5f" size 4096 crc cb2dd072 )
rom ( name "boot1" size 4096 crc 6f373bd4 )
rom ( name "boot2" size 4096 crc 2fbf16bf )
rom ( name "boot3" size 4096 crc 6e16cd16 )
rom ( name "boot4" size 4096 crc f7e09874 )
rom ( name "boot5" size 4096 crc f154670a )
rom ( name "boot6" size 4096 crc f154670a )
)
game (
name "mineswp"
description "Mine Sweeper (Dottori Kun hardware) [ESMame 0.69u3]"
year "1998"
manufacturer "J-Rom"
rom ( name "14479a.mpr" size 16384 crc 1cece483 )
)
game (
name "vantris"
description "Vantris (Vanguard hardware) [ESMame 0.69u3]"
year "1998"
manufacturer "N.Kehrer"
rom ( name "sk4_ic13.bin" size 4096 crc 1176fdb0 )
rom ( name "sk5_ic50.bin" size 2048 crc bdd86279 )
)
game (
name "airco22b"
description "Air Combat 22 [MAME 0.70u4]"
year "1995"
manufacturer "Namco"
rom ( name "acs1ccrl.3d" size 2097152 crc 07088ba1 )
rom ( name "acs1cg0.8d" size 2097152 crc 1f31343e )
rom ( name "acs1cg1.10d" size 2097152 crc ccd5481d )
rom ( name "acs1cg2.12d" size 2097152 crc 14e5d0d2 )
rom ( name "acs1cg3.13d" size 2097152 crc 1a7bcc16 )
rom ( name "acs1cg4.14d" size 2097152 crc 1920b7fb )
rom ( name "acs1cg5.16d" size 2097152 crc 3dd109b7 )
rom ( name "acs1cg6.18d" size 2097152 crc ec71c8a3 )
rom ( name "acs1cg7.19d" size 2097152 crc 82271757 )
rom ( name "acs1data.8k" size 524288 crc 33824bc9 )
rom ( name "acs1scg0.12l" size 2097152 crc e5235404 )
rom ( name "acs1scg1.10l" size 2097152 crc 828e91e7 )
rom ( name "acs1verb.1" size 1048576 crc 062c4f61 )
rom ( name "acs1verb.2" size 1048576 crc 8ae69711 )
rom ( name "acs1verb.3" size 1048576 crc 71738e67 )
rom ( name "acs1verb.4" size 1048576 crc 3b193add )
rom ( name "acs1wav0.1" size 4194304 crc 52fb9762 )
rom ( name "acs1wav1.2" size 4194304 crc b568dca2 )
rom ( name "asc1ccrh.1d" size 524288 crc 62936af6 )
rom ( name "asc1ptl0.18k" size 524288 crc bd5896c7 )
rom ( name "asc1ptl1.16k" size 524288 crc e583b975 )
rom ( name "asc1ptl2.15k" size 524288 crc 802d737a )
rom ( name "asc1ptl3.14k" size 524288 crc fe556ecb )
rom ( name "asc1ptm0.18j" size 524288 crc 949b6c58 )
rom ( name "asc1ptm1.16j" size 524288 crc 8b2b99d9 )
rom ( name "asc1ptm2.15j" size 524288 crc f1515080 )
rom ( name "asc1ptm3.14j" size 524288 crc e364f4aa )
rom ( name "asc1ptu0.18f" size 524288 crc 746b3084 )
rom ( name "asc1ptu1.16f" size 524288 crc b44f1d3b )
rom ( name "asc1ptu2.15f" size 524288 crc fdd2d778 )
rom ( name "asc1ptu3.14f" size 524288 crc 38b425d4 )
)
game (
name "alpinerd"
description "Alpine Racer Ver. D [MAME 0.70u4]"
year "1995"
manufacturer "Namco"
rom ( name "ar1datab.8k" size 524288 crc c26306f8 )
rom ( name "ar1wavea.2l" size 2097152 crc dbf64562 )
)
game (
name "cybrcomm"
description "Cyber Commando (Japan) [MAME 0.70u4]"
year "1995"
manufacturer "Namco"
rom ( name "cy1data.6r" size 131072 crc 10d0005b )
rom ( name "cy1eeprm.9e" size 8192 crc 4e1d294b )
rom ( name "cy1prgll.4d" size 524288 crc b3eab156 )
rom ( name "cy1prglm.2d" size 524288 crc 884a5b0e )
rom ( name "cy1prgum.8d" size 524288 crc c9c4a921 )
rom ( name "cy1prguu.6d" size 524288 crc 5f22975b )
rom ( name "cy1wav0.10r" size 1048576 crc c6f366a2 )
rom ( name "cy1wav1.10p" size 1048576 crc f30b5e37 )
rom ( name "cy1wav2.10n" size 1048576 crc b98c1ca6 )
rom ( name "cy1wav3.10l" size 1048576 crc 43dbac19 )
rom ( name "cyc1ccrh.2c" size 524288 crc 8c4090b8 )
rom ( name "cyc1ccrl.1c" size 1048576 crc 1a0dc5f0 )
rom ( name "cyc1cg0.1a" size 2097152 crc e839b9bd )
rom ( name "cyc1cg1.2a" size 2097152 crc 7d13993f )
rom ( name "cyc1cg2.3a" size 2097152 crc 7c464566 )
rom ( name "cyc1cg3.5a" size 2097152 crc 2222e16f )
rom ( name "cyc1ptl0.5b" size 524288 crc d91de03d )
rom ( name "cyc1ptl1.4b" size 524288 crc e5b98021 )
rom ( name "cyc1ptl2.3b" size 524288 crc 7ba786c6 )
rom ( name "cyc1ptm0.5c" size 524288 crc d454b5c6 )
rom ( name "cyc1ptm1.4c" size 524288 crc 74fdf8cc )
rom ( name "cyc1ptm2.3c" size 524288 crc b9c99a45 )
rom ( name "cyc1ptu0.5d" size 524288 crc 4d40897f )
rom ( name "cyc1ptu1.4d" size 524288 crc 3bdaeeeb )
rom ( name "cyc1ptu2.3d" size 524288 crc a0e73674 )
)
game (
name "cybrcycc"
description "Cyber Cycles Ver. C (CB2Ver.C) [MAME 0.70u4]"
year "1995"
manufacturer "Namco"
rom ( name "cb1ccrh.1d" size 524288 crc 86124b93 )
rom ( name "cb1ccrl.3d" size 2097152 crc 2f171c48 )
rom ( name "cb1cg0.12b" size 2097152 crc 762a47a0 )
rom ( name "cb1cg1.10d" size 2097152 crc df92c3e6 )
rom ( name "cb1cg2.12d" size 2097152 crc 07bc508e )
rom ( name "cb1cg3.13d" size 2097152 crc 50c86dea )
rom ( name "cb1cg4.14d" size 2097152 crc e93b8894 )
rom ( name "cb1cg5.16d" size 2097152 crc 9ee610a1 )
rom ( name "cb1cg6.18a" size 2097152 crc ddc3b5cc )
rom ( name "cb1datab.8k" size 524288 crc e2404221 )
rom ( name "cb1ptrl0.18k" size 524288 crc f1393a03 )
rom ( name "cb1ptrl1.16k" size 524288 crc 2ad51de7 )
rom ( name "cb1ptrl2.15k" size 524288 crc 78f77c0d )
rom ( name "cb1ptrl3.14k" size 524288 crc 804bfb4a )
rom ( name "cb1ptrm0.18j" size 524288 crc f4eece49 )
rom ( name "cb1ptrm1.16j" size 524288 crc 5f3cbd7d )
rom ( name "cb1ptrm2.15j" size 524288 crc 02c7e4af )
rom ( name "cb1ptrm3.14j" size 524288 crc ace3123b )
rom ( name "cb1ptru0.18f" size 524288 crc 58d35341 )
rom ( name "cb1ptru1.16f" size 524288 crc f4d005b0 )
rom ( name "cb1ptru2.15f" size 524288 crc 68ffcd50 )
rom ( name "cb1ptru3.14f" size 524288 crc d89c1c2b )
rom ( name "cb1scg0.12f" size 2097152 crc 7aaca90d )
rom ( name "cb1wavea.2l" size 4194304 crc b79a624d )
rom ( name "cb1waveb.1l" size 2097152 crc 33bf08f6 )
rom ( name "cb2ver-c.1" size 1048576 crc a8e07a14 )
rom ( name "cb2ver-c.2" size 1048576 crc 054c504f )
rom ( name "cb2ver-c.3" size 1048576 crc 47e6306c )
rom ( name "cb2ver-c.4" size 1048576 crc 398426e4 )
)
game (
name "raveracw"
description "Rave Racer (World) [MAME 0.70u4]"
year "1995"
manufacturer "Namco"
rom ( name "rv1data.6r" size 524288 crc d358ec20 )
rom ( name "rv1wav0.10r" size 1048576 crc 5aef8143 )
rom ( name "rv1wav1.10p" size 1048576 crc 9ed9e6b3 )
rom ( name "rv1wav2.10n" size 1048576 crc 5af9dc83 )
rom ( name "rv1wav3.10l" size 1048576 crc ffb9ad75 )
)
game (
name "ridger2j"
description "Ridge Racer 2 (Japan) [MAME 0.70u4]"
year "1994"
manufacturer "Namco"
rom ( name "rrs1data.bin" size 524288 crc b7063aa8 )
rom ( name "rrs1wav0.bin" size 1048576 crc 99d11a2d )
rom ( name "rrs1wav1.bin" size 1048576 crc ad28444a )
rom ( name "rrs1wav2.bin" size 1048576 crc 6f0d4619 )
rom ( name "rrs1wav3.bin" size 1048576 crc 106e761f )
)
game (
name "ridgeraj"
description "Ridge Racer (Japan [MAME 0.70u4])"
year "1993"
manufacturer "Namco"
rom ( name "rr1-data.bin" size 524288 crc 18f5f748 )
rom ( name "rr1-wav.0" size 1048576 crc a8e85bde )
rom ( name "rr1-wav.1" size 1048576 crc 35f47c8e )
rom ( name "rr1-wav.2" size 1048576 crc 3244cb59 )
rom ( name "rr1-wav.3" size 1048576 crc c4cda1a7 )
)
game (
name "timecris"
description "Time Crisis [MAME 0.70u4]"
year "1995"
manufacturer "Namco"
rom ( name "ts2ver-a.1" size 2097152 crc d57eb74b )
rom ( name "ts2ver-a.2" size 2097152 crc 671588af )
)
game (
name "victlapw"
description "Ace Driver: Victory Lap (World) [MAME 0.70u4]"
year "1996"
manufacturer "Namco"
rom ( name "adv1data.6r" size 524288 crc 10eecdb4 )
rom ( name "adv1wav0.10r" size 1048576 crc f07b2d9d )
rom ( name "adv1wav1.10p" size 1048576 crc 737f3c7a )
rom ( name "adv1wav2.10n" size 1048576 crc c1a5ca5e )
rom ( name "adv1wav3.10l" size 1048576 crc fc6b8004 )
)
game (
name 8ballact
description "Eight Ball Action (DK conversion) [MAME 0.72u1]"
year 1984
manufacturer "Seatongrove Ltd (Magic Eletronics USA licence)"
rom ( name 8b-dk.3n size 2048 crc 0x44830867 sha1 29d34792b9193edcdac427367c360d6f01e1e094 )
rom ( name 8b.2e size 256 crc 0xc7379a12 sha1 e128e7d7c71ec61b934651c29648d0d2fc69e306 )
rom ( name 8b.2f size 256 crc 0x116612b4 sha1 9a7c5329f211b13d5a757fdac761d7096d78b65a )
rom ( name 8b.2n size 256 crc 0x30586988 sha1 a9c246fd01cb3ff371ad33b55d5b2fe4898c4d1b )
)
game (
name 8ballat2
description "Eight Ball Action (DKJr conversion) [MAME 0.72u1]"
year 1984
manufacturer "Seatongrove Ltd (Magic Eletronics USA licence)"
rom ( name 8b-jr.3h size 4096 crc 0x7f5c19fa sha1 9cde134137ee8e34bb745a72e67981c581561428 )
rom ( name 8b-jr.3n size 4096 crc 0x9ec0edac sha1 ffa1ae2236995527d72917c45be337f642134cf8 )
rom ( name 8b-jr.3p size 4096 crc 0x2978a88b sha1 15c21a3b3fb879996c13ce56791828e170c771d1 )
rom ( name 8b-jr.5b size 8192 crc 0x579cd634 sha1 93d81539459f7198d8cbf05b3e66a40466aee2d9 )
rom ( name 8b-jr.5c size 8192 crc 0x9bccbe93 sha1 dec4e1d41e1df36359f205bf090c4290311e4141 )
)
game (
name asurabld
description "Asura Blade (Japan) [MAME 0.72u1]"
year 1998
manufacturer "Fuuki"
rom ( name bg1012.u22 size 4194304 crc 0xd717a0a1 sha1 007df309dc0650ca07e077b983a2b05730349d0b )
rom ( name bg1113.u23 size 4194304 crc 0x94338267 sha1 7848bc57cb0eac216100a508763451eb57a0a082 )
rom ( name bg2022.u25 size 4194304 crc 0xee312cd3 sha1 2ef9d51928d80375daf8e6b204bb66a8b9cbaee7 )
rom ( name bg2123.u24 size 4194304 crc 0x4acfc469 sha1 a98d06b967ebb3fa3b4c8aa3d7a05063ec981fb2 )
rom ( name map.u5 size 2097152 crc 0xe681155e sha1 458845b9c86df72685d92d0d4052aacc2fa7d1bd )
rom ( name pcm.u6 size 4194304 crc 0xac72225a sha1 8d16399ed34ac5bd69dbf43b2de2b0db9ac1c610 )
rom ( name pgm0.u4 size 524288 crc 0x68615497 sha1 de93751f151f195a863dc6fe83b6e7ed8f99430a )
rom ( name pgm1.u3 size 524288 crc 0x35104452 sha1 03cfd81429f8a945d5419c9750925bfa997d0607 )
rom ( name pgm2.u2 size 524288 crc 0x16b656ca sha1 5ffb551ce7dec462d3896f0fed693454496894bc )
rom ( name pgm3.u1 size 524288 crc 0x053e9758 sha1 c2754d3f0c607c81c8fa33b667b576eb0474fd0b )
rom ( name sp23.u14 size 4194304 crc 0x7df492eb sha1 30b88a3cd025ffc8c28fef06e0784755be37ef8e )
rom ( name sp45.u15 size 4194304 crc 0x1890f42a sha1 22254fe38fd83f4602a25e1ccba32df16edaf3f9 )
rom ( name sp67.u16 size 4194304 crc 0xa48f1ef0 sha1 bf8787f293793291a503af662d3738c007654726 )
rom ( name sp89.u17 size 4194304 crc 0x6b024362 sha1 8be5cc3c7306d28b75acd970bb3be6d3c9825367 )
rom ( name spab.u18 size 4194304 crc 0x803d2d8c sha1 25df30689e576a0620656c721d92bcc3fbd84844 )
rom ( name spcd.u19 size 4194304 crc 0x42e5c26e sha1 b68875d353bdc5d49113bbac02fd83508bce66a5 )
rom ( name srom.u7 size 524288 crc 0xbb1deb89 sha1 b1c70abddc0b9a88beb69a592376ff69a7e091eb )
)
game (
name gaia
description "Gaia Crusaders [MAME 0.72u1]"
year 1999
manufacturer "Noise Factory"
rom ( name bg1.989 size 4194304 crc 0x013a693d sha1 2cc5be6f47c13febed942e1c3167946efedc5f9b )
rom ( name bg2.995 size 4194304 crc 0x783cc62f sha1 8b6e4212688b53be5ecc29ff2d41fd43e7d0a420 )
rom ( name bg3.998 size 4194304 crc 0xbcd61d1c sha1 660a3b02a8c39e1117b00d0ad06f73221fef4ce8 )
rom ( name obj1.736 size 4194304 crc 0xf4f84e5d sha1 8f445dd7a5c8a996939c211e5aec5742121a6e7e )
rom ( name obj2.738 size 4194304 crc 0x15c2a9ce sha1 631eb2968395be86ef2403733e7d4ec769a013b9 )
rom ( name prg1.127 size 524288 crc 0x47b904b2 sha1 58b9b55f59cf00f70b690a0371096e86f4d723c2 )
rom ( name prg2.128 size 524288 crc 0x469b7794 sha1 502f855c51005a866900b19c3a0a170d9ea02392 )
rom ( name snd1.447 size 4194304 crc 0x92770a52 sha1 81f6835e1b45eb0f367e4586fdda92466f02edb9 )
rom ( name snd2.454 size 4194304 crc 0x329ae1cf sha1 0c5e5074a5d8f4fb85ab4893bc953f192dcb301a )
rom ( name snd3.455 size 4194304 crc 0x4048d64e sha1 5e4ec6d37e70484e2fcd04188385e79ef0b53026 )
)
game (
name strtheat
description "Street Heat - Cardinal Amusements [MAME 0.72u1]"
year 1985
manufacturer "Epos Corporation"
rom ( name 2716.3h size 2048 crc 0x4cd17174 sha1 5ed9b5275b0779d1ca05d6e62d3ad8a682ebde37 )
rom ( name 2716.3n size 2048 crc 0x29e57678 sha1 cbbb980c44c7f5c45d5f0b85209658f53b7ba4a7 )
rom ( name 2716.3p size 2048 crc 0x31171146 sha1 e26b22e73b528810b566b2b9f6d81e2d7856523d )
rom ( name 2716.7c size 2048 crc 0xa8238e9c sha1 947bbe48ce1c705ef974e37b138929f1c846ed79 )
rom ( name 2716.7d size 2048 crc 0x71202138 sha1 b4edc77ed2844ef46aee4a492282e4785bdb7224 )
rom ( name 2716.7e size 2048 crc 0xdc7785ac sha1 4ccb3f9f938fd1d9bd20f1601a16a2780c84588b )
rom ( name 2716.7f size 2048 crc 0xede71d86 sha1 0bce1b1d4180173537685a08055ce44b9dedc76a )
rom ( name 2764.u2 size 8192 crc 0x8d3e82c3 sha1 ec26fb1c6015721da1f61eca76a4b3390d8dcc76 )
rom ( name 2764.u3 size 8192 crc 0xf0759e76 sha1 e086f02d1861269194c4cd2ada71696b48ed1a1d )
rom ( name 82s129.2e size 256 crc 0x1311ba28 sha1 d9b5bc07c8943d83592833e8b1c2ff57e4accb55 )
rom ( name 82s129.2f size 256 crc 0x18d90d4f sha1 b956fd652dcc5eb50eaec8729762d19cfd475bc7 )
rom ( name 82s129.2n size 256 crc 0xa515d59b sha1 930616c4bcd819c2a4432a6619a8c6da74f3e8c5 )
)
game (
name wc90t
description "Tecmo World Cup '90 (trackball) [MAME 0.72u1]"
year 1989
manufacturer "Tecmo"
rom ( name wc90a-1.bin size 32768 crc 0xb6f51a68 sha1 - )
rom ( name wc90a-2.bin size 65536 crc 0xc50f2a98 sha1 - )
rom ( name wc90a-3.bin size 65536 crc 0x8c7a9542 sha1 - )
)

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
File Name,Internal Name,Description,Game Name,Game Description,Type,Rom Name,Disk Name,Size,CRC,MD5,SHA1,SHA256,Nodump
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Rom,file.bin,,12345,0,d41d8cd98f00b204e9800998ecf8427e,da39a3ee5e6b4b0d3255bfef95601890afd80709,ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad,No
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Disk,,file.chd,,,,da39a3ee5e6b4b0d3255bfef95601890afd80709,,No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No

View File

@@ -0,0 +1,3 @@
File Name,Internal Name,Description,Game Name,Game Description,Type,Rom Name,Disk Name,Size,CRC,MD5,SHA1,SHA256,SHA384,SHA512,SpamSum,Nodump
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Rom,file.bin,,12345,0,d41d8cd98f00b204e9800998ecf8427e,da39a3ee5e6b4b0d3255bfef95601890afd80709,ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad,cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7,ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f,QXX,No
Original DatFile Name.xml,Original DatFile Name,Original DatFile,Game,A cool game,Disk,,file.chd,,,,da39a3ee5e6b4b0d3255bfef95601890afd80709,,,,,No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 SHA384 SHA512 SpamSum Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f QXX No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,100 @@
d660d7258e04b3de83248f488c58e47c *Barney Bear Goes to School (USA) (Track 01).bin
ddcca5e6b1d05442505a935f1444c82d *Barney Bear Goes to School (USA) (Track 02).bin
52fb246984bd4bab51571454d9501904 *Barney Bear Goes to School (USA) (Track 03).bin
48e8a5b4813a942f1251aa9d013af83c *Barney Bear Goes to School (USA) (Track 04).bin
b8b04a48f1dae3ff2994a7a15143f924 *Barney Bear Goes to School (USA) (Track 05).bin
7dfdb3a6718188c6230eef6c003b0a66 *Barney Bear Goes to School (USA) (Track 06).bin
43dbf6509b694673c625c550d1583ab6 *Barney Bear Goes to School (USA) (Track 07).bin
870b67155c66d389833f7bdb4c226b78 *Barney Bear Goes to School (USA) (Track 08).bin
2146f79948f95394cd7bc8a92d8ffed3 *Barney Bear Goes to School (USA) (Track 09).bin
a95d931d28de5639e51d3ad02cdcaa0d *Barney Bear Goes to School (USA) (Track 10).bin
710b0c91d19db1e23eb0dff53c7e5b52 *Barney Bear Goes to School (USA) (Track 11).bin
92ce9aa1f3f1b6ed9be3dd601c2ff51d *Barney Bear Goes to School (USA) (Track 12).bin
83746c04b76586218074c2098d97e4ec *Barney Bear Goes to School (USA) (Track 13).bin
ced4ec11d8c1be2e1148803f19cd1f42 *Barney Bear Goes to School (USA) (Track 14).bin
09060e33785a50292eba201b0762de43 *Barney Bear Goes to School (USA) (Track 15).bin
5018feddca5aa792e78a3ab0faecfcce *Barney Bear Goes to School (USA) (Track 16).bin
fabea432e2ec97f7920388877d3b2c96 *Barney Bear Goes to School (USA) (Track 17).bin
04e1ca138b7682022d44815771f7d610 *Barney Bear Goes to School (USA) (Track 18).bin
3724b24f0f3db4e6dc5bf3719fd96159 *Barney Bear Goes to School (USA) (Track 19).bin
712529d5c03be26bc61018e2a6d62231 *Barney Bear Goes to School (USA) (Track 20).bin
416183742a8ec7c08595695a1d36f49e *Barney Bear Goes to School (USA) (Track 21).bin
3fdee94ba5e0d7e4a474f2a016d38d16 *Barney Bear Goes to School (USA) (Track 22).bin
3213aad3d108d80d1d530eca243877f3 *Barney Bear Goes to School (USA) (Track 23).bin
dc646e0e23fcc0112dda6dee7fc94048 *Barney Bear Goes to School (USA) (Track 24).bin
d49d329b62d952e14bd5629b103cc5b1 *Barney Bear Goes to School (USA) (Track 25).bin
a4c765c36e20e37993aedfaeed3b9dea *Barney Bear Goes to School (USA) (Track 26).bin
81a413c1524ad483650317036b3d9687 *Barney Bear Goes to School (USA) (Track 27).bin
f0291a33a245df7c38c0cea1ee4df9cc *Barney Bear Goes to School (USA) (Track 28).bin
0db6fe455ecc9b1fbeb55a85358d58a9 *Barney Bear Goes to School (USA) (Track 29).bin
f57d4d0cca4e1a1dbbc6d34dac28aee3 *Barney Bear Goes to School (USA) (Track 30).bin
18b018bb693b22530fa1e087a79bf2da *Barney Bear Goes to School (USA) (Track 31).bin
1bccdfc3c0f7bc0bf63b75c703d2849d *Barney Bear Goes to School (USA) (Track 32).bin
d13b18473053b6f93a931acdef2ac9ff *Barney Bear Goes to School (USA) (Track 33).bin
f106712d1ebb1c07fa2408efff0cbe53 *Barney Bear Goes to School (USA) (Track 34).bin
13aea576e33afc7923d0ab977d2470b5 *Barney Bear Goes to School (USA) (Track 35).bin
c1392dbb1c8e820f80c447ebb50ca10f *Barney Bear Goes to School (USA) (Track 36).bin
83923ea897d5284536257c85e9d468c4 *Barney Bear Goes to School (USA) (Track 37).bin
416d19d1a4471c06a6fab9cafd270541 *Barney Bear Goes to School (USA) (Track 38).bin
de980b883d382e7159848f2264d11905 *Barney Bear Goes to School (USA) (Track 39).bin
7f01aabfae9776414f4029798921f3f1 *Barney Bear Goes to School (USA) (Track 40).bin
43cfd6bb7f9f4e5add2b1119f78d4569 *Barney Bear Goes to School (USA) (Track 41).bin
59ca076d2fdc665f701e7467a3d2b180 *Barney Bear Goes to School (USA) (Track 42).bin
88ec47b4e372a1bfc9eb5b63a3ef2353 *Barney Bear Goes to School (USA) (Track 43).bin
a14c7b0d159dd11f65fb82c8c7299938 *Barney Bear Goes to School (USA) (Track 44).bin
9381f3af88a86a453167a6079a17c1aa *Barney Bear Goes to School (USA) (Track 45).bin
7d607ede892bb6f012467cfc07fab285 *Barney Bear Goes to School (USA) (Track 46).bin
f737f25818598092c3c483732ac2ca8f *Barney Bear Goes to School (USA) (Track 47).bin
3454bf5eac48968e920d78e083be5aab *Barney Bear Goes to School (USA) (Track 48).bin
f20cf6292d3dd47d77efa1102e43e530 *Barney Bear Goes to School (USA) (Track 49).bin
c5616328576e7b94cc54f3a39d035caf *Barney Bear Goes to School (USA) (Track 50).bin
4c8a8712674e4c8a98f00a5dee8053d8 *Barney Bear Goes to School (USA) (Track 51).bin
861e523b14ae06b1acfd0ae37654eedb *Barney Bear Goes to School (USA) (Track 52).bin
c0023a8fe8cf1683277c8fd61552eec5 *Barney Bear Goes to School (USA) (Track 53).bin
4551ef330c5a5e8ebabd3dc7367d0997 *Barney Bear Goes to School (USA) (Track 54).bin
6a1b8cab8ffc7f8ba0e398d06d6d6a3c *Barney Bear Goes to School (USA) (Track 55).bin
5da6fcdc3f19652cecd96bd45211f0b3 *Barney Bear Goes to School (USA) (Track 56).bin
5d56d449922dac2fb60888bcc8b65e84 *Barney Bear Goes to School (USA) (Track 57).bin
1cb6a16bfb96ddbff6981df77597ea5a *Barney Bear Goes to School (USA) (Track 58).bin
fee45f55442782a1d97c06c4caea3b94 *Barney Bear Goes to School (USA) (Track 59).bin
1012b41b1077cb5ab2d687049c229b1a *Barney Bear Goes to School (USA) (Track 60).bin
6ac86f3c17074d42a9f098d8ff957e25 *Barney Bear Goes to School (USA) (Track 61).bin
0aadb961334bec4cace74b17c40d24aa *Barney Bear Goes to School (USA) (Track 62).bin
aa3616d2742a44dd8cbeada00657607d *Barney Bear Goes to School (USA) (Track 63).bin
3c9a490073e319936bae51981132c955 *Barney Bear Goes to School (USA) (Track 64).bin
7e698663d98466bd2000a882bbe5b8cb *Barney Bear Goes to School (USA) (Track 65).bin
18f8511fe266d9538ade3216ea1661c5 *Barney Bear Goes to School (USA) (Track 66).bin
b9f7c67c8581229fad348445f50c6371 *Barney Bear Goes to School (USA) (Track 67).bin
70b9006b57fa5ee625259694f8cb47a0 *Barney Bear Goes to School (USA) (Track 68).bin
01f3ec3d63c80e274887699198e75606 *Barney Bear Goes to School (USA) (Track 69).bin
7752af3ad4a3b8cea680e4b7e1bfeb4d *Barney Bear Goes to School (USA) (Track 70).bin
bdef9ebec16c0cea78d2f4fecd48e688 *Barney Bear Goes to School (USA) (Track 71).bin
c8f3323905f892a046c979916fae514b *Barney Bear Goes to School (USA) (Track 72).bin
0a30fcd90e2839119e93ed7136a07097 *Barney Bear Goes to School (USA) (Track 73).bin
3a3edb3674bd30f7a61dc806b7562bf9 *Barney Bear Goes to School (USA) (Track 74).bin
9014a8d1a3356b01dccd95fa460bc785 *Barney Bear Goes to School (USA) (Track 75).bin
d0e58f8d6a734b20777f244edc1a45c7 *Barney Bear Goes to School (USA) (Track 76).bin
e4619f010e4af80f7a8770fb8b223cf7 *Barney Bear Goes to School (USA) (Track 77).bin
1215b28b90fec2fc1fddc6fbe3a63e87 *Barney Bear Goes to School (USA) (Track 78).bin
1c855c082e2185d7566681d63db741dc *Barney Bear Goes to School (USA) (Track 79).bin
fddaab4f57e73c36dc1af52fc66bd58d *Barney Bear Goes to School (USA) (Track 80).bin
14dfd6e66c6754ea546b23c3e56d0a75 *Barney Bear Goes to School (USA) (Track 81).bin
44b0379a2278f84f7e7015ed8bf79c54 *Barney Bear Goes to School (USA) (Track 82).bin
8089a558e9808640820fe624a32b3f8a *Barney Bear Goes to School (USA) (Track 83).bin
e862789c432b7e851d552e75e922716c *Barney Bear Goes to School (USA) (Track 84).bin
f7f27620f89bd7c7e19fd2d5a94e82c1 *Barney Bear Goes to School (USA) (Track 85).bin
2829f242300b36fc233c8eff72000c4a *Barney Bear Goes to School (USA) (Track 86).bin
342875d61f152a7da7d9143ebd0d767c *Barney Bear Goes to School (USA) (Track 87).bin
351f42129a3ca0212923c924ab028399 *Barney Bear Goes to School (USA) (Track 88).bin
f0ab189b06da969784133ca81a51454e *Barney Bear Goes to School (USA) (Track 89).bin
e6ee817f6712a8150fa793baa1333796 *Barney Bear Goes to School (USA) (Track 90).bin
2a74a5b6b3a1225a4ff9b4b824fe5fe0 *Barney Bear Goes to School (USA) (Track 91).bin
c2c9ef8ce916c8bfd9cfad5da61c8bb3 *Barney Bear Goes to School (USA) (Track 92).bin
1dab7e75dcee645759988fba5c5017cc *Barney Bear Goes to School (USA) (Track 93).bin
3a1abd4966bdc662bc9d9d51f6338942 *Barney Bear Goes to School (USA) (Track 94).bin
bd8e3e04f133b41b84fd5b84c13997b6 *Barney Bear Goes to School (USA) (Track 95).bin
fef61422100cc1a282250efb79a85292 *Barney Bear Goes to School (USA) (Track 96).bin
d087996d7f1e9856ddf833a697d2ea0b *Barney Bear Goes to School (USA) (Track 97).bin
781edf7bd5b6be3ae60a8f0198120f15 *Barney Bear Goes to School (USA) (Track 98).bin
bc206671819ac2b5b13e906fd27b89fd *Barney Bear Goes to School (USA) (Track 99).bin
37d1e3bf7439af1ac2d986150f525fc6 *Barney Bear Goes to School (USA).cue

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,911 @@
[CREDITS]
Author=ElSemi
Version=Jukebox v2.9
Comment=Autogenerated by Jukebox
[DAT]
Version=2.00
[EMULATOR]
refname=Jukebox
version=Jukebox v2.9
[GAMES]
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬ep20225.15¬4ABC6B59¬131072¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬ep20226.16¬43E05B3A¬131072¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬ep20223.13¬61B1BE98¬131072¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬ep20224.14¬EB2D7DBF¬131072¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20233.11¬3E079A3B¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20234.12¬58BDE826¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20231.9¬B3393E93¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20232.10¬DA4A2E11¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20229.7¬CDEC7BF4¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20230.8¬A166FA87¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20227.5¬1277686E¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20228.6¬49CB5568¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20236.29¬8DE9A3C2¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20235.30¬78FA11EF¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20249.31¬DC24F13D¬131072¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20250.32¬91B735D3¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20251.33¬703A947B¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20252.34¬8F48F375¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20253.35¬CA6AA17C¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20244.17¬9D2A8660¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20240.21¬51615908¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20243.18¬48671F7C¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20239.22¬6CD8D8A5¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20242.19¬E7F86AC7¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20238.23¬0A480C7C¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20241.20¬51974B98¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20237.24¬89B5D8B6¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20247.27¬00B0417D¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20245.25¬36490A08¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20248.28¬0ACE6BEF¬2097152¬¬¬
¬bel¬Behind the Enemy Lines¬bel¬Behind the Enemy Lines¬mp20246.26¬250D6CA1¬2097152¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173ea.b01¬7785AC8A¬262144¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173ea.b02¬9B45F122¬262144¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬t5¬CD724026¬131072¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬t6¬7DD54D6F¬131072¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173.a07¬4CDAEE71¬262144¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a08.b6¬DCDDED95¬2097152¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a09.a6¬C93697C4¬2097152¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a06.t10¬6541A34F¬1048576¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a05.t8¬D14333B4¬1048576¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a18.a10¬4CF85439¬2097152¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a12.b10¬0FC2AD24¬2097152¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a11.a8¬B0D747C4¬2097152¬¬¬
¬bucky¬Bucky O'Hare¬bucky¬Bucky O'Hare¬173a10.b8¬42FB0A0C¬2097152¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151b01¬FB2FA298¬262144¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151b02¬3D9F4D59¬262144¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a03¬C896D3EA¬262144¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a04¬3B24706A¬262144¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a07¬CDE247FC¬262144¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a08¬962251D7¬2097152¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a06¬38DBCAC1¬1048576¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a05¬BC616249¬1048576¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a13¬4771F525¬2097152¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a12¬4978555F¬2097152¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a11¬E7F49225¬2097152¬¬¬
¬moo¬C.O.W. Boys of Moo Mesa¬moo¬C.O.W. Boys of Moo Mesa¬151a10¬376C64F1¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16722a.epr¬48B94318¬131072¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16723a.epr¬8AF8B32D¬131072¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16528.mpr¬9CE591F6¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16529.mpr¬F7095EAF¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16808.mpr¬44F1F5A0¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16809.mpr¬37A2DD12¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16724a.epr¬469F10FD¬524288¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16725a.epr¬BA0DF8DB¬524288¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16724a.epr¬469F10FD¬524288¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16725a.epr¬BA0DF8DB¬524288¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16720.epr¬8E73CFFD¬131072¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16721.epr¬1BB3B7B7¬131072¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16491.mpr¬89920903¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16492.mpr¬459E701B¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16493.mpr¬9990DB15¬2097152¬¬¬
¬daytona¬Daytona USA¬daytona¬Daytona USA¬16494.mpr¬600E1D6C¬2097152¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬e19310aa.12¬06486F7A¬524288¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬e19311aa.13¬1BE62912¬524288¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19318.11¬AB431BFE¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19319.12¬C5CB694D¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19316.9¬2D2D1B1A¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19317.10¬96B17BCF¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19314.7¬A8D963FB¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19315.8¬90AE5682¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19312.5¬1DCEDB10¬2097152¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19313.6¬8C63055E¬2097152¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬ep19328.30¬400BDBFB¬524288¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19329.31¬8FD2708A¬2097152¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19330.32¬0C69787D¬2097152¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19331.33¬C18EA0B8¬2097152¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19332.34¬2877F96F¬2097152¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19322.17¬D0E6ECF0¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19325.21¬7CBE432D¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19323.18¬453D3F4A¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19326.22¬B976DA02¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19324.19¬D972201F¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19327.23¬6A75634C¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19321.27¬9C49E845¬4194304¬¬¬
¬doa¬Dead or Alive¬doa¬Dead or Alive¬mp19320.25¬190C017F¬4194304¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬epr16976.12¬D036DFF0¬131072¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬epr16977.13¬E91194BD¬131072¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬epr16970.14¬4EA12D1F¬131072¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬epr16971.15¬D630B220¬131072¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬mpr16974.10¬2AB491C5¬2097152¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬mpr16975.11¬E24FE7D3¬2097152¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬mpr16972.8¬23E53748¬2097152¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬mpr16973.9¬77D6F509¬2097152¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬epr16978.6¬38B3E574¬524288¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬epr16979.7¬C314EB8B¬524288¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬epr16985.7¬8C4D9056¬131072¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬mpr16986.32¬559612F9¬2097152¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬mpr16988.4¬BC705875¬2097152¬¬¬
¬desert¬Desert Tank¬desert¬Desert Tank¬mpr16989.5¬1B616B31¬2097152¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬ep19833a.15¬D99ED1B2¬524288¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬ep19834a.16¬24192BB1¬524288¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬ep19831a.13¬0527EA40¬524288¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬ep19832a.14¬2F380A40¬524288¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19841.11¬989309AF¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19842.12¬EEC54070¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19839.9¬D5A74CF4¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19840.10¬45704E95¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19837.7¬C02187D9¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19838.8¬546B61CD¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19835.5¬A3B0A37C¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19836.6¬D70A32AA¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬ep19849.31¬B0D5BFF0¬524288¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19880.32¬E1FD27BF¬2097152¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19850.33¬DC644077¬2097152¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19851.34¬CFDA4EFD¬2097152¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19853.35¬CFC64857¬2097152¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19843.17¬019BC583¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19845.21¬2D23E73A¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19844.18¬150198D6¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19846.22¬FE53CD17¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19848.27¬4C0526B7¬4194304¬¬¬
¬dynabb¬Dynamite Baseball¬dynabb¬Dynamite Baseball¬mp19847.25¬FE55EDBD¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬ep20930.12¬B8FC8FF7¬524288¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬ep20931.13¬89D13F88¬524288¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬ep20932.14¬618A68BF¬524288¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬ep20933.15¬13ABE49C¬524288¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20797.10¬87BAB1E4¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20798.11¬40DD752B¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20795.8¬0EF85E12¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20796.9¬870139CB¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20793.6¬42EA08F8¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20794.7¬8E5CD1DB¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20791.4¬4883D0DF¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20792.5¬47BECFA2¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬ep20811.30¬A154B83E¬524288¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20812.31¬695B6088¬2097152¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20813.32¬1908679C¬2097152¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20814.36¬E8EBC74C¬2097152¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20815.37¬1B5AAAE4¬2097152¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20799.16¬424571BF¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20803.20¬61A8AD52¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20800.17¬3C2EE808¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20804.21¬03B35CB8¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20801.18¬C6914173¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20805.22¬F6605EDE¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20802.19¬D11B5267¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20806.23¬0C942073¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20809.25¬3B7B4622¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20807.24¬1241E0F2¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20810.27¬838A10A7¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynamcop¬Dynamite Cop¬mp20808.26¬706BD495¬4194304¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18606d.15¬7334DE7D¬131072¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18607d.16¬700D2ADE¬131072¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18604d.13¬704FDFCF¬131072¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18605d.14¬7DDDF81F¬131072¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18614.11¬0EBC899F¬4194304¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18615.12¬018ABDB7¬4194304¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18612.9¬1F174CD1¬4194304¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18613.10¬F057CDF2¬4194304¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18610d.7¬A1871703¬524288¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18611d.8¬39A75FEE¬524288¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18608d.5¬5BC11881¬524288¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18609d.6¬CD426035¬524288¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18622.29¬C74D99E3¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18623.30¬746AE931¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Ep18628.31¬AA7DD79F¬524288¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18629.32¬5D0006CC¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18630.33¬9D405615¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18631.34¬9DAE5B45¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18632.35¬39DA6805¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18616.17¬15A239BE¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18619.21¬9D5E8E2B¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18617.18¬A62CAB7D¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18620.22¬4D432AFD¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18618.19¬ADAB589F¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18621.23¬F5EEAA95¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18626.27¬9DF0A961¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18624.25¬1D74433E¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18627.28¬946175A0¬2097152¬¬¬
¬fvipers¬Fighting Vipers¬fvipers¬Fighting Vipers¬Mp18625.26¬182FD572¬2097152¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬ep18988a.15¬F63F1AD2¬524288¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬ep18989a.16¬C1C84D65¬524288¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18974.11¬E29ECAFF¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18975.12¬D8187582¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18976.9¬C95C15EB¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18977.10¬DB8F5B6F¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18986.29¬04820F7B¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18987.30¬2419367F¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬ep18990.31¬02B1B0D1¬524288¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18978.32¬0F78B3E3¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18979.34¬F13EA36F¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18980.17¬22345534¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18981.21¬2544A33D¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18982.18¬D0A92B2A¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18983.22¬1B4AF982¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18985.27¬AD6166E3¬4194304¬¬¬
¬gunblade¬GunBlade NY¬gunblade¬GunBlade NY¬mp18984.25¬756F6F37¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19696.15¬03DA5623¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19697.16¬A9722D87¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19694.13¬E85CA1A3¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19695.14¬CD52B461¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19704.11¬AA80DBB0¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19705.12¬F906843B¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19702.9¬FC8AA3B7¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19703.10¬208D993D¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19700.7¬0558CFD3¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19701.8¬224A8929¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19698.5¬E7A7B6EA¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19699.6¬8160B3D9¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19707.29¬384FD133¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19706.30¬1277531C¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬ep19720.31¬B367D21D¬524288¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19721.32¬F5D8FA9A¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19722.34¬A56FA539¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19715.17¬3FF7DDA7¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19711.21¬080D13F1¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19714.18¬3E55AB49¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19710.22¬80DF1036¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19713.19¬4D092CD3¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19709.23¬D08937BF¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19712.20¬41577943¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19708.24¬5CB790F2¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19718.27¬A9DE5924¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19716.25¬45C7DCCE¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19719.28¬838F8343¬4194304¬¬¬
¬hotd¬House of the Dead¬hotd¬House of the Dead¬mp19717.26¬393E440B¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬ep18254a.15¬AD0F1FC5¬524288¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬ep18255a.16¬784DAAB8¬524288¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18237.11¬37E4255A¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18238.12¬BF837BAC¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18239.9¬9A2DB86E¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18240.10¬AB46A35F¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬ep18389.7¬D22EA019¬524288¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬ep18390.8¬38E796E5¬524288¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬ep18249.29¬A399F023¬524288¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬ep18250.30¬7479AD52¬524288¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬ep18391.31¬79579B72¬262144¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18241.32¬3A380AE1¬2097152¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18242.33¬1CC3DEAE¬2097152¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18243.34¬A00A0053¬2097152¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18244.35¬BFA75BEB¬2097152¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18233.17¬48A024D3¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18234.21¬1178BFC8¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18235.18¬E7D70D59¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18236.22¬6CA29E0E¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18232.27¬F962347D¬4194304¬¬¬
¬indy500¬Indianapolis 500¬indy500¬Indianapolis 500¬mp18231.25¬673D5338¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬ep19046a.15¬75BE7B7A¬524288¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬ep19047a.16¬1F5541E2¬524288¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19050.11¬E6AF2B61¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19051.12¬14B88961¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19048.9¬02180215¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19049.10¬DB7EECD6¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19056.31¬22A22918¬524288¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19057.32¬64809438¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19058.34¬E237C11C¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19052.17¬D7F27216¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19053.21¬1F328465¬4194304¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19055.27¬85A57D49¬2097152¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbrxa¬Last Bronx (Japan, Rev A)¬mp19054.25¬05366277¬2097152¬¬¬
¬lostwrld¬Lost World¬lostwrld¬Lost World¬19940.21¬B06FFE5F¬524288¬¬¬
¬lostwrld¬Lost World¬lostwrld¬Lost World¬mp19934.22¬C7D8E194¬4194304¬¬¬
¬lostwrld¬Lost World¬lostwrld¬Lost World¬mp19935.24¬91C1B618¬4194304¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18822.bin¬C7B3E45A¬131072¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18823.bin¬6B0C1DFB¬131072¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18824.bin¬352BB817¬131072¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18825.bin¬F88B036C¬131072¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18751.bin¬773AD43D¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18752.bin¬4DA3719E¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18749.bin¬C3FE0EEA¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18750.bin¬40B55494¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18747.bin¬F2ECAC6F¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18748.bin¬7815D634¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18862.bin¬9ADC3A30¬524288¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18863.bin¬603742E9¬524288¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18761.bin¬4E39EC05¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18762.bin¬4AB165D8¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬ep18826.30¬ED9FE4C1¬262144¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬mp18827.31¬58D78CA1¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬mp18764.32¬0DC6A860¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬mp18765.36¬CA4A803C¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬mp18766.37¬10F3C932¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18753.bin¬33DDAA0D¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18756.bin¬E1678C59¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18754.bin¬09AABDE5¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18757.bin¬25FC92E9¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18755.bin¬FD1FA53C¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18758.bin¬1B5473D0¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18759.bin¬89D7927D¬2097152¬¬¬
¬manxtt¬ManxTT¬manxtt¬ManxTT¬18760.bin¬4E3A4A89¬2097152¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬ep21281.pr0¬293EAD5D¬524288¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬ep21282.pr1¬ED0E7B9E¬524288¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21262.da0¬AA71353E¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21263.da1¬D55D4509¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬ep21276.sd0¬8F415BC3¬524288¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21277.sd1¬BFBA0FF6¬2097152¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21278.sd2¬27E18E08¬2097152¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21279.sd3¬3A8DCF68¬2097152¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21280.sd4¬AA548124¬2097152¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21264.tp0¬6B35204D¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21268.tp1¬16CE2147¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21265.tp2¬F061E639¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21269.tp3¬8C06255E¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21266.tp4¬F9C32021¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21270.tp5¬B61F81C3¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21267.tp6¬C42CC938¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21271.tp7¬A5325C75¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21272.tx0¬DD605C21¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21274.tx1¬F045E3D1¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21273.tx2¬722EC8A2¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkids¬Pilot Kids¬mp21275.tx3¬C4870B7C¬4194304¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬epr19692.21¬A94F5521¬524288¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬epr19612.2¬13978FD4¬131072¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬mpr19670.22¬BD31CC06¬4194304¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬mpr19671.24¬8E8526AB¬4194304¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬mpr19603.57¬B1B1765F¬2097152¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬mpr19604.58¬6AC85B49¬2097152¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬mpr19605.59¬BEC891EB¬2097152¬¬¬
¬scudrace¬Scud Race¬scudrace¬Scud Race¬mpr19606.60¬ADAD46B2¬2097152¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬epr20636.bin¬7139EBF8¬524288¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬epr20641.bin¬C9B82035¬131072¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬mpr20614.bin¬A3930E4A¬4194304¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬mpr20615.bin¬62E8A94A¬4194304¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬mpr20637.bin¬D66E8A02¬4194304¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬mpr20638.bin¬D1513382¬4194304¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬mpr20639.bin¬F6603B7B¬4194304¬¬¬
¬srally2¬Sega Rally 2¬srally2¬Sega Rally 2¬mpr20640.bin¬9EEA07B7¬4194304¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17888.bin¬00000000¬524288¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17889.bin¬00000000¬524288¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17746.bin¬00000000¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17747.bin¬00000000¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17744.bin¬00000000¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17745.bin¬00000000¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17884.bin¬00000000¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17885.bin¬00000000¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17754.bin¬81A84F67¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬17755.bin¬2A6E7DA4¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬ep17890.30¬5BAC3FA1¬262144¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬mp17856.31¬7725F111¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬mp17857.32¬1616E649¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬mp17886.33¬54A72923¬2097152¬¬¬
¬srallyc¬Sega Rally Championship¬srallyc¬Sega Rally Championship¬mp17887.34¬38C31FDD¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19272a.15¬20CEDD05¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19273a.16¬1B0AB4D6¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19257.11¬AC28EE24¬4194304¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19258.12¬F5BA7D78¬4194304¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19270.9¬7BD1D04E¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19271.10¬D2D74F85¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19255.29¬D78BF030¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19256.30¬CB2B2D9E¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19274.31¬2DCC08AE¬131072¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19275.2s¬EE809D3F¬131072¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep18643a.7¬B5E048EC¬131072¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19259.32¬4D55DBFC¬4194304¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19261.34¬B88878FF¬4194304¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19262.57s¬922AED7A¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19263.58s¬A256F4CD¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19264.59s¬B6C51D0F¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19265.60s¬7D98700A¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19251.17¬E06FF7BA¬4194304¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19252.21¬68509993¬4194304¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19266.18¬41464EE2¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19267.22¬780F994D¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19254.27¬1EC49C02¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬mp19253.25¬41BA79FB¬2097152¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19269.28¬01881121¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stcc¬Sega Touring Car Championship¬ep19268.26¬BC4E081C¬524288¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Ep18406.12¬FDE9C00A¬524288¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Ep18407.13¬35F8B529¬524288¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18415.10¬D7A1BBD7¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18416.11¬B77C9243¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18417.8¬A0D03F63¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18418.9¬C7A6F97F¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Ep18404.6¬F1407EC4¬524288¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Ep18405.7¬00B40F9E¬524288¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18420.28¬92B87817¬2097152¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18419.29¬74542D87¬2097152¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Ep18408.30¬6DEB9657¬524288¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18424.31¬590A4338¬2097152¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18423.32¬C356D765¬2097152¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18422.36¬B4F3CEA6¬2097152¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18421.37¬00522390¬2097152¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18413.16¬1C4D416C¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18409.20¬666037EF¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18414.17¬858885BA¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18410.21¬B821A695¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18411.24¬9C2DC40C¬4194304¬¬¬
¬skytargt¬Sky Target¬skytargt¬Sky Target¬Mp18412.25¬4DB52F8B¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬ep19001.15¬9B088511¬524288¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬ep19002.16¬46F510DA¬524288¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19007.11¬8B8FF751¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19008.12¬A94654F5¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19005.9¬98CD1127¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19006.10¬E79F0A26¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19015.29¬C74D99E3¬2097152¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19016.30¬746AE931¬2097152¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬ep19003.7¬63BAE5C5¬524288¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬ep19004.8¬C10C9F39¬524288¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬ep19021.31¬0B9F7583¬524288¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19022.32¬4381869B¬2097152¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19023.33¬07C67F88¬2097152¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19024.34¬15FF76D3¬2097152¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19025.35¬6AD8FB70¬2097152¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19009.17¬FD410350¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19012.21¬9BB7B5B6¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19010.18¬6FD94187¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19013.22¬9E232FE5¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19019.27¬59121896¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19017.25¬7B298379¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19020.28¬9540DBA0¬4194304¬¬¬
¬schamp¬Sonic Championship¬schamp¬Sonic Championship¬mp19018.26¬3B7E7A12¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬ep19155.15¬593952FD¬524288¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬ep19156.16¬A91FC4EE¬524288¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19146.11¬D66B5B0F¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19147.12¬D5558F48¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19148.9¬A14C86DB¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19149.10¬94EF5849¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬ep18643a.7¬B5E048EC¬131072¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬ep19157.31¬8FFEA0CF¬524288¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19154.32¬7CD9E679¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19150.17¬E0AD870E¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19151.21¬E2A1B125¬4194304¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19153.27¬136ADFD0¬2097152¬¬¬
¬sgt24h¬Super GT 24h¬sgt24h¬Super GT 24h¬mp19152.25¬363769A2¬2097152¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬ep19755a.15¬B80633B9¬524288¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬ep19756a.16¬472046A2¬524288¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19735.11¬8E509266¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19736.12¬094E0A0D¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19737.9¬281A7DDE¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19738.10¬F688327E¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19743.29¬D41A41BF¬2097152¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19744.30¬84F203BF¬2097152¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19759.31¬573530F2¬524288¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19760.2s¬2E41CA15¬131072¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19745.32¬7082A0AF¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19746.34¬657B5977¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19747.18s¬6E895AAA¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19748.20s¬FCD74DE3¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19749.22s¬842CA1EB¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19750.24s¬CD95D0BF¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19741.17¬111A6E29¬2097152¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19742.21¬28510AFF¬2097152¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19740.27¬B20F508B¬4194304¬¬¬
¬topskatr¬Top Skater¬topskatr¬Top Skater¬mp19739.25¬8120CFD8¬4194304¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17166b.12¬A5647C59¬131072¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17167b.13¬F5DDE26A¬131072¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17160a.14¬267F3242¬131072¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17161a.15¬F7126876¬131072¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17164.10¬AC5FC501¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17165.11¬82296D00¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17162.8¬60DDD41E¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17163.9¬8C1F9DC8¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17168a.6¬59091A37¬524288¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17169a.7¬0495808D¬524288¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17170.7¬06A38AE2¬131072¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬ep17171.8¬B5E436F8¬131072¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17172.32¬AB22CAC3¬1048576¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17173.33¬3CB4005C¬1048576¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17174.4¬A50369CC¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17175.5¬9136D43C¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17159.16¬E218727D¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17156.20¬C4F4AABF¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17157.24¬CF31E33D¬2097152¬¬¬
¬vcop¬Virtua Cop¬vcop¬Virtua Cop¬mp17158.25¬1108D1EC¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18524.bin¬1858988B¬524288¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18525.bin¬0C13DF3F¬524288¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18518.bin¬7842951B¬524288¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18519.bin¬31A30EDC¬524288¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18516.bin¬A3928FF0¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18517.bin¬4BD73DA4¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18514.bin¬791283C5¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18515.bin¬6BA1FFEC¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18522.bin¬61D18536¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18523.bin¬61D08DC4¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18520.bin¬1D4EC5E8¬524288¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18521.bin¬B8B3781C¬524288¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬ep18530.30¬AC9C8357¬524288¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬mp18429.31¬F76715B1¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬mp18428.32¬287A2F9A¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬mp18427.33¬E6A49314¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬mp18426.34¬6516D9B5¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18510.bin¬083F5186¬2097152¬¬¬
¬vcop2¬Virtua Cop 2¬vcop2¬Virtua Cop 2¬18513.bin¬777A3633¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17568.b¬5D966BBF¬131072¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17569.b¬0B8C1CCC¬131072¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17562.b¬B778D4EB¬131072¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17563.b¬A05C15F6¬131072¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17560¬D1389864¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17561¬B98D0101¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17558¬4B15F5A6¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17559¬D3264DE6¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17566¬FB41EF98¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17567¬C3396922¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17564¬D8062489¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17565¬0517C6E9¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17574.30¬4D4C3A55¬524288¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17573.31¬E43557FE¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17572.32¬4FEBECC8¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17571.33¬D22DC8CA¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17570.34¬BCCD324B¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17554¬27896D82¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17548¬C95FACC2¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17555¬4DF2810B¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17549¬E0BCE0E6¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17556¬41A47616¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17550¬C36FF3F5¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17552¬E91E7427¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17553¬5DA1C5D3¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17546¬042A194B¬2097152¬¬¬
¬vf2¬Virtua Fighter 2¬vf2¬Virtua Fighter 2¬mp17547¬BE940431¬2097152¬¬¬
¬vf3¬Virtua Fighter 3¬vf3¬Virtua Fighter 3¬ep19231.21¬B416FE96¬524288¬¬¬
¬vf3¬Virtua Fighter 3¬vf3¬Virtua Fighter 3¬mpr19209.22¬3715E38C¬4194304¬¬¬
¬vf3¬Virtua Fighter 3¬vf3¬Virtua Fighter 3¬mpr19210.24¬C03D6502¬4194304¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬ep18068.15¬74A47795¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬ep18069.16¬F6C3FCBF¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬ep18066.13¬E774229E¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬ep18067.14¬7DFD950C¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18055.11¬5ABA9FC0¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18056.12¬017F0C55¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18053.9¬46C770C8¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18054.10¬437AF66E¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬ep18070.7¬F52E4DB5¬524288¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬ep18071.8¬1BE63A7D¬524288¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬ep18072.31¬73EABB58¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18063.32¬B74D7C8A¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18064.33¬783B9910¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18065.34¬046B55FE¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18057.17¬890D8806¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18059.21¬C5CDF534¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18058.18¬D4CBDF7C¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18060.22¬93D5C95F¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18062.27¬126E7DE3¬2097152¬¬¬
¬vstriker¬Virtua Striker¬vstriker¬Virtua Striker¬mp18061.25¬C37F1C67¬2097152¬¬¬
¬vs2¬Virtua Striker 2¬vs2¬Virtua Striker 2¬epr19807.bin¬9641CBAF¬524288¬¬¬
¬vs2¬Virtua Striker 2¬vs2¬Virtua Striker 2¬mpr19785.bin¬E7D190E3¬4194304¬¬¬
¬vs2¬Virtua Striker 2¬vs2¬Virtua Striker 2¬mpr19786.bin¬B08D889B¬4194304¬¬¬
¬vs298¬Virtua Striker 2 '98¬vs298¬Virtua Striker 2 '98¬epr20921.bin¬30F032A7¬524288¬¬¬
¬vs298¬Virtua Striker 2 '98¬vs298¬Virtua Striker 2 '98¬mpr20903.bin¬E343E131¬4194304¬¬¬
¬vs298¬Virtua Striker 2 '98¬vs298¬Virtua Striker 2 '98¬mpr20904.bin¬21A91B84¬4194304¬¬¬
¬vs299¬Virtua Striker 2 '99¬vs299¬Virtua Striker 2 '99¬epr21539.bin¬A1D3E00E¬524288¬¬¬
¬vs299¬Virtua Striker 2 '99¬vs299¬Virtua Striker 2 '99¬mpr21513.bin¬CCA1CC00¬4194304¬¬¬
¬vs299¬Virtua Striker 2 '99¬vs299¬Virtua Striker 2 '99¬mpr21514.bin¬6CEDD292¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬ep18664b.15¬27D0172C¬524288¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬ep18665b.16¬2F0142EE¬524288¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬ep18666.13¬66EDB432¬524288¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬ep18667.14¬B593D31F¬524288¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18648.11¬2EDBE489¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18649.12¬E68C5AA6¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18650.9¬89A855B9¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18651.10¬F4C23107¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18662.29¬A33D3335¬2097152¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18663.30¬EA74A641¬2097152¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬ep18643a.7¬B5E048EC¬131072¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬ep18670.31¬3E715F76¬524288¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18652.32¬037EEE53¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18653.34¬9EC3E7BF¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18654.17¬6A0CAF29¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18655.21¬A4293E78¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18656.18¬B4F51E76¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18657.22¬A9BE4674¬4194304¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18660.27¬E53663E5¬2097152¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18658.25¬3D0FCD01¬2097152¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18661.28¬52B50410¬2097152¬¬¬
¬von¬Virtual ON¬von¬Virtual ON¬mp18659.26¬27AA8AE2¬2097152¬¬¬
¬von2¬Virtual ON 2¬von2¬Virtual ON 2¬SROM0-4M.U21¬FA084DE5¬524288¬¬¬
¬von2¬Virtual ON 2¬von2¬Virtual ON 2¬SROM1-32.U22¬977EB6A4¬4194304¬¬¬
¬von2¬Virtual ON 2¬von2¬Virtual ON 2¬SROM3-32.U24¬0EFC0CA8¬4194304¬¬¬
¬von2¬Virtual ON 2¬von2¬Virtual ON 2¬SROM2.U23¬89F21281¬2097152¬¬¬
¬von2¬Virtual ON 2¬von2¬Virtual ON 2¬SROM4.U25¬B7C1BEBF¬2097152¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬ep20439.15¬10125381¬524288¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬ep20440.16¬CE872747¬524288¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20296.11¬072D8A5E¬4194304¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20297.12¬BA6A825B¬4194304¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20294.9¬A0BD1474¬4194304¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20295.10¬C548CCED¬4194304¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬ep20302.31¬44FF50D2¬524288¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20303.32¬C040973F¬2097152¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20304.33¬6DECFE83¬2097152¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20298.17¬8AB782FC¬4194304¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20299.21¬90E20CDB¬4194304¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20301.27¬52010FB2¬2097152¬¬¬
¬zerogun¬Zero Gunner¬zerogun¬Zero Gunner¬mp20300.25¬6F042792¬2097152¬¬¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬q5¬DCAECCA0¬262144¬¬¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬q6¬E3C856A6¬262144¬¬¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬t5¬CD724026¬131072¬bucky¬t5¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬t6¬7DD54D6F¬131072¬bucky¬t6¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173.a07¬4CDAEE71¬262144¬bucky¬173.a07¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a08.b6¬DCDDED95¬2097152¬bucky¬173a08.b6¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a09.a6¬C93697C4¬2097152¬bucky¬173a09.a6¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a06.t10¬6541A34F¬1048576¬bucky¬173a06.t10¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a05.t8¬D14333B4¬1048576¬bucky¬173a05.t8¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a18.a10¬4CF85439¬2097152¬bucky¬173a18.a10¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a12.b10¬0FC2AD24¬2097152¬bucky¬173a12.b10¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a11.a8¬B0D747C4¬2097152¬bucky¬173a11.a8¬
¬bucky¬Bucky O'Hare¬buckyua¬Bucky O'Hare (US)¬173a10.b8¬42FB0A0C¬2097152¬bucky¬173a10.b8¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬turbo_a¬AEC6857A¬131072¬¬¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬turbo_b¬CB657EDC¬131072¬¬¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16528.mpr¬9CE591F6¬2097152¬daytona¬16528.mpr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16529.mpr¬F7095EAF¬2097152¬daytona¬16529.mpr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16808.mpr¬44F1F5A0¬2097152¬daytona¬16808.mpr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16809.mpr¬37A2DD12¬2097152¬daytona¬16809.mpr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16724a.epr¬469F10FD¬524288¬daytona¬16724a.epr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16725a.epr¬BA0DF8DB¬524288¬daytona¬16725a.epr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16724a.epr¬469F10FD¬524288¬daytona¬16724a.epr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16725a.epr¬BA0DF8DB¬524288¬daytona¬16725a.epr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16720.epr¬8E73CFFD¬131072¬daytona¬16720.epr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16721.epr¬1BB3B7B7¬131072¬daytona¬16721.epr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16491.mpr¬89920903¬2097152¬daytona¬16491.mpr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16492.mpr¬459E701B¬2097152¬daytona¬16492.mpr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16493.mpr¬9990DB15¬2097152¬daytona¬16493.mpr¬
¬daytona¬Daytona USA¬daytntus¬Daytona USA Turbo¬16494.mpr¬600E1D6C¬2097152¬daytona¬16494.mpr¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬maxx.12¬604EF2D9¬131072¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬maxx.13¬7D319970¬131072¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬maxx.14¬2DEBFCE0¬131072¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16528.mpr¬9CE591F6¬2097152¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16529.mpr¬F7095EAF¬2097152¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16808.mpr¬44F1F5A0¬2097152¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16809.mpr¬37A2DD12¬2097152¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16724a.epr¬469F10FD¬524288¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16725a.epr¬BA0DF8DB¬524288¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16724a.epr¬469F10FD¬524288¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16725a.epr¬BA0DF8DB¬524288¬¬¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16720.epr¬8E73CFFD¬131072¬daytona¬16720.epr¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16721.epr¬1BB3B7B7¬131072¬daytona¬16721.epr¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16491.mpr¬89920903¬2097152¬daytona¬16491.mpr¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16492.mpr¬459E701B¬2097152¬daytona¬16492.mpr¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16493.mpr¬9990DB15¬2097152¬daytona¬16493.mpr¬
¬daytona¬Daytona USA¬daytnmax¬Daytona USA to the Maxx¬16494.mpr¬600E1D6C¬2097152¬daytona¬16494.mpr¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬ep19379b.15¬8A10A944¬524288¬¬¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬ep19380b.16¬766C1EC8¬524288¬¬¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19318.11¬AB431BFE¬4194304¬doa¬mp19318.11¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19319.12¬C5CB694D¬4194304¬doa¬mp19319.12¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19316.9¬2D2D1B1A¬4194304¬doa¬mp19316.9¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19317.10¬96B17BCF¬4194304¬doa¬mp19317.10¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19314.7¬A8D963FB¬4194304¬doa¬mp19314.7¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19315.8¬90AE5682¬4194304¬doa¬mp19315.8¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19312.5¬1DCEDB10¬2097152¬doa¬mp19312.5¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19313.6¬8C63055E¬2097152¬doa¬mp19313.6¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬ep19328.30¬400BDBFB¬524288¬doa¬ep19328.30¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19329.31¬8FD2708A¬2097152¬doa¬mp19329.31¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19330.32¬0C69787D¬2097152¬doa¬mp19330.32¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19331.33¬C18EA0B8¬2097152¬doa¬mp19331.33¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19332.34¬2877F96F¬2097152¬doa¬mp19332.34¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19322.17¬D0E6ECF0¬4194304¬doa¬mp19322.17¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19325.21¬7CBE432D¬4194304¬doa¬mp19325.21¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19323.18¬453D3F4A¬4194304¬doa¬mp19323.18¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19326.22¬B976DA02¬4194304¬doa¬mp19326.22¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19324.19¬D972201F¬4194304¬doa¬mp19324.19¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19327.23¬6A75634C¬4194304¬doa¬mp19327.23¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19321.27¬9C49E845¬4194304¬doa¬mp19321.27¬
¬doa¬Dead or Alive¬doab¬Dead or Alive (Model 2B)¬mp19320.25¬190C017F¬4194304¬doa¬mp19320.25¬
¬dragwld2¬Dragon World 2¬dragwld2¬Dragon World 2¬pgm_bios.rom¬E42B166E¬131072¬pgmbios¬pgm_bios.rom¬
¬dragwld2¬Dragon World 2¬dragwld2¬Dragon World 2¬V-100C.u2¬67467981¬524288¬¬¬
¬dragwld2¬Dragon World 2¬dragwld2¬Dragon World 2¬pgm_m01s.rom¬45AE7159¬2097152¬pgmbios¬pgm_m01s.rom¬
¬dragwld2¬Dragon World 2¬dragwld2¬Dragon World 2¬pgm_t01s.rom¬1A7123A0¬2097152¬pgmbios¬pgm_t01s.rom¬
¬dragwld2¬Dragon World 2¬dragwld2¬Dragon World 2¬pgmt0200.u7¬B0F6534D¬4194304¬¬¬
¬dragwld2¬Dragon World 2¬dragwld2¬Dragon World 2¬pgmb0200.u9¬932D0F13¬4194304¬¬¬
¬dragwld2¬Dragon World 2¬dragwld2¬Dragon World 2¬pgma0200.u5¬13B95069¬4194304¬¬¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬progrom0.15¬29B142F2¬524288¬¬¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬progrom1.16¬C495912E¬524288¬¬¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬ep20932.14¬618A68BF¬524288¬dynamcop¬ep20932.14¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬ep20933.15¬13ABE49C¬524288¬dynamcop¬ep20933.15¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20797.10¬87BAB1E4¬4194304¬dynamcop¬mp20797.10¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20798.11¬40DD752B¬4194304¬dynamcop¬mp20798.11¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20795.8¬0EF85E12¬4194304¬dynamcop¬mp20795.8¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20796.9¬870139CB¬4194304¬dynamcop¬mp20796.9¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20793.6¬42EA08F8¬4194304¬dynamcop¬mp20793.6¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20794.7¬8E5CD1DB¬4194304¬dynamcop¬mp20794.7¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20791.4¬4883D0DF¬4194304¬dynamcop¬mp20791.4¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20792.5¬47BECFA2¬4194304¬dynamcop¬mp20792.5¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬ep20811.30¬A154B83E¬524288¬dynamcop¬ep20811.30¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20812.31¬695B6088¬2097152¬dynamcop¬mp20812.31¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20813.32¬1908679C¬2097152¬dynamcop¬mp20813.32¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20814.36¬E8EBC74C¬2097152¬dynamcop¬mp20814.36¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20815.37¬1B5AAAE4¬2097152¬dynamcop¬mp20815.37¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20799.16¬424571BF¬4194304¬dynamcop¬mp20799.16¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20803.20¬61A8AD52¬4194304¬dynamcop¬mp20803.20¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20800.17¬3C2EE808¬4194304¬dynamcop¬mp20800.17¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20804.21¬03B35CB8¬4194304¬dynamcop¬mp20804.21¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20801.18¬C6914173¬4194304¬dynamcop¬mp20801.18¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20805.22¬F6605EDE¬4194304¬dynamcop¬mp20805.22¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20802.19¬D11B5267¬4194304¬dynamcop¬mp20802.19¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20806.23¬0C942073¬4194304¬dynamcop¬mp20806.23¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20809.25¬3B7B4622¬4194304¬dynamcop¬mp20809.25¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20807.24¬1241E0F2¬4194304¬dynamcop¬mp20807.24¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20810.27¬838A10A7¬4194304¬dynamcop¬mp20810.27¬
¬dynamcop¬Dynamite Cop¬dynmcopb¬Dynamite Cop (Model 2B)¬mp20808.26¬706BD495¬4194304¬dynamcop¬mp20808.26¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬pgm_bios.rom¬E42B166E¬131072¬kov¬pgm_bios.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬p0600.115¬527A2924¬4194304¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬pgm_m01s.rom¬45AE7159¬2097152¬kov¬pgm_m01s.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬m0600.rom¬3ADA4FD6¬4194304¬kov¬m0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬pgm_t01s.rom¬1A7123A0¬2097152¬kov¬pgm_t01s.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬t0600.rom¬4ACC1AD6¬8388608¬kov¬t0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬b0600.rom¬7D3CD059¬8388608¬kov¬b0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬b0601.rom¬A0BB1C2F¬4194304¬kov¬b0601.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬a0600.rom¬D8167834¬8388608¬kov¬a0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬a0601.rom¬FF7A4373¬8388608¬kov¬a0601.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬a0602.rom¬E7A32959¬8388608¬kov¬a0602.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov115¬Knights of Valour (Rev 115)¬a0613.rom¬EC31ABDA¬4194304¬kov¬a0613.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬pgm_bios.rom¬E42B166E¬131072¬pgmbios¬pgm_bios.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬p0600.rom¬C4D19FE6¬4194304¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬pgm_m01s.rom¬45AE7159¬2097152¬pgmbios¬pgm_m01s.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬m0600.rom¬3ADA4FD6¬4194304¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬pgm_t01s.rom¬1A7123A0¬2097152¬pgmbios¬pgm_t01s.rom¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬t0600.rom¬4ACC1AD6¬8388608¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬b0600.rom¬7D3CD059¬8388608¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬b0601.rom¬A0BB1C2F¬4194304¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬a0600.rom¬D8167834¬8388608¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬a0601.rom¬FF7A4373¬8388608¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬a0602.rom¬E7A32959¬8388608¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kov¬Knights of Valour (Rev 117)¬a0613.rom¬EC31ABDA¬4194304¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬pgm_bios.rom¬E42B166E¬131072¬kov¬pgm_bios.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬p0600.119¬E4B0875D¬4194304¬¬¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬pgm_m01s.rom¬45AE7159¬2097152¬kov¬pgm_m01s.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬m0600.rom¬3ADA4FD6¬4194304¬kov¬m0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬pgm_t01s.rom¬1A7123A0¬2097152¬kov¬pgm_t01s.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬t0600.rom¬4ACC1AD6¬8388608¬kov¬t0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬b0600.rom¬7D3CD059¬8388608¬kov¬b0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬b0601.rom¬A0BB1C2F¬4194304¬kov¬b0601.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬a0600.rom¬D8167834¬8388608¬kov¬a0600.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬a0601.rom¬FF7A4373¬8388608¬kov¬a0601.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬a0602.rom¬E7A32959¬8388608¬kov¬a0602.rom¬
¬kov¬Knights of Valour (Rev 117)¬kovplus¬Knights of Valour Plus (Rev 119)¬a0613.rom¬EC31ABDA¬4194304¬kov¬a0613.rom¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬ep19061a.15¬C0AEBAB2¬524288¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬ep19062a.16¬CDF597E8¬524288¬¬¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19050.11¬E6AF2B61¬4194304¬lastbrxa¬mp19050.11¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19051.12¬14B88961¬4194304¬lastbrxa¬mp19051.12¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19048.9¬02180215¬4194304¬lastbrxa¬mp19048.9¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19049.10¬DB7EECD6¬4194304¬lastbrxa¬mp19049.10¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19056.31¬22A22918¬524288¬lastbrxa¬mp19056.31¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19057.32¬64809438¬4194304¬lastbrxa¬mp19057.32¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19058.34¬E237C11C¬4194304¬lastbrxa¬mp19058.34¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19052.17¬D7F27216¬4194304¬lastbrxa¬mp19052.17¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19053.21¬1F328465¬4194304¬lastbrxa¬mp19053.21¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19055.27¬85A57D49¬2097152¬lastbrxa¬mp19055.27¬
¬lastbrxa¬Last Bronx (Japan, Rev A)¬lastbexp¬Last Bronx (Export, Rev A)¬mp19054.25¬05366277¬2097152¬lastbrxa¬mp19054.25¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬pgm_bios.rom¬E42B166E¬131072¬orlegend¬pgm_bios.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬p0101.160¬B24F0C1E¬2097152¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬pgm_m01s.rom¬45AE7159¬2097152¬orlegend¬pgm_m01s.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬m0100.rom¬E5C36C83¬2097152¬orlegend¬m0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬pgm_t01s.rom¬1A7123A0¬2097152¬orlegend¬pgm_t01s.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬t0100.rom¬61425E1E¬4194304¬orlegend¬t0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬b0100.rom¬69D2E48C¬4194304¬orlegend¬b0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬b0101.rom¬0D587BF3¬4194304¬orlegend¬b0101.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬b0102.rom¬43823C1E¬4194304¬orlegend¬b0102.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬a0100.rom¬8B3BD88A¬4194304¬orlegend¬a0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬a0101.rom¬3B9E9644¬4194304¬orlegend¬a0101.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬a0102.rom¬069E2C38¬4194304¬orlegend¬a0102.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬a0103.rom¬4460A3FD¬4194304¬orlegend¬a0103.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬a0104.rom¬5F8ABB56¬4194304¬orlegend¬a0104.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegndc¬Oriental Legend (Rev 112 Chinese)¬a0105.rom¬A17A7147¬4194304¬orlegend¬a0105.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬pgm_bios.rom¬E42B166E¬131072¬orlegend¬pgm_bios.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬p0102.rom¬4D0F6CC5¬2097152¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬pgm_m01s.rom¬45AE7159¬2097152¬orlegend¬pgm_m01s.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬m0100.rom¬E5C36C83¬2097152¬orlegend¬m0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬pgm_t01s.rom¬1A7123A0¬2097152¬orlegend¬pgm_t01s.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬t0100.rom¬61425E1E¬4194304¬orlegend¬t0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬b0100.rom¬69D2E48C¬4194304¬orlegend¬b0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬b0101.rom¬0D587BF3¬4194304¬orlegend¬b0101.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬b0102.rom¬43823C1E¬4194304¬orlegend¬b0102.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬a0100.rom¬8B3BD88A¬4194304¬orlegend¬a0100.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬a0101.rom¬3B9E9644¬4194304¬orlegend¬a0101.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬a0102.rom¬069E2C38¬4194304¬orlegend¬a0102.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬a0103.rom¬4460A3FD¬4194304¬orlegend¬a0103.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬a0104.rom¬5F8ABB56¬4194304¬orlegend¬a0104.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegnde¬Oriental Legend (Rev 112)¬a0105.rom¬A17A7147¬4194304¬orlegend¬a0105.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬pgm_bios.rom¬E42B166E¬131072¬pgmbios¬pgm_bios.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬p0103.rom¬D5E93543¬2097152¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬pgm_m01s.rom¬45AE7159¬2097152¬pgmbios¬pgm_m01s.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬m0100.rom¬E5C36C83¬2097152¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬pgm_t01s.rom¬1A7123A0¬2097152¬pgmbios¬pgm_t01s.rom¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬t0100.rom¬61425E1E¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬b0100.rom¬69D2E48C¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬b0101.rom¬0D587BF3¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬b0102.rom¬43823C1E¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬a0100.rom¬8B3BD88A¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬a0101.rom¬3B9E9644¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬a0102.rom¬069E2C38¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬a0103.rom¬4460A3FD¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬a0104.rom¬5F8ABB56¬4194304¬¬¬
¬orlegend¬Oriental Legend (Rev 126)¬orlegend¬Oriental Legend (Rev 126)¬a0105.rom¬A17A7147¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬ep21285a.15¬BDDE5B41¬524288¬¬¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬ep21286a.16¬C8092E0E¬524288¬¬¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21262.da0¬AA71353E¬4194304¬pltkids¬mp21262.da0¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21263.da1¬D55D4509¬4194304¬pltkids¬mp21263.da1¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬ep21276.sd0¬8F415BC3¬524288¬pltkids¬ep21276.sd0¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21277.sd1¬BFBA0FF6¬2097152¬pltkids¬mp21277.sd1¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21278.sd2¬27E18E08¬2097152¬pltkids¬mp21278.sd2¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21279.sd3¬3A8DCF68¬2097152¬pltkids¬mp21279.sd3¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21280.sd4¬AA548124¬2097152¬pltkids¬mp21280.sd4¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21264.tp0¬6B35204D¬4194304¬pltkids¬mp21264.tp0¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21268.tp1¬16CE2147¬4194304¬pltkids¬mp21268.tp1¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21265.tp2¬F061E639¬4194304¬pltkids¬mp21265.tp2¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21269.tp3¬8C06255E¬4194304¬pltkids¬mp21269.tp3¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21266.tp4¬F9C32021¬4194304¬pltkids¬mp21266.tp4¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21270.tp5¬B61F81C3¬4194304¬pltkids¬mp21270.tp5¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21267.tp6¬C42CC938¬4194304¬pltkids¬mp21267.tp6¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21271.tp7¬A5325C75¬4194304¬pltkids¬mp21271.tp7¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21274.tx1¬F045E3D1¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21272.tx0¬DD605C21¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21275.tx3¬C4870B7C¬4194304¬¬¬
¬pltkids¬Pilot Kids¬pltkidsb¬Pilot Kids (Rev A,Model 2B)¬mp21273.tx2¬722EC8A2¬4194304¬¬¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬ic12.bin¬00000000¬524288¬srallyc¬17888.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬ic13.bin¬00000000¬524288¬srallyc¬17889.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17746.bin¬00000000¬2097152¬srallyc¬17746.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17747.bin¬00000000¬2097152¬srallyc¬17747.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17744.bin¬00000000¬2097152¬srallyc¬17744.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17745.bin¬00000000¬2097152¬srallyc¬17745.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17884.bin¬00000000¬2097152¬srallyc¬17884.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17885.bin¬00000000¬2097152¬srallyc¬17885.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17754.bin¬81A84F67¬2097152¬srallyc¬17754.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬17755.bin¬2A6E7DA4¬2097152¬srallyc¬17755.bin¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬ep17890.30¬5BAC3FA1¬262144¬srallyc¬ep17890.30¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬mp17856.31¬7725F111¬2097152¬srallyc¬mp17856.31¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬mp17857.32¬1616E649¬2097152¬srallyc¬mp17857.32¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬mp17886.33¬54A72923¬2097152¬srallyc¬mp17886.33¬
¬srallyc¬Sega Rally Championship¬srallyp¬Sega Rally Pro Drivin¬mp17887.34¬38C31FDD¬2097152¬srallyc¬mp17887.34¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬SEGA-TC.U15¬EFDFB625¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬SEGA-TC.U16¬61A357D9¬524288¬¬¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19257.11¬AC28EE24¬4194304¬stcc¬mp19257.11¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19258.12¬F5BA7D78¬4194304¬stcc¬mp19258.12¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬ep19270.9¬7BD1D04E¬524288¬stcc¬ep19270.9¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬ep19271.10¬D2D74F85¬524288¬stcc¬ep19271.10¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19255.29¬D78BF030¬2097152¬stcc¬mp19255.29¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19256.30¬CB2B2D9E¬2097152¬stcc¬mp19256.30¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬ep19274.31¬2DCC08AE¬131072¬stcc¬ep19274.31¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19259.32¬4D55DBFC¬4194304¬stcc¬mp19259.32¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19261.34¬B88878FF¬4194304¬stcc¬mp19261.34¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19251.17¬E06FF7BA¬4194304¬stcc¬mp19251.17¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19252.21¬68509993¬4194304¬stcc¬mp19252.21¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬ep19266.18¬41464EE2¬524288¬stcc¬ep19266.18¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬ep19267.22¬780F994D¬524288¬stcc¬ep19267.22¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19254.27¬1EC49C02¬2097152¬stcc¬mp19254.27¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬mp19253.25¬41BA79FB¬2097152¬stcc¬mp19253.25¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬ep19269.28¬01881121¬524288¬stcc¬ep19269.28¬
¬stcc¬Sega Touring Car Championship¬stccb¬Sega Touring Car Championship (Rev B)¬ep19268.26¬BC4E081C¬524288¬stcc¬ep19268.26¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬ep18068a.15¬AFC69B54¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬ep18069a.16¬0243250C¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬ep18066a.13¬E658B33A¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬ep18067a.14¬49E94047¬131072¬¬¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18055.11¬5ABA9FC0¬2097152¬vstriker¬mp18055.11¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18056.12¬017F0C55¬2097152¬vstriker¬mp18056.12¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18053.9¬46C770C8¬2097152¬vstriker¬mp18053.9¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18054.10¬437AF66E¬2097152¬vstriker¬mp18054.10¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬ep18070a.7¬1961E2FC¬524288¬¬¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬ep18071a.8¬B2492DCA¬524288¬¬¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬ep18072.31¬73EABB58¬131072¬vstriker¬ep18072.31¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18063.32¬B74D7C8A¬2097152¬vstriker¬mp18063.32¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18064.33¬783B9910¬2097152¬vstriker¬mp18064.33¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18065.34¬046B55FE¬2097152¬vstriker¬mp18065.34¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18057.17¬890D8806¬2097152¬vstriker¬mp18057.17¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18059.21¬C5CDF534¬2097152¬vstriker¬mp18059.21¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18058.18¬D4CBDF7C¬2097152¬vstriker¬mp18058.18¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18060.22¬93D5C95F¬2097152¬vstriker¬mp18060.22¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18062.27¬126E7DE3¬2097152¬vstriker¬mp18062.27¬
¬vstriker¬Virtua Striker¬vstrikra¬Virtua Striker (Rev A)¬mp18061.25¬C37F1C67¬2097152¬vstriker¬mp18061.25¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬vo-prog0.usa¬6499CC59¬524288¬¬¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬vo-prog1.usa¬0053B10F¬524288¬¬¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬ep18666.13¬66EDB432¬524288¬von¬ep18666.13¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬ep18667.14¬B593D31F¬524288¬von¬ep18667.14¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18648.11¬2EDBE489¬4194304¬von¬mp18648.11¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18649.12¬E68C5AA6¬4194304¬von¬mp18649.12¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18650.9¬89A855B9¬4194304¬von¬mp18650.9¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18651.10¬F4C23107¬4194304¬von¬mp18651.10¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18662.29¬A33D3335¬2097152¬von¬mp18662.29¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18663.30¬EA74A641¬2097152¬von¬mp18663.30¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬ep18643a.7¬B5E048EC¬131072¬von¬ep18643a.7¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬ep18670.31¬3E715F76¬524288¬von¬ep18670.31¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18652.32¬037EEE53¬4194304¬von¬mp18652.32¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18653.34¬9EC3E7BF¬4194304¬von¬mp18653.34¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18654.17¬6A0CAF29¬4194304¬von¬mp18654.17¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18655.21¬A4293E78¬4194304¬von¬mp18655.21¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18656.18¬B4F51E76¬4194304¬von¬mp18656.18¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18657.22¬A9BE4674¬4194304¬von¬mp18657.22¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18660.27¬E53663E5¬2097152¬von¬mp18660.27¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18658.25¬3D0FCD01¬2097152¬von¬mp18658.25¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18661.28¬52B50410¬2097152¬von¬mp18661.28¬
¬von¬Virtual ON¬vonusa¬Virtual ON (USA)¬mp18659.26¬27AA8AE2¬2097152¬von¬mp18659.26¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬ep20437¬FAD30CC0¬524288¬¬¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬ep20438¬CA364408¬524288¬¬¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20296.11¬072D8A5E¬4194304¬zerogun¬mp20296.11¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20297.12¬BA6A825B¬4194304¬zerogun¬mp20297.12¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20294.9¬A0BD1474¬4194304¬zerogun¬mp20294.9¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20295.10¬C548CCED¬4194304¬zerogun¬mp20295.10¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬ep20302.31¬44FF50D2¬524288¬zerogun¬ep20302.31¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20303.32¬C040973F¬2097152¬zerogun¬mp20303.32¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20304.33¬6DECFE83¬2097152¬zerogun¬mp20304.33¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20298.17¬8AB782FC¬4194304¬zerogun¬mp20298.17¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20299.21¬90E20CDB¬4194304¬zerogun¬mp20299.21¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20301.27¬52010FB2¬2097152¬zerogun¬mp20301.27¬
¬zerogun¬Zero Gunner¬zeroguna¬Zero Gunner (Model 2A)¬mp20300.25¬6F042792¬2097152¬zerogun¬mp20300.25¬

View File

@@ -0,0 +1,100 @@
Barney Bear Goes to School (USA) (Track 01).bin c2b0380c
Barney Bear Goes to School (USA) (Track 02).bin c5a453dc
Barney Bear Goes to School (USA) (Track 03).bin ace9996c
Barney Bear Goes to School (USA) (Track 04).bin 6f40b0b0
Barney Bear Goes to School (USA) (Track 05).bin 8ac376dc
Barney Bear Goes to School (USA) (Track 06).bin c645a24b
Barney Bear Goes to School (USA) (Track 07).bin d94cf99c
Barney Bear Goes to School (USA) (Track 08).bin cbbd68c0
Barney Bear Goes to School (USA) (Track 09).bin f0fc14c8
Barney Bear Goes to School (USA) (Track 10).bin acf0a9a5
Barney Bear Goes to School (USA) (Track 11).bin 5b331b57
Barney Bear Goes to School (USA) (Track 12).bin b9b64ec0
Barney Bear Goes to School (USA) (Track 13).bin d6851dee
Barney Bear Goes to School (USA) (Track 14).bin 037889d2
Barney Bear Goes to School (USA) (Track 15).bin f3d32cea
Barney Bear Goes to School (USA) (Track 16).bin 3ccd6a90
Barney Bear Goes to School (USA) (Track 17).bin feeb7b3e
Barney Bear Goes to School (USA) (Track 18).bin 9400c912
Barney Bear Goes to School (USA) (Track 19).bin 31b6478a
Barney Bear Goes to School (USA) (Track 20).bin ed18d3d0
Barney Bear Goes to School (USA) (Track 21).bin 6aca0fd9
Barney Bear Goes to School (USA) (Track 22).bin 1f4c00d4
Barney Bear Goes to School (USA) (Track 23).bin ce9c3836
Barney Bear Goes to School (USA) (Track 24).bin 14a52799
Barney Bear Goes to School (USA) (Track 25).bin b8735a03
Barney Bear Goes to School (USA) (Track 26).bin f489cd1f
Barney Bear Goes to School (USA) (Track 27).bin bbb1166b
Barney Bear Goes to School (USA) (Track 28).bin 991e15c5
Barney Bear Goes to School (USA) (Track 29).bin 7649e2b4
Barney Bear Goes to School (USA) (Track 30).bin 6902b486
Barney Bear Goes to School (USA) (Track 31).bin f154b6a4
Barney Bear Goes to School (USA) (Track 32).bin 58dbf520
Barney Bear Goes to School (USA) (Track 33).bin 8ff80802
Barney Bear Goes to School (USA) (Track 34).bin 8b54c487
Barney Bear Goes to School (USA) (Track 35).bin c8de569a
Barney Bear Goes to School (USA) (Track 36).bin 7cdecfde
Barney Bear Goes to School (USA) (Track 37).bin 601727ad
Barney Bear Goes to School (USA) (Track 38).bin 807f518e
Barney Bear Goes to School (USA) (Track 39).bin e5048ba4
Barney Bear Goes to School (USA) (Track 40).bin de2bcb80
Barney Bear Goes to School (USA) (Track 41).bin 9025a637
Barney Bear Goes to School (USA) (Track 42).bin df40bb50
Barney Bear Goes to School (USA) (Track 43).bin 01f0c4b3
Barney Bear Goes to School (USA) (Track 44).bin 8b4242b2
Barney Bear Goes to School (USA) (Track 45).bin 7876d09b
Barney Bear Goes to School (USA) (Track 46).bin 9428abad
Barney Bear Goes to School (USA) (Track 47).bin 9d893258
Barney Bear Goes to School (USA) (Track 48).bin 51aac16b
Barney Bear Goes to School (USA) (Track 49).bin 362fa379
Barney Bear Goes to School (USA) (Track 50).bin e4d8ecaa
Barney Bear Goes to School (USA) (Track 51).bin f08992b3
Barney Bear Goes to School (USA) (Track 52).bin 3c8d4367
Barney Bear Goes to School (USA) (Track 53).bin 87954cbc
Barney Bear Goes to School (USA) (Track 54).bin ec086f32
Barney Bear Goes to School (USA) (Track 55).bin c394fa0f
Barney Bear Goes to School (USA) (Track 56).bin 3ad4671d
Barney Bear Goes to School (USA) (Track 57).bin 333cacef
Barney Bear Goes to School (USA) (Track 58).bin cbfcb5d7
Barney Bear Goes to School (USA) (Track 59).bin 504777c6
Barney Bear Goes to School (USA) (Track 60).bin 1fa823d3
Barney Bear Goes to School (USA) (Track 61).bin 24ee30bb
Barney Bear Goes to School (USA) (Track 62).bin 660b6ef0
Barney Bear Goes to School (USA) (Track 63).bin f666dcd5
Barney Bear Goes to School (USA) (Track 64).bin e32633c6
Barney Bear Goes to School (USA) (Track 65).bin 2188de3b
Barney Bear Goes to School (USA) (Track 66).bin f91dd564
Barney Bear Goes to School (USA) (Track 67).bin 37bf5c5b
Barney Bear Goes to School (USA) (Track 68).bin 668ed023
Barney Bear Goes to School (USA) (Track 69).bin 5518673c
Barney Bear Goes to School (USA) (Track 70).bin e439b914
Barney Bear Goes to School (USA) (Track 71).bin 56ee347d
Barney Bear Goes to School (USA) (Track 72).bin 4be41c59
Barney Bear Goes to School (USA) (Track 73).bin 5a115f81
Barney Bear Goes to School (USA) (Track 74).bin 11634540
Barney Bear Goes to School (USA) (Track 75).bin 476bb94b
Barney Bear Goes to School (USA) (Track 76).bin 6826e507
Barney Bear Goes to School (USA) (Track 77).bin 305f858f
Barney Bear Goes to School (USA) (Track 78).bin 08502ef6
Barney Bear Goes to School (USA) (Track 79).bin a8aa910e
Barney Bear Goes to School (USA) (Track 80).bin e02d0ab2
Barney Bear Goes to School (USA) (Track 81).bin d49c10fa
Barney Bear Goes to School (USA) (Track 82).bin 068d3b79
Barney Bear Goes to School (USA) (Track 83).bin 1e893985
Barney Bear Goes to School (USA) (Track 84).bin f4a1fa93
Barney Bear Goes to School (USA) (Track 85).bin 4602f294
Barney Bear Goes to School (USA) (Track 86).bin 5a128907
Barney Bear Goes to School (USA) (Track 87).bin f07cd311
Barney Bear Goes to School (USA) (Track 88).bin f05e95f7
Barney Bear Goes to School (USA) (Track 89).bin 4a349918
Barney Bear Goes to School (USA) (Track 90).bin 86946adb
Barney Bear Goes to School (USA) (Track 91).bin 8cb842ec
Barney Bear Goes to School (USA) (Track 92).bin 25a06f44
Barney Bear Goes to School (USA) (Track 93).bin 103f23af
Barney Bear Goes to School (USA) (Track 94).bin 37ab546f
Barney Bear Goes to School (USA) (Track 95).bin 96f61b43
Barney Bear Goes to School (USA) (Track 96).bin 3cf5c0a6
Barney Bear Goes to School (USA) (Track 97).bin 3f9148ea
Barney Bear Goes to School (USA) (Track 98).bin 4fd7ddae
Barney Bear Goes to School (USA) (Track 99).bin fab012e6
Barney Bear Goes to School (USA).cue ac37e95b

View File

@@ -0,0 +1,100 @@
552497c13fc47fa14a7b626bf6b01de6020e091a *Barney Bear Goes to School (USA) (Track 01).bin
d2bbb8e2d902bab9d2326c358da0f89076ba86ac *Barney Bear Goes to School (USA) (Track 02).bin
14c9d68301fd1116bf929d26119cf34c03889af3 *Barney Bear Goes to School (USA) (Track 03).bin
3d494d1975bd89a10e1f17dc5ac0a1f5827c32f2 *Barney Bear Goes to School (USA) (Track 04).bin
c80bae6ba28fc9e7c45ef3228903c0b3b06d384f *Barney Bear Goes to School (USA) (Track 05).bin
059bcbad79f1d3455f3bc75befebaad9ad3f9324 *Barney Bear Goes to School (USA) (Track 06).bin
7960707b46957df2cabb8fa154bf033e31580b2c *Barney Bear Goes to School (USA) (Track 07).bin
452e78d923ac63e02b0b165a1e1c986734ebba61 *Barney Bear Goes to School (USA) (Track 08).bin
cf189c32133d62df96c3ce0a36288113da823aa7 *Barney Bear Goes to School (USA) (Track 09).bin
a1434029702c0b353d8306c7e9950819ba5267db *Barney Bear Goes to School (USA) (Track 10).bin
ce4fc5f66808d0fe367e68f880431498f6b478fb *Barney Bear Goes to School (USA) (Track 11).bin
3e80a154316a345fb127ca37ba6b8b72c750e4e6 *Barney Bear Goes to School (USA) (Track 12).bin
50ff9c0f8e9b0a87e5b36e2ecc0f3f1508784675 *Barney Bear Goes to School (USA) (Track 13).bin
0762ef8f6905f45acf8c4ae4054ab60a6cf7c073 *Barney Bear Goes to School (USA) (Track 14).bin
ad67f5ca5844d75c592fad8f12336d3133a183b4 *Barney Bear Goes to School (USA) (Track 15).bin
0920f59fd541026fe4d0d795bc7b6c57a36ad91f *Barney Bear Goes to School (USA) (Track 16).bin
3309dab66316e075faf4893f55ff0798ae2f88cc *Barney Bear Goes to School (USA) (Track 17).bin
3c69e6c6973218c427eb1a1e9a345f68e6b49fc6 *Barney Bear Goes to School (USA) (Track 18).bin
4f5cf49b310c832252127b12cc2b0df229180359 *Barney Bear Goes to School (USA) (Track 19).bin
7ab59b64684c10884fcf6c9ecc043dc7a5153841 *Barney Bear Goes to School (USA) (Track 20).bin
3a278ff89146499e6a7e7e25909305d1cfa5fb80 *Barney Bear Goes to School (USA) (Track 21).bin
0b92f885a17fc0553927f9fa0cacf1da6b6b7b39 *Barney Bear Goes to School (USA) (Track 22).bin
8669634838d19a7032e8526e038bd399bfdf9b57 *Barney Bear Goes to School (USA) (Track 23).bin
6912d94ded87afb74bcca87806f3f72bf4702b9d *Barney Bear Goes to School (USA) (Track 24).bin
9ed5776b573c700ab26c32a459a0fd1a00485328 *Barney Bear Goes to School (USA) (Track 25).bin
9efdff891f55eca95a02b348d66c35980ad968de *Barney Bear Goes to School (USA) (Track 26).bin
d2a421fd7018b6eed013cbe61b8ee2070eb2aceb *Barney Bear Goes to School (USA) (Track 27).bin
90442878e2556a87b57c321641e708e8ad93a471 *Barney Bear Goes to School (USA) (Track 28).bin
e2fda0b201b406190a1917ed7efd00e79d272efb *Barney Bear Goes to School (USA) (Track 29).bin
76cb82eb26e66fa432e268fe43911fc708cbb6ee *Barney Bear Goes to School (USA) (Track 30).bin
b69ef59ca3a9826c4137c59a5eb30f3e305f9b30 *Barney Bear Goes to School (USA) (Track 31).bin
2bde2c5a8f0d74c6bd083dd1cb5377be2070524d *Barney Bear Goes to School (USA) (Track 32).bin
54d4a3f7869786899393d4fb67fbe03e40626330 *Barney Bear Goes to School (USA) (Track 33).bin
9e52d519d4579ebac2d3da9c5ce0669eddb19cfe *Barney Bear Goes to School (USA) (Track 34).bin
ee811b8c5f8f60e3398148a79d195ae2848d8e4c *Barney Bear Goes to School (USA) (Track 35).bin
e27350c280c69b7c11bd44267a539073fb0b77fc *Barney Bear Goes to School (USA) (Track 36).bin
d5089422ddfce443abf69ec23befb210c9062077 *Barney Bear Goes to School (USA) (Track 37).bin
835924566f39f4d8c64094d1ed863937917e0707 *Barney Bear Goes to School (USA) (Track 38).bin
4abf1743a011b3183f0b057ebeccc163fa0f3045 *Barney Bear Goes to School (USA) (Track 39).bin
c150b686dda96233048b0f1d29ccea071daf9f01 *Barney Bear Goes to School (USA) (Track 40).bin
640d9918d448bce59be2e1ef52e5b82587613b23 *Barney Bear Goes to School (USA) (Track 41).bin
ce62fdb5a9f32b9292b787ac51e04d7498f11964 *Barney Bear Goes to School (USA) (Track 42).bin
23d147665661a130d1f073467cf6f6f0704f4d7b *Barney Bear Goes to School (USA) (Track 43).bin
6b4349b5279a92f428e349abebce438cd965810c *Barney Bear Goes to School (USA) (Track 44).bin
85b3d934c062498f3090538d6da6a3c63d089508 *Barney Bear Goes to School (USA) (Track 45).bin
302edc1ad287fa0df75b4c86307ac747f8df4a24 *Barney Bear Goes to School (USA) (Track 46).bin
2de127469e98e4fa7bfe00bbb882007fcdb12856 *Barney Bear Goes to School (USA) (Track 47).bin
e6b1ae9d4e5f281afe8b6c3defed0431dcb99b91 *Barney Bear Goes to School (USA) (Track 48).bin
893cb6ade428f689b38a125d275379bf31aee8d3 *Barney Bear Goes to School (USA) (Track 49).bin
8358d5170b00b4d09c56b8a28c828ebba1d5adf7 *Barney Bear Goes to School (USA) (Track 50).bin
2b423bf03c9c49dc0be0175c8c3299012d364200 *Barney Bear Goes to School (USA) (Track 51).bin
12a6097937de5d869b27d7a8238da8340f438ade *Barney Bear Goes to School (USA) (Track 52).bin
84698a6f846de2a779a81a8b93cbbcbc9036a8dc *Barney Bear Goes to School (USA) (Track 53).bin
4061e1f7258a0c87cb23336e4f64cbaf4cdd254d *Barney Bear Goes to School (USA) (Track 54).bin
cc8f53b24f138fc21a23b019a437368289a4c265 *Barney Bear Goes to School (USA) (Track 55).bin
7b763ba759342e15eb2ccc4d98acbc01cca3ca39 *Barney Bear Goes to School (USA) (Track 56).bin
f630af7d1e49a95ab428bdb74126f81b62730912 *Barney Bear Goes to School (USA) (Track 57).bin
17e48a7e1a32b85977eb7b8ad4fae85d8c42bf86 *Barney Bear Goes to School (USA) (Track 58).bin
10d5b198c8499ebfd41d68eb6c8de18b2e69e65f *Barney Bear Goes to School (USA) (Track 59).bin
47185af038c1d83ab89317010050afa512bc2886 *Barney Bear Goes to School (USA) (Track 60).bin
f5bd27601429f2f716e65ab2f897d5197717ede8 *Barney Bear Goes to School (USA) (Track 61).bin
199f76e7ed30f85009e05a5525b23f0e89995a91 *Barney Bear Goes to School (USA) (Track 62).bin
0cab20ff575958d3c81728c90c891e10f715e0af *Barney Bear Goes to School (USA) (Track 63).bin
e335f003aea9e9e813cf5e426bc72f07ec768b17 *Barney Bear Goes to School (USA) (Track 64).bin
e99995125809473a9a3bfcefcec7e4da1d4f797b *Barney Bear Goes to School (USA) (Track 65).bin
97afb5a41008b20e1bcccdac76936f49d9a749eb *Barney Bear Goes to School (USA) (Track 66).bin
53be03dfca426ac80378b10d0e36a33e9c11d776 *Barney Bear Goes to School (USA) (Track 67).bin
3d9a3eaa86603918ebe477ae28bacfc304fe5425 *Barney Bear Goes to School (USA) (Track 68).bin
9da2fdf58468db4b780b57c5b2076e481d7698ed *Barney Bear Goes to School (USA) (Track 69).bin
5e2855cf17f0d2030ea88aa95ce23caa210a3510 *Barney Bear Goes to School (USA) (Track 70).bin
d3b7ac10d5ad278d395c0728d93d83e731f93967 *Barney Bear Goes to School (USA) (Track 71).bin
06af05085066a2d57fdf0bfd1426567e740372c7 *Barney Bear Goes to School (USA) (Track 72).bin
52149d8d53a03d0cee85cc4e4df1b82e5ac88e10 *Barney Bear Goes to School (USA) (Track 73).bin
85f6ad48de39dfbc87aa4fa46ba016984aa8c679 *Barney Bear Goes to School (USA) (Track 74).bin
a2791067722c9b0f3da80ed06b264498dd98ff15 *Barney Bear Goes to School (USA) (Track 75).bin
c7313b864bc7d8577bfb9f51fc3c78d21f531816 *Barney Bear Goes to School (USA) (Track 76).bin
4213b728f776ce2c9794249f0e606e374d8360a9 *Barney Bear Goes to School (USA) (Track 77).bin
c820dff0bb7701b713e23349b0fd7f7ab4665fdd *Barney Bear Goes to School (USA) (Track 78).bin
3d9e1093945b295cb55cad9677670596f662795d *Barney Bear Goes to School (USA) (Track 79).bin
ae9a1f294ef937e5d55a879a1902aa8977363c14 *Barney Bear Goes to School (USA) (Track 80).bin
0d2590dfa441e56044b2a10a43a9db970874030f *Barney Bear Goes to School (USA) (Track 81).bin
d60d6f2e180d66167eaf33263939b7955f86d5f5 *Barney Bear Goes to School (USA) (Track 82).bin
15cbcf935c605fdb99052b5d21733eeb77ddd72b *Barney Bear Goes to School (USA) (Track 83).bin
001f27aebd72128158b2d5b7a48d8f713dde7c95 *Barney Bear Goes to School (USA) (Track 84).bin
2a67600411c22a58f721b3da5a289957f9f52f65 *Barney Bear Goes to School (USA) (Track 85).bin
4e42e0e0adb78d3917bc38b5101e7a973d7238b6 *Barney Bear Goes to School (USA) (Track 86).bin
4a190ced3513bfce98e3c93dbdb774ecf8b1d6aa *Barney Bear Goes to School (USA) (Track 87).bin
2325d30fe9ce608a5c6982c7c02185e6f97fab63 *Barney Bear Goes to School (USA) (Track 88).bin
7fc6e6263f54c245770ddb9a541e323036f67d2c *Barney Bear Goes to School (USA) (Track 89).bin
b3e79071a649e2492a9f7937e062ad57454858a1 *Barney Bear Goes to School (USA) (Track 90).bin
c2eab8f35e746dfd9335dfd67203dfeccb458de5 *Barney Bear Goes to School (USA) (Track 91).bin
6da8c81d445b0190ba0c11ef44dc181b48981eb3 *Barney Bear Goes to School (USA) (Track 92).bin
58c0f25bdc479a7c7ab63324fa8e5257aee4ec30 *Barney Bear Goes to School (USA) (Track 93).bin
ff55b21f3931d8f2a7685a207a95088445eb31cd *Barney Bear Goes to School (USA) (Track 94).bin
78497cb64ca43645e14a21129329982e7138f802 *Barney Bear Goes to School (USA) (Track 95).bin
6df2447ce0fd01e7db56a23942c0ae72200f3a97 *Barney Bear Goes to School (USA) (Track 96).bin
13134fa895412372ba243b161965c978e23f6fd2 *Barney Bear Goes to School (USA) (Track 97).bin
360703189c7756f774ac4c26d4f381ae1d1b5b07 *Barney Bear Goes to School (USA) (Track 98).bin
43b2ab2a65d451f0527c1572f1308430148c96e3 *Barney Bear Goes to School (USA) (Track 99).bin
48d2d7269050249dc7a2e5881177778359a6345b *Barney Bear Goes to School (USA).cue

View File

@@ -0,0 +1 @@
ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad rom.bin

View File

@@ -0,0 +1 @@
cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 rom.bin

View File

@@ -0,0 +1 @@
ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f rom.bin

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
QXX rom.bin

View File

@@ -0,0 +1,3 @@
File Name;Internal Name;Description;Game Name;Game Description;Type;Rom Name;Disk Name;Size;CRC;MD5;SHA1;SHA256;Nodump
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Rom;file.bin;;12345;0;d41d8cd98f00b204e9800998ecf8427e;da39a3ee5e6b4b0d3255bfef95601890afd80709;ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad;No
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Disk;;file.chd;;;;da39a3ee5e6b4b0d3255bfef95601890afd80709;;No

View File

@@ -0,0 +1,3 @@
File Name;Internal Name;Description;Game Name;Game Description;Type;Rom Name;Disk Name;Size;CRC;MD5;SHA1;SHA256;SHA384;SHA512;SpamSum;Nodump
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Rom;file.bin;;12345;0;d41d8cd98f00b204e9800998ecf8427e;da39a3ee5e6b4b0d3255bfef95601890afd80709;ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad;cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7;ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f;QXX;No
Original DatFile Name.xml;Original DatFile Name;Original DatFile;Game;A cool game;Disk;;file.chd;;;;da39a3ee5e6b4b0d3255bfef95601890afd80709;;;;;No

View File

@@ -0,0 +1,3 @@
File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 Nodump
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad No
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No

View File

@@ -0,0 +1,3 @@
File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 SHA384 SHA512 SpamSum Nodump
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f QXX No
Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No
1 File Name Internal Name Description Game Name Game Description Type Rom Name Disk Name Size CRC MD5 SHA1 SHA256 SHA384 SHA512 SpamSum Nodump
2 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Rom file.bin 12345 0 d41d8cd98f00b204e9800998ecf8427e da39a3ee5e6b4b0d3255bfef95601890afd80709 ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7 ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f QXX No
3 Original DatFile Name.xml Original DatFile Name Original DatFile Game A cool game Disk file.chd da39a3ee5e6b4b0d3255bfef95601890afd80709 No

View File

@@ -7,6 +7,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Serialization",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{F3DEE31A-4726-464C-A90C-C19D78F51898}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Serialization.Test", "SabreTools.Serialization.Test\SabreTools.Serialization.Test.csproj", "{B8A04C5E-A14F-4842-9035-2F6871A1DA10}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -24,5 +26,9 @@ Global
{F3DEE31A-4726-464C-A90C-C19D78F51898}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3DEE31A-4726-464C-A90C-C19D78F51898}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3DEE31A-4726-464C-A90C-C19D78F51898}.Release|Any CPU.Build.0 = Release|Any CPU
{B8A04C5E-A14F-4842-9035-2F6871A1DA10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B8A04C5E-A14F-4842-9035-2F6871A1DA10}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B8A04C5E-A14F-4842-9035-2F6871A1DA10}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B8A04C5E-A14F-4842-9035-2F6871A1DA10}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

View File

@@ -70,20 +70,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
byte[]? magic = data.ReadBytes(4);
if (magic == null)
if (header == null)
return null;
header.Magic = Encoding.ASCII.GetString(magic);
if (header.Magic != SignatureString)
return null;
header.Version = data.ReadInt32();
header.Files = data.ReadInt32();
return header;
}
@@ -92,10 +85,10 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled file entry on success, null on error</returns>
private static FileEntry ParseFileEntry(Stream data)
private static FileEntry? ParseFileEntry(Stream data)
{
// TODO: Use marshalling here instead of building
FileEntry fileEntry = new FileEntry();
var fileEntry = new FileEntry();
fileEntry.NameSize = data.ReadInt32();
if (fileEntry.NameSize > 0)

View File

@@ -47,6 +47,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < HL_BSP_LUMP_COUNT; i++)
{
var lump = ParseLump(data);
if (lump == null)
return null;
file.Lumps[i] = lump;
}
@@ -102,13 +105,13 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Level header on success, null on error</returns>
/// <remarks>Only recognized versions are 29 and 30</remarks>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
// Only recognized versions are 29 and 30
header.Version = data.ReadUInt32();
if (header == null)
return null;
if (header.Version != 29 && header.Version != 30)
return null;
@@ -120,15 +123,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled lump on success, null on error</returns>
private static Lump ParseLump(Stream data)
private static Lump? ParseLump(Stream data)
{
// TODO: Use marshalling here instead of building
Lump lump = new Lump();
lump.Offset = data.ReadUInt32();
lump.Length = data.ReadUInt32();
return lump;
return data.ReadType<Lump>();
}
/// <summary>
@@ -139,7 +136,7 @@ namespace SabreTools.Serialization.Deserializers
private static TextureHeader ParseTextureHeader(Stream data)
{
// TODO: Use marshalling here instead of building
TextureHeader textureHeader = new TextureHeader();
var textureHeader = new TextureHeader();
textureHeader.TextureCount = data.ReadUInt32();
@@ -166,7 +163,7 @@ namespace SabreTools.Serialization.Deserializers
private static Texture ParseTexture(Stream data, uint mipmap = 0)
{
// TODO: Use marshalling here instead of building
Texture texture = new Texture();
var texture = new Texture();
byte[]? name = data.ReadBytes(16)?.TakeWhile(c => c != '\0')?.ToArray();
if (name != null)

View File

@@ -17,6 +17,11 @@ namespace SabreTools.Serialization.Deserializers
IFileDeserializer<TModel>,
IStreamDeserializer<TModel>
{
/// <summary>
/// Indicates if compressed files should be decompressed before processing
/// </summary>
protected virtual bool SkipCompression => false;
#region IByteDeserializer
/// <inheritdoc/>
@@ -42,7 +47,7 @@ namespace SabreTools.Serialization.Deserializers
/// <inheritdoc/>
public virtual TModel? Deserialize(string? path)
{
using var stream = PathProcessor.OpenStream(path);
using var stream = PathProcessor.OpenStream(path, SkipCompression);
return DeserializeStream(stream);
}
@@ -98,32 +103,56 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Deserializer of the requested type, null on error</returns>
private static TDeserializer? GetType<TDeserializer>()
{
var assembly = Assembly.GetExecutingAssembly();
if (assembly == null)
// If the deserializer type is invalid
string? deserializerName = typeof(TDeserializer)?.Name;
if (deserializerName == null)
return default;
// If not all types can be loaded, use the ones that could be
List<Type> assemblyTypes = [];
try
{
assemblyTypes = assembly.GetTypes().ToList<Type>();
}
catch (ReflectionTypeLoadException rtle)
{
assemblyTypes = rtle.Types.Where(t => t != null)!.ToList<Type>();
}
// If the deserializer has no model type
Type? modelType = typeof(TDeserializer).GetGenericArguments()?.FirstOrDefault();
if (modelType == null)
return default;
// Loop through all types
foreach (Type type in assemblyTypes)
// Loop through all loaded assemblies
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
// If the type isn't a class or doesn't implement the interface
if (!type.IsClass || type.GetInterface(typeof(TDeserializer).Name) == null)
continue;
// If the assembly is invalid
if (assembly == null)
return default;
// Try to create a concrete instance of the type
var instance = (TDeserializer?)Activator.CreateInstance(type);
if (instance != null)
return instance;
// If not all types can be loaded, use the ones that could be
List<Type> assemblyTypes = [];
try
{
assemblyTypes = assembly.GetTypes().ToList<Type>();
}
catch (ReflectionTypeLoadException rtle)
{
assemblyTypes = rtle.Types.Where(t => t != null)!.ToList<Type>();
}
// Loop through all types
foreach (Type type in assemblyTypes)
{
// If the type isn't a class
if (!type.IsClass)
continue;
// If the type doesn't implement the interface
var interfaceType = type.GetInterface(deserializerName);
if (interfaceType == null)
continue;
// If the interface doesn't use the correct type parameter
var genericTypes = interfaceType.GetGenericArguments();
if (genericTypes.Length != 1 || genericTypes[0] != modelType)
continue;
// Try to create a concrete instance of the type
var instance = (TDeserializer?)Activator.CreateInstance(type);
if (instance != null)
return instance;
}
}
return default;

View File

@@ -42,7 +42,7 @@ namespace SabreTools.Serialization.Deserializers
#region DIFAT Sector Numbers
// Create a DIFAT sector table
var difatSectors = new List<SectorNumber?>();
var difatSectors = new List<SectorNumber>();
// Add the sectors from the header
if (fileHeader.DIFAT != null)
@@ -84,7 +84,7 @@ namespace SabreTools.Serialization.Deserializers
#region FAT Sector Numbers
// Create a FAT sector table
var fatSectors = new List<SectorNumber?>();
var fatSectors = new List<SectorNumber>();
// Loop through and add the FAT sectors
currentSector = binary.DIFATSectorNumbers[0];
@@ -122,7 +122,7 @@ namespace SabreTools.Serialization.Deserializers
#region Mini FAT Sector Numbers
// Create a mini FAT sector table
var miniFatSectors = new List<SectorNumber?>();
var miniFatSectors = new List<SectorNumber>();
// Loop through and add the mini FAT sectors
currentSector = (SectorNumber)fileHeader.FirstMiniFATSectorLocation;
@@ -233,49 +233,23 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled file header on success, null on error</returns>
private static FileHeader? ParseFileHeader(Stream data)
{
// TODO: Use marshalling here instead of building
FileHeader header = new FileHeader();
var header = data.ReadType<FileHeader>();
header.Signature = data.ReadUInt64();
if (header == null)
return null;
if (header.Signature != SignatureUInt64)
return null;
header.CLSID = data.ReadGuid();
header.MinorVersion = data.ReadUInt16();
header.MajorVersion = data.ReadUInt16();
header.ByteOrder = data.ReadUInt16();
if (header.ByteOrder != 0xFFFE)
return null;
header.SectorShift = data.ReadUInt16();
if (header.MajorVersion == 3 && header.SectorShift != 0x0009)
return null;
else if (header.MajorVersion == 4 && header.SectorShift != 0x000C)
return null;
header.MiniSectorShift = data.ReadUInt16();
header.Reserved = data.ReadBytes(6);
header.NumberOfDirectorySectors = data.ReadUInt32();
if (header.MajorVersion == 3 && header.NumberOfDirectorySectors != 0)
return null;
header.NumberOfFATSectors = data.ReadUInt32();
header.FirstDirectorySectorLocation = data.ReadUInt32();
header.TransactionSignatureNumber = data.ReadUInt32();
header.MiniStreamCutoffSize = data.ReadUInt32();
if (header.MiniStreamCutoffSize != 0x00001000)
return null;
header.FirstMiniFATSectorLocation = data.ReadUInt32();
header.NumberOfMiniFATSectors = data.ReadUInt32();
header.FirstDIFATSectorLocation = data.ReadUInt32();
header.NumberOfDIFATSectors = data.ReadUInt32();
header.DIFAT = new SectorNumber?[109];
for (int i = 0; i < header.DIFAT.Length; i++)
{
header.DIFAT[i] = (SectorNumber)data.ReadUInt32();
}
// Skip rest of sector for version 4
if (header.MajorVersion == 4)
_ = data.ReadBytes(3584);
@@ -289,11 +263,11 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="sectorShift">Sector shift from the header</param>
/// <returns>Filled sector full of sector numbers on success, null on error</returns>
private static SectorNumber?[] ParseSectorNumbers(Stream data, ushort sectorShift)
private static SectorNumber[] ParseSectorNumbers(Stream data, ushort sectorShift)
{
// TODO: Use marshalling here instead of building
int sectorCount = (int)(Math.Pow(2, sectorShift) / sizeof(uint));
var sectorNumbers = new SectorNumber?[sectorCount];
var sectorNumbers = new SectorNumber[sectorCount];
for (int i = 0; i < sectorNumbers.Length; i++)
{
@@ -315,7 +289,7 @@ namespace SabreTools.Serialization.Deserializers
// TODO: Use marshalling here instead of building
const int directoryEntrySize = 64 + 2 + 1 + 1 + 4 + 4 + 4 + 16 + 4 + 8 + 8 + 4 + 8;
int sectorCount = (int)(Math.Pow(2, sectorShift) / directoryEntrySize);
DirectoryEntry[] directoryEntries = new DirectoryEntry[sectorCount];
var directoryEntries = new DirectoryEntry[sectorCount];
for (int i = 0; i < directoryEntries.Length; i++)
{
@@ -335,26 +309,17 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="majorVersion">Major version from the header</param>
/// <returns>Filled directory entry on success, null on error</returns>
private static DirectoryEntry ParseDirectoryEntry(Stream data, ushort majorVersion)
private static DirectoryEntry? ParseDirectoryEntry(Stream data, ushort majorVersion)
{
// TODO: Use marshalling here instead of building
DirectoryEntry directoryEntry = new DirectoryEntry();
var directoryEntry = data.ReadType<DirectoryEntry>();
byte[]? name = data.ReadBytes(64);
if (name != null)
directoryEntry.Name = Encoding.Unicode.GetString(name).TrimEnd('\0');
directoryEntry.NameLength = data.ReadUInt16();
directoryEntry.ObjectType = (ObjectType)data.ReadByteValue();
directoryEntry.ColorFlag = (ColorFlag)data.ReadByteValue();
directoryEntry.LeftSiblingID = (StreamID)data.ReadUInt32();
directoryEntry.RightSiblingID = (StreamID)data.ReadUInt32();
directoryEntry.ChildID = (StreamID)data.ReadUInt32();
directoryEntry.CLSID = data.ReadGuid();
directoryEntry.StateBits = data.ReadUInt32();
directoryEntry.CreationTime = data.ReadUInt64();
directoryEntry.ModifiedTime = data.ReadUInt64();
directoryEntry.StartingSectorLocation = data.ReadUInt32();
directoryEntry.StreamSize = data.ReadUInt64();
if (directoryEntry == null)
return null;
// TEMPORARY FIX FOR ASCII -> UNICODE
directoryEntry.Name = Encoding.Unicode.GetString(Encoding.ASCII.GetBytes(directoryEntry.Name!));
// Handle version 3 entries
if (majorVersion == 3)
directoryEntry.StreamSize &= 0x0000FFFF;

View File

@@ -145,22 +145,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled CIA header on success, null on error</returns>
private static CIAHeader ParseCIAHeader(Stream data)
public static CIAHeader? ParseCIAHeader(Stream data)
{
// TODO: Use marshalling here instead of building
CIAHeader ciaHeader = new CIAHeader();
ciaHeader.HeaderSize = data.ReadUInt32();
ciaHeader.Type = data.ReadUInt16();
ciaHeader.Version = data.ReadUInt16();
ciaHeader.CertificateChainSize = data.ReadUInt32();
ciaHeader.TicketSize = data.ReadUInt32();
ciaHeader.TMDFileSize = data.ReadUInt32();
ciaHeader.MetaSize = data.ReadUInt32();
ciaHeader.ContentSize = data.ReadUInt64();
ciaHeader.ContentIndex = data.ReadBytes(0x2000);
return ciaHeader;
return data.ReadType<CIAHeader>();
}
/// <summary>
@@ -168,7 +155,7 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled certificate on success, null on error</returns>
private static Certificate? ParseCertificate(Stream data)
public static Certificate? ParseCertificate(Stream data)
{
// TODO: Use marshalling here instead of building
Certificate certificate = new Certificate();
@@ -244,7 +231,7 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="fromCdn">Indicates if the ticket is from CDN</param>
/// <returns>Filled ticket on success, null on error</returns>
private static Ticket? ParseTicket(Stream data, bool fromCdn = false)
public static Ticket? ParseTicket(Stream data, bool fromCdn = false)
{
// TODO: Use marshalling here instead of building
Ticket ticket = new Ticket();
@@ -349,10 +336,10 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="fromCdn">Indicates if the ticket is from CDN</param>
/// <returns>Filled title metadata on success, null on error</returns>
private static TitleMetadata? ParseTitleMetadata(Stream data, bool fromCdn = false)
public static TitleMetadata? ParseTitleMetadata(Stream data, bool fromCdn = false)
{
// TODO: Use marshalling here instead of building
TitleMetadata titleMetadata = new TitleMetadata();
var titleMetadata = new TitleMetadata();
titleMetadata.SignatureType = (SignatureType)data.ReadUInt32();
switch (titleMetadata.SignatureType)
@@ -420,11 +407,19 @@ namespace SabreTools.Serialization.Deserializers
titleMetadata.ContentInfoRecords = new ContentInfoRecord[64];
for (int i = 0; i < 64; i++)
{
var contentInfoRecord = ParseContentInfoRecord(data);
if (contentInfoRecord == null)
return null;
titleMetadata.ContentInfoRecords[i] = ParseContentInfoRecord(data);
}
titleMetadata.ContentChunkRecords = new ContentChunkRecord[titleMetadata.ContentCount];
for (int i = 0; i < titleMetadata.ContentCount; i++)
{
var contentChunkRecord = ParseContentChunkRecord(data);
if (contentChunkRecord == null)
return null;
titleMetadata.ContentChunkRecords[i] = ParseContentChunkRecord(data);
}
@@ -450,16 +445,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled content info record on success, null on error</returns>
private static ContentInfoRecord ParseContentInfoRecord(Stream data)
public static ContentInfoRecord? ParseContentInfoRecord(Stream data)
{
// TODO: Use marshalling here instead of building
ContentInfoRecord contentInfoRecord = new ContentInfoRecord();
contentInfoRecord.ContentIndexOffset = data.ReadUInt16();
contentInfoRecord.ContentCommandCount = data.ReadUInt16();
contentInfoRecord.UnhashedContentRecordsSHA256Hash = data.ReadBytes(0x20);
return contentInfoRecord;
return data.ReadType<ContentInfoRecord>();
}
/// <summary>
@@ -467,18 +455,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled content chunk record on success, null on error</returns>
private static ContentChunkRecord ParseContentChunkRecord(Stream data)
public static ContentChunkRecord? ParseContentChunkRecord(Stream data)
{
// TODO: Use marshalling here instead of building
ContentChunkRecord contentChunkRecord = new ContentChunkRecord();
contentChunkRecord.ContentId = data.ReadUInt32();
contentChunkRecord.ContentIndex = (ContentIndex)data.ReadUInt16();
contentChunkRecord.ContentType = (TMDContentType)data.ReadUInt16();
contentChunkRecord.ContentSize = data.ReadUInt64();
contentChunkRecord.SHA256Hash = data.ReadBytes(0x20);
return contentChunkRecord;
return data.ReadType<ContentChunkRecord>();
}
/// <summary>
@@ -486,18 +465,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled meta data on success, null on error</returns>
private static MetaData ParseMetaData(Stream data)
public static MetaData? ParseMetaData(Stream data)
{
// TODO: Use marshalling here instead of building
MetaData metaData = new MetaData();
metaData.TitleIDDependencyList = data.ReadBytes(0x180);
metaData.Reserved1 = data.ReadBytes(0x180);
metaData.CoreVersion = data.ReadUInt32();
metaData.Reserved2 = data.ReadBytes(0xFC);
metaData.IconData = data.ReadBytes(0x36C0);
return metaData;
return data.ReadType<MetaData>();
}
}
}

View File

@@ -58,6 +58,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < blockEntryHeader.BlockCount; i++)
{
var blockEntry = ParseBlockEntry(data);
if (blockEntry == null)
return null;
file.BlockEntries[i] = blockEntry;
}
@@ -84,6 +87,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < fragmentationMapHeader.BlockCount; i++)
{
var fragmentationMap = ParseFragmentationMap(data);
if (fragmentationMap == null)
return null;
file.FragmentationMaps[i] = fragmentationMap;
}
@@ -115,6 +121,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < file.BlockEntryMapHeader.BlockCount; i++)
{
var blockEntryMap = ParseBlockEntryMap(data);
if (blockEntryMap == null)
return null;
file.BlockEntryMaps[i] = blockEntryMap;
}
}
@@ -145,6 +154,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.ItemCount; i++)
{
var directoryEntry = ParseDirectoryEntry(data);
if (directoryEntry == null)
return null;
file.DirectoryEntries[i] = directoryEntry;
}
@@ -167,7 +179,7 @@ namespace SabreTools.Serialization.Deserializers
while (data.Position < directoryNamesEnd)
{
long nameOffset = data.Position - directoryNamesStart;
string? directoryName = data.ReadString(Encoding.ASCII);
string? directoryName = data.ReadNullTerminatedAnsiString();
if (data.Position > directoryNamesEnd)
{
data.Seek(-directoryName?.Length ?? 0, SeekOrigin.Current);
@@ -180,13 +192,6 @@ namespace SabreTools.Serialization.Deserializers
file.DirectoryNames[nameOffset] = directoryName;
}
// Loop and assign to entries
foreach (var directoryEntry in file.DirectoryEntries)
{
if (directoryEntry != null)
directoryEntry.Name = file.DirectoryNames[directoryEntry.NameOffset];
}
}
#endregion
@@ -200,6 +205,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.Info1Count; i++)
{
var directoryInfo1Entry = ParseDirectoryInfo1Entry(data);
if (directoryInfo1Entry == null)
return null;
file.DirectoryInfo1Entries[i] = directoryInfo1Entry;
}
@@ -214,6 +222,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.ItemCount; i++)
{
var directoryInfo2Entry = ParseDirectoryInfo2Entry(data);
if (directoryInfo2Entry == null)
return null;
file.DirectoryInfo2Entries[i] = directoryInfo2Entry;
}
@@ -228,6 +239,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.CopyCount; i++)
{
var directoryCopyEntry = ParseDirectoryCopyEntry(data);
if (directoryCopyEntry == null)
return null;
file.DirectoryCopyEntries[i] = directoryCopyEntry;
}
@@ -242,6 +256,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.LocalCount; i++)
{
var directoryLocalEntry = ParseDirectoryLocalEntry(data);
if (directoryLocalEntry == null)
return null;
file.DirectoryLocalEntries[i] = directoryLocalEntry;
}
@@ -274,6 +291,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.ItemCount; i++)
{
var directoryMapEntry = ParseDirectoryMapEntry(data);
if (directoryMapEntry == null)
return null;
file.DirectoryMapEntries[i] = directoryMapEntry;
}
@@ -315,6 +335,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < checksumMapHeader.ItemCount; i++)
{
var checksumMapEntry = ParseChecksumMapEntry(data);
if (checksumMapEntry == null)
return null;
file.ChecksumMapEntries[i] = checksumMapEntry;
}
@@ -329,6 +352,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < checksumMapHeader.ChecksumCount; i++)
{
var checksumEntry = ParseChecksumEntry(data);
if (checksumEntry == null)
return null;
file.ChecksumEntries[i] = checksumEntry;
}
@@ -359,30 +385,17 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life Game Cache on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
header.Dummy0 = data.ReadUInt32();
if (header == null)
return null;
if (header.Dummy0 != 0x00000001)
return null;
header.MajorVersion = data.ReadUInt32();
if (header.MajorVersion != 0x00000001)
return null;
header.MinorVersion = data.ReadUInt32();
if (header.MinorVersion != 3 && header.MinorVersion != 5 && header.MinorVersion != 6)
return null;
header.CacheID = data.ReadUInt32();
header.LastVersionPlayed = data.ReadUInt32();
header.Dummy1 = data.ReadUInt32();
header.Dummy2 = data.ReadUInt32();
header.FileSize = data.ReadUInt32();
header.BlockSize = data.ReadUInt32();
header.BlockCount = data.ReadUInt32();
header.Dummy3 = data.ReadUInt32();
return header;
}
@@ -391,21 +404,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache block entry header on success, null on error</returns>
private static BlockEntryHeader ParseBlockEntryHeader(Stream data)
private static BlockEntryHeader? ParseBlockEntryHeader(Stream data)
{
// TODO: Use marshalling here instead of building
BlockEntryHeader blockEntryHeader = new BlockEntryHeader();
blockEntryHeader.BlockCount = data.ReadUInt32();
blockEntryHeader.BlocksUsed = data.ReadUInt32();
blockEntryHeader.Dummy0 = data.ReadUInt32();
blockEntryHeader.Dummy1 = data.ReadUInt32();
blockEntryHeader.Dummy2 = data.ReadUInt32();
blockEntryHeader.Dummy3 = data.ReadUInt32();
blockEntryHeader.Dummy4 = data.ReadUInt32();
blockEntryHeader.Checksum = data.ReadUInt32();
return blockEntryHeader;
return data.ReadType<BlockEntryHeader>();
}
/// <summary>
@@ -413,20 +414,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache block entry on success, null on error</returns>
private static BlockEntry ParseBlockEntry(Stream data)
private static BlockEntry? ParseBlockEntry(Stream data)
{
// TODO: Use marshalling here instead of building
BlockEntry blockEntry = new BlockEntry();
blockEntry.EntryFlags = data.ReadUInt32();
blockEntry.FileDataOffset = data.ReadUInt32();
blockEntry.FileDataSize = data.ReadUInt32();
blockEntry.FirstDataBlockIndex = data.ReadUInt32();
blockEntry.NextBlockEntryIndex = data.ReadUInt32();
blockEntry.PreviousBlockEntryIndex = data.ReadUInt32();
blockEntry.DirectoryIndex = data.ReadUInt32();
return blockEntry;
return data.ReadType<BlockEntry>();
}
/// <summary>
@@ -434,17 +424,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache fragmentation map header on success, null on error</returns>
private static FragmentationMapHeader ParseFragmentationMapHeader(Stream data)
private static FragmentationMapHeader? ParseFragmentationMapHeader(Stream data)
{
// TODO: Use marshalling here instead of building
FragmentationMapHeader fragmentationMapHeader = new FragmentationMapHeader();
fragmentationMapHeader.BlockCount = data.ReadUInt32();
fragmentationMapHeader.FirstUnusedEntry = data.ReadUInt32();
fragmentationMapHeader.Terminator = data.ReadUInt32();
fragmentationMapHeader.Checksum = data.ReadUInt32();
return fragmentationMapHeader;
return data.ReadType<FragmentationMapHeader>();
}
/// <summary>
@@ -452,14 +434,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache fragmentation map on success, null on error</returns>
private static FragmentationMap ParseFragmentationMap(Stream data)
private static FragmentationMap? ParseFragmentationMap(Stream data)
{
// TODO: Use marshalling here instead of building
FragmentationMap fragmentationMap = new FragmentationMap();
fragmentationMap.NextDataBlockIndex = data.ReadUInt32();
return fragmentationMap;
return data.ReadType<FragmentationMap>();
}
/// <summary>
@@ -467,18 +444,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache block entry map header on success, null on error</returns>
private static BlockEntryMapHeader ParseBlockEntryMapHeader(Stream data)
private static BlockEntryMapHeader? ParseBlockEntryMapHeader(Stream data)
{
// TODO: Use marshalling here instead of building
BlockEntryMapHeader blockEntryMapHeader = new BlockEntryMapHeader();
blockEntryMapHeader.BlockCount = data.ReadUInt32();
blockEntryMapHeader.FirstBlockEntryIndex = data.ReadUInt32();
blockEntryMapHeader.LastBlockEntryIndex = data.ReadUInt32();
blockEntryMapHeader.Dummy0 = data.ReadUInt32();
blockEntryMapHeader.Checksum = data.ReadUInt32();
return blockEntryMapHeader;
return data.ReadType<BlockEntryMapHeader>();
}
/// <summary>
@@ -486,15 +454,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache block entry map on success, null on error</returns>
private static BlockEntryMap ParseBlockEntryMap(Stream data)
private static BlockEntryMap? ParseBlockEntryMap(Stream data)
{
// TODO: Use marshalling here instead of building
BlockEntryMap blockEntryMap = new BlockEntryMap();
blockEntryMap.PreviousBlockEntryIndex = data.ReadUInt32();
blockEntryMap.NextBlockEntryIndex = data.ReadUInt32();
return blockEntryMap;
return data.ReadType<BlockEntryMap>();
}
/// <summary>
@@ -502,27 +464,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache directory header on success, null on error</returns>
private static DirectoryHeader ParseDirectoryHeader(Stream data)
private static DirectoryHeader? ParseDirectoryHeader(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryHeader directoryHeader = new DirectoryHeader();
directoryHeader.Dummy0 = data.ReadUInt32();
directoryHeader.CacheID = data.ReadUInt32();
directoryHeader.LastVersionPlayed = data.ReadUInt32();
directoryHeader.ItemCount = data.ReadUInt32();
directoryHeader.FileCount = data.ReadUInt32();
directoryHeader.Dummy1 = data.ReadUInt32();
directoryHeader.DirectorySize = data.ReadUInt32();
directoryHeader.NameSize = data.ReadUInt32();
directoryHeader.Info1Count = data.ReadUInt32();
directoryHeader.CopyCount = data.ReadUInt32();
directoryHeader.LocalCount = data.ReadUInt32();
directoryHeader.Dummy2 = data.ReadUInt32();
directoryHeader.Dummy3 = data.ReadUInt32();
directoryHeader.Checksum = data.ReadUInt32();
return directoryHeader;
return data.ReadType<DirectoryHeader>();
}
/// <summary>
@@ -530,20 +474,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache directory entry on success, null on error</returns>
private static DirectoryEntry ParseDirectoryEntry(Stream data)
private static DirectoryEntry? ParseDirectoryEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryEntry directoryEntry = new DirectoryEntry();
directoryEntry.NameOffset = data.ReadUInt32();
directoryEntry.ItemSize = data.ReadUInt32();
directoryEntry.ChecksumIndex = data.ReadUInt32();
directoryEntry.DirectoryFlags = (HL_GCF_FLAG)data.ReadUInt32();
directoryEntry.ParentIndex = data.ReadUInt32();
directoryEntry.NextIndex = data.ReadUInt32();
directoryEntry.FirstIndex = data.ReadUInt32();
return directoryEntry;
return data.ReadType<DirectoryEntry>();
}
/// <summary>
@@ -551,14 +484,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache directory info 1 entry on success, null on error</returns>
private static DirectoryInfo1Entry ParseDirectoryInfo1Entry(Stream data)
private static DirectoryInfo1Entry? ParseDirectoryInfo1Entry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryInfo1Entry directoryInfo1Entry = new DirectoryInfo1Entry();
directoryInfo1Entry.Dummy0 = data.ReadUInt32();
return directoryInfo1Entry;
return data.ReadType<DirectoryInfo1Entry>();
}
/// <summary>
@@ -566,14 +494,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache directory info 2 entry on success, null on error</returns>
private static DirectoryInfo2Entry ParseDirectoryInfo2Entry(Stream data)
private static DirectoryInfo2Entry? ParseDirectoryInfo2Entry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryInfo2Entry directoryInfo2Entry = new DirectoryInfo2Entry();
directoryInfo2Entry.Dummy0 = data.ReadUInt32();
return directoryInfo2Entry;
return data.ReadType<DirectoryInfo2Entry>();
}
/// <summary>
@@ -581,14 +504,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache directory copy entry on success, null on error</returns>
private static DirectoryCopyEntry ParseDirectoryCopyEntry(Stream data)
private static DirectoryCopyEntry? ParseDirectoryCopyEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryCopyEntry directoryCopyEntry = new DirectoryCopyEntry();
directoryCopyEntry.DirectoryIndex = data.ReadUInt32();
return directoryCopyEntry;
return data.ReadType<DirectoryCopyEntry>();
}
/// <summary>
@@ -596,14 +514,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache directory local entry on success, null on error</returns>
private static DirectoryLocalEntry ParseDirectoryLocalEntry(Stream data)
private static DirectoryLocalEntry? ParseDirectoryLocalEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryLocalEntry directoryLocalEntry = new DirectoryLocalEntry();
directoryLocalEntry.DirectoryIndex = data.ReadUInt32();
return directoryLocalEntry;
return data.ReadType<DirectoryLocalEntry>();
}
/// <summary>
@@ -613,14 +526,12 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life Game Cache directory map header on success, null on error</returns>
private static DirectoryMapHeader? ParseDirectoryMapHeader(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryMapHeader directoryMapHeader = new DirectoryMapHeader();
var directoryMapHeader = data.ReadType<DirectoryMapHeader>();
directoryMapHeader.Dummy0 = data.ReadUInt32();
if (directoryMapHeader == null)
return null;
if (directoryMapHeader.Dummy0 != 0x00000001)
return null;
directoryMapHeader.Dummy1 = data.ReadUInt32();
if (directoryMapHeader.Dummy1 != 0x00000000)
return null;
@@ -632,14 +543,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache directory map entry on success, null on error</returns>
private static DirectoryMapEntry ParseDirectoryMapEntry(Stream data)
private static DirectoryMapEntry? ParseDirectoryMapEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryMapEntry directoryMapEntry = new DirectoryMapEntry();
directoryMapEntry.FirstBlockIndex = data.ReadUInt32();
return directoryMapEntry;
return data.ReadType<DirectoryMapEntry>();
}
/// <summary>
@@ -649,15 +555,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life Game Cache checksum header on success, null on error</returns>
private static ChecksumHeader? ParseChecksumHeader(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumHeader checksumHeader = new ChecksumHeader();
var checksumHeader = data.ReadType<ChecksumHeader>();
checksumHeader.Dummy0 = data.ReadUInt32();
if (checksumHeader == null)
return null;
if (checksumHeader.Dummy0 != 0x00000001)
return null;
checksumHeader.ChecksumSize = data.ReadUInt32();
return checksumHeader;
}
@@ -668,20 +572,15 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life Game Cache checksum map header on success, null on error</returns>
private static ChecksumMapHeader? ParseChecksumMapHeader(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumMapHeader checksumMapHeader = new ChecksumMapHeader();
var checksumMapHeader = data.ReadType<ChecksumMapHeader>();
checksumMapHeader.Dummy0 = data.ReadUInt32();
if (checksumMapHeader == null)
return null;
if (checksumMapHeader.Dummy0 != 0x14893721)
return null;
checksumMapHeader.Dummy1 = data.ReadUInt32();
if (checksumMapHeader.Dummy1 != 0x00000001)
return null;
checksumMapHeader.ItemCount = data.ReadUInt32();
checksumMapHeader.ChecksumCount = data.ReadUInt32();
return checksumMapHeader;
}
@@ -690,15 +589,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache checksum map entry on success, null on error</returns>
private static ChecksumMapEntry ParseChecksumMapEntry(Stream data)
private static ChecksumMapEntry? ParseChecksumMapEntry(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumMapEntry checksumMapEntry = new ChecksumMapEntry();
checksumMapEntry.ChecksumCount = data.ReadUInt32();
checksumMapEntry.FirstChecksumIndex = data.ReadUInt32();
return checksumMapEntry;
return data.ReadType<ChecksumMapEntry>();
}
/// <summary>
@@ -706,14 +599,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Game Cache checksum entry on success, null on error</returns>
private static ChecksumEntry ParseChecksumEntry(Stream data)
private static ChecksumEntry? ParseChecksumEntry(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumEntry checksumEntry = new ChecksumEntry();
checksumEntry.Checksum = data.ReadUInt32();
return checksumEntry;
return data.ReadType<ChecksumEntry>();
}
/// <summary>
@@ -722,10 +610,10 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="minorVersion">Minor version field from the header</param>
/// <returns>Filled Half-Life Game Cache data block header on success, null on error</returns>
private static DataBlockHeader ParseDataBlockHeader(Stream data, uint minorVersion)
private static DataBlockHeader? ParseDataBlockHeader(Stream data, uint minorVersion)
{
// TODO: Use marshalling here instead of building
DataBlockHeader dataBlockHeader = new DataBlockHeader();
var dataBlockHeader = new DataBlockHeader();
// In version 3 the DataBlockHeader is missing the LastVersionPlayed field.
if (minorVersion >= 5)

View File

@@ -20,7 +20,7 @@ namespace SabreTools.Serialization.Deserializers
// Cache the current offset
int initialOffset = (int)data.Position;
// Create a new media key block to fill
// Create a new IRD to fill
var ird = new Models.IRD.File();
ird.Magic = data.ReadBytes(4);

View File

@@ -0,0 +1,130 @@
using System.Collections.Generic;
using System.IO;
using SabreTools.IO.Extensions;
using SabreTools.Models.InstallShieldArchiveV3;
namespace SabreTools.Serialization.Deserializers
{
public class InstallShieldArchiveV3 : BaseBinaryDeserializer<Archive>
{
public override Archive? Deserialize(Stream? data)
{
// If the data is invalid
if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead)
return null;
// If the offset is out of bounds
if (data.Position < 0 || data.Position >= data.Length)
return null;
// Cache the current offset
int initialOffset = (int)data.Position;
// Create a new archive to fill
var archive = new Archive();
#region Header
// Try to parse the header
var header = ParseHeader(data);
if (header == null)
return null;
// Set the archive header
archive.Header = header;
#endregion
#region Directories
// Get the directories offset
uint directoriesOffset = header.TocAddress;
if (directoriesOffset < 0 || directoriesOffset >= data.Length)
return null;
// Seek to the directories
data.Seek(directoriesOffset, SeekOrigin.Begin);
// Try to parse the directories
var directories = new List<Models.InstallShieldArchiveV3.Directory>();
for (int i = 0; i < header.DirCount; i++)
{
var directory = ParseDirectory(data);
if (directory?.Name == null)
return null;
directories.Add(directory);
data.Seek(directory.ChunkSize - directory.Name.Length - 6, SeekOrigin.Current);
}
// Set the directories
archive.Directories = [.. directories];
#endregion
#region Files
// Try to parse the files
var files = new List<Models.InstallShieldArchiveV3.File>();
for (int i = 0; i < archive.Directories.Length; i++)
{
var directory = archive.Directories[i];
for (int j = 0; j < directory.FileCount; j++)
{
var file = ParseFile(data);
if (file?.Name == null)
return null;
files.Add(file);
data.Seek(file.ChunkSize - file.Name.Length - 30, SeekOrigin.Current);
}
}
// Set the files
archive.Files = [.. files];
#endregion
return archive;
}
/// <summary>
/// Parse a Stream into a header
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled header on success, null on error</returns>
public static Header? ParseHeader(Stream data)
{
var header = data.ReadType<Header>();
if (header == null)
return null;
if (header.Signature1 != 0x8C655D13) // TODO: Move constant to Models
return null;
if (header.TocAddress >= data.Length)
return null;
return header;
}
/// <summary>
/// Parse a Stream into a directory
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled directory on success, null on error</returns>
public static Models.InstallShieldArchiveV3.Directory? ParseDirectory(Stream data)
{
return data.ReadType<Models.InstallShieldArchiveV3.Directory>();
}
/// <summary>
/// Parse a Stream into a file
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled file on success, null on error</returns>
public static Models.InstallShieldArchiveV3.File? ParseFile(Stream data)
{
return data.ReadType<Models.InstallShieldArchiveV3.File>();
}
}
}

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using SabreTools.IO.Extensions;
using SabreTools.Models.InstallShieldCabinet;
using static SabreTools.Models.InstallShieldCabinet.Constants;
@@ -333,23 +332,15 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled common header on success, null on error</returns>
private static CommonHeader? ParseCommonHeader(Stream data)
public static CommonHeader? ParseCommonHeader(Stream data)
{
CommonHeader commonHeader = new CommonHeader();
var commonHeader = data.ReadType<CommonHeader>();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
if (commonHeader == null)
return null;
commonHeader.Signature = Encoding.ASCII.GetString(signature);
if (commonHeader.Signature != SignatureString)
return null;
commonHeader.Version = data.ReadUInt32();
commonHeader.VolumeInfo = data.ReadUInt32();
commonHeader.DescriptorOffset = data.ReadUInt32();
commonHeader.DescriptorSize = data.ReadUInt32();
return commonHeader;
}
@@ -359,7 +350,7 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="majorVersion">Major version of the cabinet</param>
/// <returns>Filled volume header on success, null on error</returns>
private static VolumeHeader ParseVolumeHeader(Stream data, int majorVersion)
public static VolumeHeader ParseVolumeHeader(Stream data, int majorVersion)
{
VolumeHeader volumeHeader = new VolumeHeader();
@@ -406,46 +397,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled descriptor on success, null on error</returns>
private static Descriptor ParseDescriptor(Stream data)
public static Descriptor? ParseDescriptor(Stream data)
{
Descriptor descriptor = new Descriptor();
descriptor.StringsOffset = data.ReadUInt32();
descriptor.Reserved0 = data.ReadBytes(4);
descriptor.ComponentListOffset = data.ReadUInt32();
descriptor.FileTableOffset = data.ReadUInt32();
descriptor.Reserved1 = data.ReadBytes(4);
descriptor.FileTableSize = data.ReadUInt32();
descriptor.FileTableSize2 = data.ReadUInt32();
descriptor.DirectoryCount = data.ReadUInt16();
descriptor.Reserved2 = data.ReadBytes(4);
descriptor.Reserved3 = data.ReadBytes(2);
descriptor.Reserved4 = data.ReadBytes(4);
descriptor.FileCount = data.ReadUInt32();
descriptor.FileTableOffset2 = data.ReadUInt32();
descriptor.ComponentTableInfoCount = data.ReadUInt16();
descriptor.ComponentTableOffset = data.ReadUInt32();
descriptor.Reserved5 = data.ReadBytes(4);
descriptor.Reserved6 = data.ReadBytes(4);
descriptor.FileGroupOffsets = new uint[MAX_FILE_GROUP_COUNT];
for (int i = 0; i < descriptor.FileGroupOffsets.Length; i++)
{
descriptor.FileGroupOffsets[i] = data.ReadUInt32();
}
descriptor.ComponentOffsets = new uint[MAX_COMPONENT_COUNT];
for (int i = 0; i < descriptor.ComponentOffsets.Length; i++)
{
descriptor.ComponentOffsets[i] = data.ReadUInt32();
}
descriptor.SetupTypesOffset = data.ReadUInt32();
descriptor.SetupTableOffset = data.ReadUInt32();
descriptor.Reserved7 = data.ReadBytes(4);
descriptor.Reserved8 = data.ReadBytes(4);
return descriptor;
return data.ReadType<Descriptor>();
}
/// <summary>
@@ -455,9 +409,9 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="majorVersion">Major version of the cabinet</param>
/// <param name="descriptorOffset">Offset of the cabinet descriptor</param>
/// <returns>Filled offset list on success, null on error</returns>
private static OffsetList ParseOffsetList(Stream data, int majorVersion, uint descriptorOffset)
public static OffsetList ParseOffsetList(Stream data, int majorVersion, uint descriptorOffset)
{
OffsetList offsetList = new OffsetList();
var offsetList = new OffsetList();
offsetList.NameOffset = data.ReadUInt32();
offsetList.DescriptorOffset = data.ReadUInt32();
@@ -471,9 +425,9 @@ namespace SabreTools.Serialization.Deserializers
// Read the string
if (majorVersion >= 17)
offsetList.Name = data.ReadString(Encoding.Unicode);
offsetList.Name = data.ReadNullTerminatedUnicodeString();
else
offsetList.Name = data.ReadString(Encoding.ASCII);
offsetList.Name = data.ReadNullTerminatedAnsiString();
// Seek back to the correct offset
data.Seek(currentOffset, SeekOrigin.Begin);
@@ -488,9 +442,9 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="majorVersion">Major version of the cabinet</param>
/// <param name="descriptorOffset">Offset of the cabinet descriptor</param>
/// <returns>Filled file group on success, null on error</returns>
private static FileGroup ParseFileGroup(Stream data, int majorVersion, uint descriptorOffset)
public static FileGroup ParseFileGroup(Stream data, int majorVersion, uint descriptorOffset)
{
FileGroup fileGroup = new FileGroup();
var fileGroup = new FileGroup();
fileGroup.NameOffset = data.ReadUInt32();
@@ -533,9 +487,9 @@ namespace SabreTools.Serialization.Deserializers
// Read the string
if (majorVersion >= 17)
fileGroup.Name = data.ReadString(Encoding.Unicode);
fileGroup.Name = data.ReadNullTerminatedUnicodeString();
else
fileGroup.Name = data.ReadString(Encoding.ASCII);
fileGroup.Name = data.ReadNullTerminatedUnicodeString();
}
// Seek back to the correct offset
@@ -551,14 +505,14 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="majorVersion">Major version of the cabinet</param>
/// <param name="descriptorOffset">Offset of the cabinet descriptor</param>
/// <returns>Filled component on success, null on error</returns>
private static Component ParseComponent(Stream data, int majorVersion, uint descriptorOffset)
public static Component ParseComponent(Stream data, int majorVersion, uint descriptorOffset)
{
Component component = new Component();
var component = new Component();
component.IdentifierOffset = data.ReadUInt32();
component.DescriptorOffset = data.ReadUInt32();
component.DisplayNameOffset = data.ReadUInt32();
component.Reserved0 = data.ReadBytes(2);
component.Reserved0 = data.ReadUInt16();
component.ReservedOffset0 = data.ReadUInt32();
component.ReservedOffset1 = data.ReadUInt32();
component.ComponentIndex = data.ReadUInt16();
@@ -595,9 +549,9 @@ namespace SabreTools.Serialization.Deserializers
// Read the string
if (majorVersion >= 17)
component.Identifier = data.ReadString(Encoding.Unicode);
component.Identifier = data.ReadNullTerminatedUnicodeString();
else
component.Identifier = data.ReadString(Encoding.ASCII);
component.Identifier = data.ReadNullTerminatedAnsiString();
}
// Read the display name, if possible
@@ -608,9 +562,9 @@ namespace SabreTools.Serialization.Deserializers
// Read the string
if (majorVersion >= 17)
component.DisplayName = data.ReadString(Encoding.Unicode);
component.DisplayName = data.ReadNullTerminatedUnicodeString();
else
component.DisplayName = data.ReadString(Encoding.ASCII);
component.DisplayName = data.ReadNullTerminatedAnsiString();
}
// Read the name, if possible
@@ -621,9 +575,9 @@ namespace SabreTools.Serialization.Deserializers
// Read the string
if (majorVersion >= 17)
component.Name = data.ReadString(Encoding.Unicode);
component.Name = data.ReadNullTerminatedUnicodeString();
else
component.Name = data.ReadString(Encoding.ASCII);
component.Name = data.ReadNullTerminatedAnsiString();
}
// Read the CLSID, if possible
@@ -656,9 +610,9 @@ namespace SabreTools.Serialization.Deserializers
data.Seek(nameOffset + descriptorOffset, SeekOrigin.Begin);
if (majorVersion >= 17)
component.FileGroupNames[j] = data.ReadString(Encoding.Unicode) ?? string.Empty;
component.FileGroupNames[j] = data.ReadNullTerminatedUnicodeString() ?? string.Empty;
else
component.FileGroupNames[j] = data.ReadString(Encoding.ASCII) ?? string.Empty;
component.FileGroupNames[j] = data.ReadNullTerminatedAnsiString() ?? string.Empty;
// Seek back to the original position
data.Seek(preNameOffset, SeekOrigin.Begin);
@@ -677,13 +631,13 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="majorVersion">Major version of the cabinet</param>
/// <returns>Filled directory name on success, null on error</returns>
private static string? ParseDirectoryName(Stream data, int majorVersion)
public static string? ParseDirectoryName(Stream data, int majorVersion)
{
// Read the string
if (majorVersion >= 17)
return data.ReadString(Encoding.Unicode);
return data.ReadNullTerminatedUnicodeString();
else
return data.ReadString(Encoding.ASCII);
return data.ReadNullTerminatedAnsiString();
}
/// <summary>
@@ -693,7 +647,7 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="majorVersion">Major version of the cabinet</param>
/// <param name="descriptorOffset">Offset of the cabinet descriptor</param>
/// <returns>Filled file descriptor on success, null on error</returns>
private static FileDescriptor ParseFileDescriptor(Stream data, int majorVersion, uint descriptorOffset)
public static FileDescriptor ParseFileDescriptor(Stream data, int majorVersion, uint descriptorOffset)
{
FileDescriptor fileDescriptor = new FileDescriptor();
@@ -740,9 +694,9 @@ namespace SabreTools.Serialization.Deserializers
// Read the string
if (majorVersion >= 17)
fileDescriptor.Name = data.ReadString(Encoding.Unicode);
fileDescriptor.Name = data.ReadNullTerminatedUnicodeString();
else
fileDescriptor.Name = data.ReadString(Encoding.ASCII);
fileDescriptor.Name = data.ReadNullTerminatedAnsiString();
}
// Seek back to the correct offset
@@ -757,7 +711,7 @@ namespace SabreTools.Serialization.Deserializers
/// Get the major version of the cabinet
/// </summary>
/// <remarks>This should live in the wrapper but is needed during parsing</remarks>
private static int GetMajorVersion(CommonHeader commonHeader)
public static int GetMajorVersion(CommonHeader commonHeader)
{
uint majorVersion = commonHeader.Version;
if (majorVersion >> 24 == 1)

View File

@@ -425,63 +425,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled information block on success, null on error</returns>
public static InformationBlock? ParseInformationBlock(Stream data)
{
// TODO: Use marshalling here instead of building
var informationBlock = new InformationBlock();
var informationBlock = data.ReadType<InformationBlock>();
byte[]? magic = data.ReadBytes(2);
if (magic == null)
if (informationBlock == null)
return null;
informationBlock.Signature = Encoding.ASCII.GetString(magic);
if (informationBlock.Signature != LESignatureString && informationBlock.Signature != LXSignatureString)
return null;
informationBlock.ByteOrder = (ByteOrder)data.ReadByteValue();
informationBlock.WordOrder = (WordOrder)data.ReadByteValue();
informationBlock.ExecutableFormatLevel = data.ReadUInt32();
informationBlock.CPUType = (CPUType)data.ReadUInt16();
informationBlock.ModuleOS = (OperatingSystem)data.ReadUInt16();
informationBlock.ModuleVersion = data.ReadUInt32();
informationBlock.ModuleTypeFlags = (ModuleFlags)data.ReadUInt32();
informationBlock.ModuleNumberPages = data.ReadUInt32();
informationBlock.InitialObjectCS = data.ReadUInt32();
informationBlock.InitialEIP = data.ReadUInt32();
informationBlock.InitialObjectSS = data.ReadUInt32();
informationBlock.InitialESP = data.ReadUInt32();
informationBlock.MemoryPageSize = data.ReadUInt32();
informationBlock.BytesOnLastPage = data.ReadUInt32();
informationBlock.FixupSectionSize = data.ReadUInt32();
informationBlock.FixupSectionChecksum = data.ReadUInt32();
informationBlock.LoaderSectionSize = data.ReadUInt32();
informationBlock.LoaderSectionChecksum = data.ReadUInt32();
informationBlock.ObjectTableOffset = data.ReadUInt32();
informationBlock.ObjectTableCount = data.ReadUInt32();
informationBlock.ObjectPageMapOffset = data.ReadUInt32();
informationBlock.ObjectIterateDataMapOffset = data.ReadUInt32();
informationBlock.ResourceTableOffset = data.ReadUInt32();
informationBlock.ResourceTableCount = data.ReadUInt32();
informationBlock.ResidentNamesTableOffset = data.ReadUInt32();
informationBlock.EntryTableOffset = data.ReadUInt32();
informationBlock.ModuleDirectivesTableOffset = data.ReadUInt32();
informationBlock.ModuleDirectivesCount = data.ReadUInt32();
informationBlock.FixupPageTableOffset = data.ReadUInt32();
informationBlock.FixupRecordTableOffset = data.ReadUInt32();
informationBlock.ImportedModulesNameTableOffset = data.ReadUInt32();
informationBlock.ImportedModulesCount = data.ReadUInt32();
informationBlock.ImportProcedureNameTableOffset = data.ReadUInt32();
informationBlock.PerPageChecksumTableOffset = data.ReadUInt32();
informationBlock.DataPagesOffset = data.ReadUInt32();
informationBlock.PreloadPageCount = data.ReadUInt32();
informationBlock.NonResidentNamesTableOffset = data.ReadUInt32();
informationBlock.NonResidentNamesTableLength = data.ReadUInt32();
informationBlock.NonResidentNamesTableChecksum = data.ReadUInt32();
informationBlock.AutomaticDataObject = data.ReadUInt32();
informationBlock.DebugInformationOffset = data.ReadUInt32();
informationBlock.DebugInformationLength = data.ReadUInt32();
informationBlock.PreloadInstancePagesNumber = data.ReadUInt32();
informationBlock.DemandInstancePagesNumber = data.ReadUInt32();
informationBlock.ExtraHeapAllocation = data.ReadUInt32();
return informationBlock;
}
@@ -490,19 +440,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled object table entry on success, null on error</returns>
public static ObjectTableEntry ParseObjectTableEntry(Stream data)
public static ObjectTableEntry? ParseObjectTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new ObjectTableEntry();
entry.VirtualSegmentSize = data.ReadUInt32();
entry.RelocationBaseAddress = data.ReadUInt32();
entry.ObjectFlags = (ObjectFlags)data.ReadUInt16();
entry.PageTableIndex = data.ReadUInt32();
entry.PageTableEntries = data.ReadUInt32();
entry.Reserved = data.ReadUInt32();
return entry;
return data.ReadType<ObjectTableEntry>();
}
/// <summary>
@@ -510,16 +450,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled object page map entry on success, null on error</returns>
public static ObjectPageMapEntry ParseObjectPageMapEntry(Stream data)
public static ObjectPageMapEntry? ParseObjectPageMapEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new ObjectPageMapEntry();
entry.PageDataOffset = data.ReadUInt32();
entry.DataSize = data.ReadUInt16();
entry.Flags = (ObjectPageFlags)data.ReadUInt16();
return entry;
return data.ReadType<ObjectPageMapEntry>();
}
/// <summary>
@@ -527,18 +460,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled resource table entry on success, null on error</returns>
public static ResourceTableEntry ParseResourceTableEntry(Stream data)
public static ResourceTableEntry? ParseResourceTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new ResourceTableEntry();
entry.TypeID = (ResourceTableEntryType)data.ReadUInt32();
entry.NameID = data.ReadUInt16();
entry.ResourceSize = data.ReadUInt32();
entry.ObjectNumber = data.ReadUInt16();
entry.Offset = data.ReadUInt32();
return entry;
return data.ReadType<ResourceTableEntry>();
}
/// <summary>
@@ -552,7 +476,7 @@ namespace SabreTools.Serialization.Deserializers
var entry = new ResidentNamesTableEntry();
entry.Length = data.ReadByteValue();
if (entry.Length > 0)
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
{
byte[]? name = data.ReadBytes(entry.Length);
if (name != null)
@@ -631,16 +555,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled module format directives table entry on success, null on error</returns>
public static ModuleFormatDirectivesTableEntry ParseModuleFormatDirectivesTableEntry(Stream data)
public static ModuleFormatDirectivesTableEntry? ParseModuleFormatDirectivesTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new ModuleFormatDirectivesTableEntry();
entry.DirectiveNumber = (DirectiveNumber)data.ReadUInt16();
entry.DirectiveDataLength = data.ReadUInt16();
entry.DirectiveDataOffset = data.ReadUInt32();
return entry;
return data.ReadType<ModuleFormatDirectivesTableEntry>();
}
/// <summary>
@@ -648,20 +565,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled verify record directive table entry on success, null on error</returns>
public static VerifyRecordDirectiveTableEntry ParseVerifyRecordDirectiveTableEntry(Stream data)
public static VerifyRecordDirectiveTableEntry? ParseVerifyRecordDirectiveTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new VerifyRecordDirectiveTableEntry();
entry.EntryCount = data.ReadUInt16();
entry.OrdinalIndex = data.ReadUInt16();
entry.Version = data.ReadUInt16();
entry.ObjectEntriesCount = data.ReadUInt16();
entry.ObjectNumberInModule = data.ReadUInt16();
entry.ObjectLoadBaseAddress = data.ReadUInt16();
entry.ObjectVirtualAddressSize = data.ReadUInt16();
return entry;
return data.ReadType<VerifyRecordDirectiveTableEntry>();
}
/// <summary>
@@ -669,14 +575,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled fix-up page table entry on success, null on error</returns>
public static FixupPageTableEntry ParseFixupPageTableEntry(Stream data)
public static FixupPageTableEntry? ParseFixupPageTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new FixupPageTableEntry();
entry.Offset = data.ReadUInt32();
return entry;
return data.ReadType<FixupPageTableEntry>();
}
/// <summary>
@@ -909,7 +810,7 @@ namespace SabreTools.Serialization.Deserializers
var entry = new ImportModuleNameTableEntry();
entry.Length = data.ReadByteValue();
if (entry.Length > 0)
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
{
byte[]? name = data.ReadBytes(entry.Length);
if (name != null)
@@ -930,7 +831,7 @@ namespace SabreTools.Serialization.Deserializers
var entry = new ImportModuleProcedureNameTableEntry();
entry.Length = data.ReadByteValue();
if (entry.Length > 0)
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
{
byte[]? name = data.ReadBytes(entry.Length);
if (name != null)
@@ -945,14 +846,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled per-page checksum table entry on success, null on error</returns>
public static PerPageChecksumTableEntry ParsePerPageChecksumTableEntry(Stream data)
public static PerPageChecksumTableEntry? ParsePerPageChecksumTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new PerPageChecksumTableEntry();
entry.Checksum = data.ReadUInt32();
return entry;
return data.ReadType<PerPageChecksumTableEntry>();
}
/// <summary>
@@ -966,7 +862,7 @@ namespace SabreTools.Serialization.Deserializers
var entry = new NonResidentNamesTableEntry();
entry.Length = data.ReadByteValue();
if (entry.Length > 0)
if (entry.Length > 0 && data.Position + entry.Length <= data.Length)
{
byte[]? name = data.ReadBytes(entry.Length);
if (name != null)

View File

@@ -126,20 +126,31 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="count">Number of relocation table entries to read</param>
/// <returns>Filled relocation table on success, null on error</returns>
private static RelocationEntry[] ParseRelocationTable(Stream data, int count)
private static RelocationEntry[]? ParseRelocationTable(Stream data, int count)
{
// TODO: Use marshalling here instead of building
var relocationTable = new RelocationEntry[count];
for (int i = 0; i < count; i++)
{
var entry = new RelocationEntry();
entry.Offset = data.ReadUInt16();
entry.Segment = data.ReadUInt16();
var entry = ParseRelocationEntry(data);
if (entry == null)
return null;
relocationTable[i] = entry;
}
return relocationTable;
}
/// <summary>
/// Parse a Stream into a relocation table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled relocation table entry on success, null on error</returns>
public static RelocationEntry? ParseRelocationEntry(Stream data)
{
return data.ReadType<RelocationEntry>();
}
}
}

View File

@@ -138,8 +138,8 @@ namespace SabreTools.Serialization.Deserializers
if (header.Flags.HasFlag(HeaderFlags.PREV_CABINET))
#endif
{
header.CabinetPrev = data.ReadString(Encoding.ASCII);
header.DiskPrev = data.ReadString(Encoding.ASCII);
header.CabinetPrev = data.ReadNullTerminatedAnsiString();
header.DiskPrev = data.ReadNullTerminatedAnsiString();
}
#if NET20 || NET35
@@ -148,8 +148,8 @@ namespace SabreTools.Serialization.Deserializers
if (header.Flags.HasFlag(HeaderFlags.NEXT_CABINET))
#endif
{
header.CabinetNext = data.ReadString(Encoding.ASCII);
header.DiskNext = data.ReadString(Encoding.ASCII);
header.CabinetNext = data.ReadNullTerminatedAnsiString();
header.DiskNext = data.ReadNullTerminatedAnsiString();
}
return header;
@@ -234,9 +234,9 @@ namespace SabreTools.Serialization.Deserializers
#else
if (file.Attributes.HasFlag(Models.MicrosoftCabinet.FileAttributes.NAME_IS_UTF))
#endif
file.Name = data.ReadString(Encoding.Unicode);
file.Name = data.ReadNullTerminatedUnicodeString();
else
file.Name = data.ReadString(Encoding.ASCII);
file.Name = data.ReadNullTerminatedAnsiString();
return file;
}

View File

@@ -404,20 +404,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled user data on success, null on error</returns>
private static UserData? ParseUserData(Stream data)
{
UserData userData = new UserData();
var userData = data.ReadType<UserData>();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
if (userData == null)
return null;
userData.Signature = Encoding.ASCII.GetString(signature);
if (userData.Signature != UserDataSignatureString)
return null;
userData.UserDataSize = data.ReadUInt32();
userData.HeaderOffset = data.ReadUInt32();
userData.UserDataHeaderSize = data.ReadUInt32();
return userData;
}
@@ -428,7 +421,7 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled HET table on success, null on error</returns>
private static HetTable? ParseHetTable(Stream data)
{
HetTable hetTable = new HetTable();
var hetTable = new HetTable();
// Common Headers
byte[]? signature = data.ReadBytes(4);
@@ -465,7 +458,7 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled BET table on success, null on error</returns>
private static BetTable? ParseBetTable(Stream data)
{
BetTable betTable = new BetTable();
var betTable = new BetTable();
// Common Headers
byte[]? signature = data.ReadBytes(4);
@@ -519,18 +512,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled hash entry on success, null on error</returns>
private static HashEntry ParseHashEntry(Stream data)
private static HashEntry? ParseHashEntry(Stream data)
{
// TODO: Use marshalling here instead of building
HashEntry hashEntry = new HashEntry();
hashEntry.NameHashPartA = data.ReadUInt32();
hashEntry.NameHashPartB = data.ReadUInt32();
hashEntry.Locale = (Locale)data.ReadUInt16();
hashEntry.Platform = data.ReadUInt16();
hashEntry.BlockIndex = data.ReadUInt32();
return hashEntry;
return data.ReadType<HashEntry>();
}
/// <summary>
@@ -538,16 +522,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled block entry on success, null on error</returns>
private static BlockEntry ParseBlockEntry(Stream data)
private static BlockEntry? ParseBlockEntry(Stream data)
{
BlockEntry blockEntry = new BlockEntry();
blockEntry.FilePosition = data.ReadUInt32();
blockEntry.CompressedSize = data.ReadUInt32();
blockEntry.UncompressedSize = data.ReadUInt32();
blockEntry.Flags = (FileFlags)data.ReadUInt32();
return blockEntry;
return data.ReadType<BlockEntry>();
}
/// <summary>
@@ -555,19 +532,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled patch info on success, null on error</returns>
private static PatchInfo ParsePatchInfo(Stream data)
private static PatchInfo? ParsePatchInfo(Stream data)
{
// TODO: Use marshalling here instead of building
PatchInfo patchInfo = new PatchInfo();
patchInfo.Length = data.ReadUInt32();
patchInfo.Flags = data.ReadUInt32();
patchInfo.DataSize = data.ReadUInt32();
patchInfo.MD5 = data.ReadBytes(0x10);
// TODO: Fill the sector offset table
return patchInfo;
return data.ReadType<PatchInfo>();
}
#region Helpers

View File

@@ -137,7 +137,11 @@ namespace SabreTools.Serialization.Deserializers
data.Seek(offset, SeekOrigin.Begin);
// Parse the ExeFS header
cart.ExeFSHeaders[i] = ParseExeFSHeader(data);
var exeFsHeader = ParseExeFSHeader(data);
if (exeFsHeader == null)
return null;
cart.ExeFSHeaders[i] = exeFsHeader;
}
#endregion
@@ -182,7 +186,7 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled NCSD header on success, null on error</returns>
private static NCSDHeader? ParseNCSDHeader(Stream data)
public static NCSDHeader? ParseNCSDHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var header = new NCSDHeader();
@@ -204,7 +208,11 @@ namespace SabreTools.Serialization.Deserializers
header.PartitionsTable = new PartitionTableEntry[8];
for (int i = 0; i < 8; i++)
{
header.PartitionsTable[i] = ParsePartitionTableEntry(data);
var partitionTableEntry = ParsePartitionTableEntry(data);
if (partitionTableEntry == null)
return null;
header.PartitionsTable[i] = partitionTableEntry;
}
if (header.PartitionsFSType == FilesystemType.Normal || header.PartitionsFSType == FilesystemType.None)
@@ -239,15 +247,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled partition table entry on success, null on error</returns>
private static PartitionTableEntry ParsePartitionTableEntry(Stream data)
public static PartitionTableEntry? ParsePartitionTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var partitionTableEntry = new PartitionTableEntry();
partitionTableEntry.Offset = data.ReadUInt32();
partitionTableEntry.Length = data.ReadUInt32();
return partitionTableEntry;
return data.ReadType<PartitionTableEntry>();
}
/// <summary>
@@ -255,24 +257,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled card info header on success, null on error</returns>
private static CardInfoHeader ParseCardInfoHeader(Stream data)
public static CardInfoHeader? ParseCardInfoHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var cardInfoHeader = new CardInfoHeader();
cardInfoHeader.WritableAddressMediaUnits = data.ReadUInt32();
cardInfoHeader.CardInfoBitmask = data.ReadUInt32();
cardInfoHeader.Reserved1 = data.ReadBytes(0xF8);
cardInfoHeader.FilledSize = data.ReadUInt32();
cardInfoHeader.Reserved2 = data.ReadBytes(0x0C);
cardInfoHeader.TitleVersion = data.ReadUInt16();
cardInfoHeader.CardRevision = data.ReadUInt16();
cardInfoHeader.Reserved3 = data.ReadBytes(0x0C);
cardInfoHeader.CVerTitleID = data.ReadBytes(8);
cardInfoHeader.CVerVersionNumber = data.ReadUInt16();
cardInfoHeader.Reserved4 = data.ReadBytes(0xCD6);
return cardInfoHeader;
return data.ReadType<CardInfoHeader>();
}
/// <summary>
@@ -280,46 +267,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled development card info header on success, null on error</returns>
private static DevelopmentCardInfoHeader? ParseDevelopmentCardInfoHeader(Stream data)
public static DevelopmentCardInfoHeader? ParseDevelopmentCardInfoHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var developmentCardInfoHeader = new DevelopmentCardInfoHeader();
developmentCardInfoHeader.InitialData = ParseInitialData(data);
if (developmentCardInfoHeader.InitialData == null)
return null;
developmentCardInfoHeader.CardDeviceReserved1 = data.ReadBytes(0x200);
developmentCardInfoHeader.TitleKey = data.ReadBytes(0x10);
developmentCardInfoHeader.CardDeviceReserved2 = data.ReadBytes(0x1BF0);
developmentCardInfoHeader.TestData = ParseTestData(data);
if (developmentCardInfoHeader.TestData == null)
return null;
return developmentCardInfoHeader;
}
/// <summary>
/// Parse a Stream into an initial data
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled initial data on success, null on error</returns>
private static InitialData? ParseInitialData(Stream data)
{
// TODO: Use marshalling here instead of building
var initialData = new InitialData();
initialData.CardSeedKeyY = data.ReadBytes(0x10);
initialData.EncryptedCardSeed = data.ReadBytes(0x10);
initialData.CardSeedAESMAC = data.ReadBytes(0x10);
initialData.CardSeedNonce = data.ReadBytes(0xC);
initialData.Reserved = data.ReadBytes(0xC4);
initialData.BackupHeader = ParseNCCHHeader(data, true);
if (initialData.BackupHeader == null)
return null;
return initialData;
return data.ReadType<DevelopmentCardInfoHeader>();
}
/// <summary>
@@ -328,7 +278,7 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="skipSignature">Indicates if the signature should be skipped</param>
/// <returns>Filled NCCH header on success, null on error</returns>
internal static NCCHHeader ParseNCCHHeader(Stream data, bool skipSignature = false)
public static NCCHHeader ParseNCCHHeader(Stream data, bool skipSignature = false)
{
// TODO: Use marshalling here instead of building
var header = new NCCHHeader();
@@ -352,7 +302,7 @@ namespace SabreTools.Serialization.Deserializers
header.ProductCode = Encoding.ASCII.GetString(productCode).TrimEnd('\0');
header.ExtendedHeaderHash = data.ReadBytes(0x20);
header.ExtendedHeaderSizeInBytes = data.ReadUInt32();
header.Reserved2 = data.ReadBytes(4);
header.Reserved2 = data.ReadUInt32();
header.Flags = ParseNCCHHeaderFlags(data);
header.PlainRegionOffsetInMediaUnits = data.ReadUInt32();
header.PlainRegionSizeInMediaUnits = data.ReadUInt32();
@@ -361,11 +311,11 @@ namespace SabreTools.Serialization.Deserializers
header.ExeFSOffsetInMediaUnits = data.ReadUInt32();
header.ExeFSSizeInMediaUnits = data.ReadUInt32();
header.ExeFSHashRegionSizeInMediaUnits = data.ReadUInt32();
header.Reserved3 = data.ReadBytes(4);
header.Reserved3 = data.ReadUInt32();
header.RomFSOffsetInMediaUnits = data.ReadUInt32();
header.RomFSSizeInMediaUnits = data.ReadUInt32();
header.RomFSHashRegionSizeInMediaUnits = data.ReadUInt32();
header.Reserved4 = data.ReadBytes(4);
header.Reserved4 = data.ReadUInt32();
header.ExeFSSuperblockHash = data.ReadBytes(0x20);
header.RomFSSuperblockHash = data.ReadBytes(0x20);
@@ -377,46 +327,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled NCCH header flags on success, null on error</returns>
private static NCCHHeaderFlags ParseNCCHHeaderFlags(Stream data)
public static NCCHHeaderFlags? ParseNCCHHeaderFlags(Stream data)
{
// TODO: Use marshalling here instead of building
var headerFlags = new NCCHHeaderFlags();
headerFlags.Reserved0 = data.ReadByteValue();
headerFlags.Reserved1 = data.ReadByteValue();
headerFlags.Reserved2 = data.ReadByteValue();
headerFlags.CryptoMethod = (CryptoMethod)data.ReadByteValue();
headerFlags.ContentPlatform = (ContentPlatform)data.ReadByteValue();
headerFlags.MediaPlatformIndex = (ContentType)data.ReadByteValue();
headerFlags.ContentUnitSize = data.ReadByteValue();
headerFlags.BitMasks = (BitMasks)data.ReadByteValue();
return headerFlags;
}
/// <summary>
/// Parse a Stream into an initial data
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled initial data on success, null on error</returns>
private static TestData ParseTestData(Stream data)
{
// TODO: Use marshalling here instead of building
var testData = new TestData();
// TODO: Validate some of the values
testData.Signature = data.ReadBytes(8);
testData.AscendingByteSequence = data.ReadBytes(0x1F8);
testData.DescendingByteSequence = data.ReadBytes(0x200);
testData.Filled00 = data.ReadBytes(0x200);
testData.FilledFF = data.ReadBytes(0x200);
testData.Filled0F = data.ReadBytes(0x200);
testData.FilledF0 = data.ReadBytes(0x200);
testData.Filled55 = data.ReadBytes(0x200);
testData.FilledAA = data.ReadBytes(0x1FF);
testData.FinalByte = data.ReadByteValue();
return testData;
return data.ReadType<NCCHHeaderFlags>();
}
/// <summary>
@@ -424,203 +337,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled NCCH extended header on success, null on error</returns>
private static NCCHExtendedHeader? ParseNCCHExtendedHeader(Stream data)
public static NCCHExtendedHeader? ParseNCCHExtendedHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var extendedHeader = new NCCHExtendedHeader();
extendedHeader.SCI = ParseSystemControlInfo(data);
if (extendedHeader.SCI == null)
return null;
extendedHeader.ACI = ParseAccessControlInfo(data);
if (extendedHeader.ACI == null)
return null;
extendedHeader.AccessDescSignature = data.ReadBytes(0x100);
extendedHeader.NCCHHDRPublicKey = data.ReadBytes(0x100);
extendedHeader.ACIForLimitations = ParseAccessControlInfo(data);
if (extendedHeader.ACI == null)
return null;
return extendedHeader;
}
/// <summary>
/// Parse a Stream into a system control info
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled system control info on success, null on error</returns>
private static SystemControlInfo ParseSystemControlInfo(Stream data)
{
// TODO: Use marshalling here instead of building
var systemControlInfo = new SystemControlInfo();
byte[]? applicationTitle = data.ReadBytes(8);
if (applicationTitle != null)
systemControlInfo.ApplicationTitle = Encoding.ASCII.GetString(applicationTitle).TrimEnd('\0');
systemControlInfo.Reserved1 = data.ReadBytes(5);
systemControlInfo.Flag = data.ReadByteValue();
systemControlInfo.RemasterVersion = data.ReadUInt16();
systemControlInfo.TextCodeSetInfo = ParseCodeSetInfo(data);
systemControlInfo.StackSize = data.ReadUInt32();
systemControlInfo.ReadOnlyCodeSetInfo = ParseCodeSetInfo(data);
systemControlInfo.Reserved2 = data.ReadBytes(4);
systemControlInfo.DataCodeSetInfo = ParseCodeSetInfo(data);
systemControlInfo.BSSSize = data.ReadUInt32();
systemControlInfo.DependencyModuleList = new ulong[48];
for (int i = 0; i < 48; i++)
{
systemControlInfo.DependencyModuleList[i] = data.ReadUInt64();
}
systemControlInfo.SystemInfo = ParseSystemInfo(data);
return systemControlInfo;
}
/// <summary>
/// Parse a Stream into a code set info
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled code set info on success, null on error</returns>
private static CodeSetInfo ParseCodeSetInfo(Stream data)
{
// TODO: Use marshalling here instead of building
var codeSetInfo = new CodeSetInfo();
codeSetInfo.Address = data.ReadUInt32();
codeSetInfo.PhysicalRegionSizeInPages = data.ReadUInt32();
codeSetInfo.SizeInBytes = data.ReadUInt32();
return codeSetInfo;
}
/// <summary>
/// Parse a Stream into a system info
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled system info on success, null on error</returns>
private static SystemInfo ParseSystemInfo(Stream data)
{
// TODO: Use marshalling here instead of building
var systemInfo = new SystemInfo();
systemInfo.SaveDataSize = data.ReadUInt64();
systemInfo.JumpID = data.ReadUInt64();
systemInfo.Reserved = data.ReadBytes(0x30);
return systemInfo;
}
/// <summary>
/// Parse a Stream into an access control info
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled access control info on success, null on error</returns>
private static AccessControlInfo ParseAccessControlInfo(Stream data)
{
// TODO: Use marshalling here instead of building
var accessControlInfo = new AccessControlInfo();
accessControlInfo.ARM11LocalSystemCapabilities = ParseARM11LocalSystemCapabilities(data);
accessControlInfo.ARM11KernelCapabilities = ParseARM11KernelCapabilities(data);
accessControlInfo.ARM9AccessControl = ParseARM9AccessControl(data);
return accessControlInfo;
}
/// <summary>
/// Parse a Stream into an ARM11 local system capabilities
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ARM11 local system capabilities on success, null on error</returns>
private static ARM11LocalSystemCapabilities ParseARM11LocalSystemCapabilities(Stream data)
{
// TODO: Use marshalling here instead of building
var arm11LocalSystemCapabilities = new ARM11LocalSystemCapabilities();
arm11LocalSystemCapabilities.ProgramID = data.ReadUInt64();
arm11LocalSystemCapabilities.CoreVersion = data.ReadUInt32();
arm11LocalSystemCapabilities.Flag1 = (ARM11LSCFlag1)data.ReadByteValue();
arm11LocalSystemCapabilities.Flag2 = (ARM11LSCFlag2)data.ReadByteValue();
arm11LocalSystemCapabilities.Flag0 = (ARM11LSCFlag0)data.ReadByteValue();
arm11LocalSystemCapabilities.Priority = data.ReadByteValue();
arm11LocalSystemCapabilities.ResourceLimitDescriptors = new ushort[16];
for (int i = 0; i < 16; i++)
{
arm11LocalSystemCapabilities.ResourceLimitDescriptors[i] = data.ReadUInt16();
}
arm11LocalSystemCapabilities.StorageInfo = ParseStorageInfo(data);
arm11LocalSystemCapabilities.ServiceAccessControl = new ulong[32];
for (int i = 0; i < 32; i++)
{
arm11LocalSystemCapabilities.ServiceAccessControl[i] = data.ReadUInt64();
}
arm11LocalSystemCapabilities.ExtendedServiceAccessControl = new ulong[2];
for (int i = 0; i < 2; i++)
{
arm11LocalSystemCapabilities.ExtendedServiceAccessControl[i] = data.ReadUInt64();
}
arm11LocalSystemCapabilities.Reserved = data.ReadBytes(0x0F);
arm11LocalSystemCapabilities.ResourceLimitCategory = (ResourceLimitCategory)data.ReadByteValue();
return arm11LocalSystemCapabilities;
}
/// <summary>
/// Parse a Stream into a storage info
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled storage info on success, null on error</returns>
private static StorageInfo ParseStorageInfo(Stream data)
{
// TODO: Use marshalling here instead of building
var storageInfo = new StorageInfo();
storageInfo.ExtdataID = data.ReadUInt64();
storageInfo.SystemSavedataIDs = data.ReadBytes(8);
storageInfo.StorageAccessibleUniqueIDs = data.ReadBytes(8);
storageInfo.FileSystemAccessInfo = data.ReadBytes(7);
storageInfo.OtherAttributes = (StorageInfoOtherAttributes)data.ReadByteValue();
return storageInfo;
}
/// <summary>
/// Parse a Stream into an ARM11 kernel capabilities
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ARM11 kernel capabilities on success, null on error</returns>
private static ARM11KernelCapabilities ParseARM11KernelCapabilities(Stream data)
{
// TODO: Use marshalling here instead of building
var arm11KernelCapabilities = new ARM11KernelCapabilities();
arm11KernelCapabilities.Descriptors = new uint[28];
for (int i = 0; i < 28; i++)
{
arm11KernelCapabilities.Descriptors[i] = data.ReadUInt32();
}
arm11KernelCapabilities.Reserved = data.ReadBytes(0x10);
return arm11KernelCapabilities;
}
/// <summary>
/// Parse a Stream into an ARM11 access control
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ARM11 access control on success, null on error</returns>
private static ARM9AccessControl ParseARM9AccessControl(Stream data)
{
// TODO: Use marshalling here instead of building
var arm9AccessControl = new ARM9AccessControl();
arm9AccessControl.Descriptors = data.ReadBytes(15);
arm9AccessControl.DescriptorVersion = data.ReadByteValue();
return arm9AccessControl;
return data.ReadType<NCCHExtendedHeader>();
}
/// <summary>
@@ -628,7 +347,7 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ExeFS header on success, null on error</returns>
private static ExeFSHeader ParseExeFSHeader(Stream data)
public static ExeFSHeader? ParseExeFSHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var exeFSHeader = new ExeFSHeader();
@@ -636,7 +355,11 @@ namespace SabreTools.Serialization.Deserializers
exeFSHeader.FileHeaders = new ExeFSFileHeader[10];
for (int i = 0; i < 10; i++)
{
exeFSHeader.FileHeaders[i] = ParseExeFSFileHeader(data);
var exeFsFileHeader = ParseExeFSFileHeader(data);
if (exeFsFileHeader == null)
return null;
exeFSHeader.FileHeaders[i] = exeFsFileHeader;
}
exeFSHeader.Reserved = data.ReadBytes(0x20);
exeFSHeader.FileHashes = new byte[10][];
@@ -653,7 +376,7 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ExeFS file header on success, null on error</returns>
private static ExeFSFileHeader ParseExeFSFileHeader(Stream data)
public static ExeFSFileHeader? ParseExeFSFileHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var exeFSFileHeader = new ExeFSFileHeader();
@@ -672,39 +395,17 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled RomFS header on success, null on error</returns>
private static RomFSHeader? ParseRomFSHeader(Stream data)
public static RomFSHeader? ParseRomFSHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var romFSHeader = new RomFSHeader();
var romFSHeader = data.ReadType<RomFSHeader>();
byte[]? magicString = data.ReadBytes(4);
if (magicString == null)
if (romFSHeader == null)
return null;
romFSHeader.MagicString = Encoding.ASCII.GetString(magicString).TrimEnd('\0');
if (romFSHeader.MagicString != RomFSMagicNumber)
return null;
romFSHeader.MagicNumber = data.ReadUInt32();
if (romFSHeader.MagicNumber != RomFSSecondMagicNumber)
return null;
romFSHeader.MasterHashSize = data.ReadUInt32();
romFSHeader.Level1LogicalOffset = data.ReadUInt64();
romFSHeader.Level1HashdataSize = data.ReadUInt64();
romFSHeader.Level1BlockSizeLog2 = data.ReadUInt32();
romFSHeader.Reserved1 = data.ReadBytes(4);
romFSHeader.Level2LogicalOffset = data.ReadUInt64();
romFSHeader.Level2HashdataSize = data.ReadUInt64();
romFSHeader.Level2BlockSizeLog2 = data.ReadUInt32();
romFSHeader.Reserved2 = data.ReadBytes(4);
romFSHeader.Level3LogicalOffset = data.ReadUInt64();
romFSHeader.Level3HashdataSize = data.ReadUInt64();
romFSHeader.Level3BlockSizeLog2 = data.ReadUInt32();
romFSHeader.Reserved3 = data.ReadBytes(4);
romFSHeader.Reserved4 = data.ReadBytes(4);
romFSHeader.OptionalInfoSize = data.ReadUInt32();
return romFSHeader;
}
}

View File

@@ -61,6 +61,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.ItemCount; i++)
{
var directoryEntry = ParseDirectoryEntry(data);
if (directoryEntry == null)
return null;
file.DirectoryEntries[i] = directoryEntry;
}
@@ -83,7 +86,7 @@ namespace SabreTools.Serialization.Deserializers
while (data.Position < directoryNamesEnd)
{
long nameOffset = data.Position - directoryNamesStart;
string? directoryName = data.ReadString(Encoding.ASCII);
string? directoryName = data.ReadNullTerminatedAnsiString();
if (data.Position > directoryNamesEnd)
{
data.Seek(-directoryName?.Length ?? 0, SeekOrigin.Current);
@@ -96,13 +99,6 @@ namespace SabreTools.Serialization.Deserializers
file.DirectoryNames[nameOffset] = directoryName;
}
// Loop and assign to entries
foreach (var directoryEntry in file.DirectoryEntries)
{
if (directoryEntry != null)
directoryEntry.Name = file.DirectoryNames[directoryEntry.NameOffset];
}
}
#endregion
@@ -116,6 +112,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.Info1Count; i++)
{
var directoryInfo1Entry = ParseDirectoryInfo1Entry(data);
if (directoryInfo1Entry == null)
return null;
file.DirectoryInfo1Entries[i] = directoryInfo1Entry;
}
@@ -130,6 +129,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.ItemCount; i++)
{
var directoryInfo2Entry = ParseDirectoryInfo2Entry(data);
if (directoryInfo2Entry == null)
return null;
file.DirectoryInfo2Entries[i] = directoryInfo2Entry;
}
@@ -144,6 +146,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.CopyCount; i++)
{
var directoryCopyEntry = ParseDirectoryCopyEntry(data);
if (directoryCopyEntry == null)
return null;
file.DirectoryCopyEntries[i] = directoryCopyEntry;
}
@@ -158,6 +163,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.LocalCount; i++)
{
var directoryLocalEntry = ParseDirectoryLocalEntry(data);
if (directoryLocalEntry == null)
return null;
file.DirectoryLocalEntries[i] = directoryLocalEntry;
}
@@ -187,6 +195,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < directoryHeader.ItemCount; i++)
{
var unknownEntry = ParseUnknownEntry(data);
if (unknownEntry == null)
return null;
file.UnknownEntries[i] = unknownEntry;
}
@@ -228,6 +239,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < checksumMapHeader.ItemCount; i++)
{
var checksumMapEntry = ParseChecksumMapEntry(data);
if (checksumMapEntry == null)
return null;
file.ChecksumMapEntries[i] = checksumMapEntry;
}
@@ -242,6 +256,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < checksumMapHeader.ChecksumCount; i++)
{
var checksumEntry = ParseChecksumEntry(data);
if (checksumEntry == null)
return null;
file.ChecksumEntries[i] = checksumEntry;
}
@@ -260,30 +277,17 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life No Cache header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
header.Dummy0 = data.ReadUInt32();
if (header == null)
return null;
if (header.Dummy0 != 0x00000001)
return null;
header.MajorVersion = data.ReadUInt32();
if (header.MajorVersion != 0x00000002)
return null;
header.MinorVersion = data.ReadUInt32();
if (header.MinorVersion != 1)
return null;
header.CacheID = data.ReadUInt32();
header.LastVersionPlayed = data.ReadUInt32();
header.Dummy1 = data.ReadUInt32();
header.Dummy2 = data.ReadUInt32();
header.FileSize = data.ReadUInt32();
header.BlockSize = data.ReadUInt32();
header.BlockCount = data.ReadUInt32();
header.Dummy3 = data.ReadUInt32();
return header;
}
@@ -294,27 +298,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life No Cache directory header on success, null on error</returns>
private static DirectoryHeader? ParseDirectoryHeader(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryHeader directoryHeader = new DirectoryHeader();
var directoryHeader = data.ReadType<DirectoryHeader>();
directoryHeader.Dummy0 = data.ReadUInt32();
if (directoryHeader == null)
return null;
if (directoryHeader.Dummy0 != 0x00000004)
return null;
directoryHeader.CacheID = data.ReadUInt32();
directoryHeader.LastVersionPlayed = data.ReadUInt32();
directoryHeader.ItemCount = data.ReadUInt32();
directoryHeader.FileCount = data.ReadUInt32();
directoryHeader.ChecksumDataLength = data.ReadUInt32();
directoryHeader.DirectorySize = data.ReadUInt32();
directoryHeader.NameSize = data.ReadUInt32();
directoryHeader.Info1Count = data.ReadUInt32();
directoryHeader.CopyCount = data.ReadUInt32();
directoryHeader.LocalCount = data.ReadUInt32();
directoryHeader.Dummy1 = data.ReadUInt32();
directoryHeader.Dummy2 = data.ReadUInt32();
directoryHeader.Checksum = data.ReadUInt32();
return directoryHeader;
}
@@ -323,20 +313,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cache directory entry on success, null on error</returns>
private static DirectoryEntry ParseDirectoryEntry(Stream data)
private static DirectoryEntry? ParseDirectoryEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryEntry directoryEntry = new DirectoryEntry();
directoryEntry.NameOffset = data.ReadUInt32();
directoryEntry.ItemSize = data.ReadUInt32();
directoryEntry.ChecksumIndex = data.ReadUInt32();
directoryEntry.DirectoryFlags = (HL_NCF_FLAG)data.ReadUInt32();
directoryEntry.ParentIndex = data.ReadUInt32();
directoryEntry.NextIndex = data.ReadUInt32();
directoryEntry.FirstIndex = data.ReadUInt32();
return directoryEntry;
return data.ReadType<DirectoryEntry>();
}
/// <summary>
@@ -344,14 +323,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cache directory info 1 entry on success, null on error</returns>
private static DirectoryInfo1Entry ParseDirectoryInfo1Entry(Stream data)
private static DirectoryInfo1Entry? ParseDirectoryInfo1Entry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryInfo1Entry directoryInfo1Entry = new DirectoryInfo1Entry();
directoryInfo1Entry.Dummy0 = data.ReadUInt32();
return directoryInfo1Entry;
return data.ReadType<DirectoryInfo1Entry>();
}
/// <summary>
@@ -359,14 +333,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cache directory info 2 entry on success, null on error</returns>
private static DirectoryInfo2Entry ParseDirectoryInfo2Entry(Stream data)
private static DirectoryInfo2Entry? ParseDirectoryInfo2Entry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryInfo2Entry directoryInfo2Entry = new DirectoryInfo2Entry();
directoryInfo2Entry.Dummy0 = data.ReadUInt32();
return directoryInfo2Entry;
return data.ReadType<DirectoryInfo2Entry>();
}
/// <summary>
@@ -374,14 +343,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cache directory copy entry on success, null on error</returns>
private static DirectoryCopyEntry ParseDirectoryCopyEntry(Stream data)
private static DirectoryCopyEntry? ParseDirectoryCopyEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryCopyEntry directoryCopyEntry = new DirectoryCopyEntry();
directoryCopyEntry.DirectoryIndex = data.ReadUInt32();
return directoryCopyEntry;
return data.ReadType<DirectoryCopyEntry>();
}
/// <summary>
@@ -389,14 +353,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cache directory local entry on success, null on error</returns>
private static DirectoryLocalEntry ParseDirectoryLocalEntry(Stream data)
private static DirectoryLocalEntry? ParseDirectoryLocalEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryLocalEntry directoryLocalEntry = new DirectoryLocalEntry();
directoryLocalEntry.DirectoryIndex = data.ReadUInt32();
return directoryLocalEntry;
return data.ReadType<DirectoryLocalEntry>();
}
/// <summary>
@@ -406,14 +365,12 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life No Cache unknown header on success, null on error</returns>
private static UnknownHeader? ParseUnknownHeader(Stream data)
{
// TODO: Use marshalling here instead of building
UnknownHeader unknownHeader = new UnknownHeader();
var unknownHeader = data.ReadType<UnknownHeader>();
unknownHeader.Dummy0 = data.ReadUInt32();
if (unknownHeader == null)
return null;
if (unknownHeader.Dummy0 != 0x00000001)
return null;
unknownHeader.Dummy1 = data.ReadUInt32();
if (unknownHeader.Dummy1 != 0x00000000)
return null;
@@ -425,14 +382,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cacheunknown entry on success, null on error</returns>
private static UnknownEntry ParseUnknownEntry(Stream data)
private static UnknownEntry? ParseUnknownEntry(Stream data)
{
// TODO: Use marshalling here instead of building
UnknownEntry unknownEntry = new UnknownEntry();
unknownEntry.Dummy0 = data.ReadUInt32();
return unknownEntry;
return data.ReadType<UnknownEntry>();
}
/// <summary>
@@ -442,15 +394,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life No Cache checksum header on success, null on error</returns>
private static ChecksumHeader? ParseChecksumHeader(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumHeader checksumHeader = new ChecksumHeader();
var checksumHeader = data.ReadType<ChecksumHeader>();
checksumHeader.Dummy0 = data.ReadUInt32();
if (checksumHeader == null)
return null;
if (checksumHeader.Dummy0 != 0x00000001)
return null;
checksumHeader.ChecksumSize = data.ReadUInt32();
return checksumHeader;
}
@@ -461,20 +411,15 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life No Cache checksum map header on success, null on error</returns>
private static ChecksumMapHeader? ParseChecksumMapHeader(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumMapHeader checksumMapHeader = new ChecksumMapHeader();
var checksumMapHeader = data.ReadType<ChecksumMapHeader>();
checksumMapHeader.Dummy0 = data.ReadUInt32();
if (checksumMapHeader == null)
return null;
if (checksumMapHeader.Dummy0 != 0x14893721)
return null;
checksumMapHeader.Dummy1 = data.ReadUInt32();
if (checksumMapHeader.Dummy1 != 0x00000001)
return null;
checksumMapHeader.ItemCount = data.ReadUInt32();
checksumMapHeader.ChecksumCount = data.ReadUInt32();
return checksumMapHeader;
}
@@ -483,15 +428,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cache checksum map entry on success, null on error</returns>
private static ChecksumMapEntry ParseChecksumMapEntry(Stream data)
private static ChecksumMapEntry? ParseChecksumMapEntry(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumMapEntry checksumMapEntry = new ChecksumMapEntry();
checksumMapEntry.ChecksumCount = data.ReadUInt32();
checksumMapEntry.FirstChecksumIndex = data.ReadUInt32();
return checksumMapEntry;
return data.ReadType<ChecksumMapEntry>();
}
/// <summary>
@@ -499,14 +438,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life No Cache checksum entry on success, null on error</returns>
private static ChecksumEntry ParseChecksumEntry(Stream data)
private static ChecksumEntry? ParseChecksumEntry(Stream data)
{
// TODO: Use marshalling here instead of building
ChecksumEntry checksumEntry = new ChecksumEntry();
checksumEntry.Checksum = data.ReadUInt32();
return checksumEntry;
return data.ReadType<ChecksumEntry>();
}
}
}

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using SabreTools.IO.Extensions;
using SabreTools.Models.NewExecutable;
using static SabreTools.Models.NewExecutable.Constants;
@@ -77,7 +76,7 @@ namespace SabreTools.Serialization.Deserializers
// If the offset for the segment table doesn't exist
tableAddress = initialOffset
+ (int)stub.Header.NewExeHeaderAddr
+ executableHeader.SegmentTableOffset;
+ executableHeader.ResourceTableOffset;
if (tableAddress >= data.Length)
return executable;
@@ -214,48 +213,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled executable header on success, null on error</returns>
public static ExecutableHeader? ParseExecutableHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var header = new ExecutableHeader();
var header = data.ReadType<ExecutableHeader>();
byte[]? magic = data.ReadBytes(2);
if (magic == null)
if (header == null)
return null;
header.Magic = Encoding.ASCII.GetString(magic);
if (header.Magic != SignatureString)
return null;
header.LinkerVersion = data.ReadByteValue();
header.LinkerRevision = data.ReadByteValue();
header.EntryTableOffset = data.ReadUInt16();
header.EntryTableSize = data.ReadUInt16();
header.CrcChecksum = data.ReadUInt32();
header.FlagWord = (HeaderFlag)data.ReadUInt16();
header.AutomaticDataSegmentNumber = data.ReadUInt16();
header.InitialHeapAlloc = data.ReadUInt16();
header.InitialStackAlloc = data.ReadUInt16();
header.InitialCSIPSetting = data.ReadUInt32();
header.InitialSSSPSetting = data.ReadUInt32();
header.FileSegmentCount = data.ReadUInt16();
header.ModuleReferenceTableSize = data.ReadUInt16();
header.NonResidentNameTableSize = data.ReadUInt16();
header.SegmentTableOffset = data.ReadUInt16();
header.ResourceTableOffset = data.ReadUInt16();
header.ResidentNameTableOffset = data.ReadUInt16();
header.ModuleReferenceTableOffset = data.ReadUInt16();
header.ImportedNamesTableOffset = data.ReadUInt16();
header.NonResidentNamesTableOffset = data.ReadUInt32();
header.MovableEntriesCount = data.ReadUInt16();
header.SegmentAlignmentShiftCount = data.ReadUInt16();
header.ResourceEntriesCount = data.ReadUInt16();
header.TargetOperatingSystem = (OperatingSystem)data.ReadByteValue();
header.AdditionalFlags = (OS2Flag)data.ReadByteValue();
header.ReturnThunkOffset = data.ReadUInt16();
header.SegmentReferenceThunkOffset = data.ReadUInt16();
header.MinCodeSwapAreaSize = data.ReadUInt16();
header.WindowsSDKRevision = data.ReadByteValue();
header.WindowsSDKVersion = data.ReadByteValue();
return header;
}
@@ -265,31 +229,40 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="count">Number of segment table entries to read</param>
/// <returns>Filled segment table on success, null on error</returns>
public static SegmentTableEntry[] ParseSegmentTable(Stream data, int count)
public static SegmentTableEntry[]? ParseSegmentTable(Stream data, int count)
{
// TODO: Use marshalling here instead of building
var segmentTable = new SegmentTableEntry[count];
for (int i = 0; i < count; i++)
{
var entry = new SegmentTableEntry();
entry.Offset = data.ReadUInt16();
entry.Length = data.ReadUInt16();
entry.FlagWord = (SegmentTableEntryFlag)data.ReadUInt16();
entry.MinimumAllocationSize = data.ReadUInt16();
var entry = ParseSegmentTableEntry(data);
if (entry == null)
return null;
segmentTable[i] = entry;
}
return segmentTable;
}
/// <summary>
/// Parse a Stream into a segment table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled segment table entry on success, null on error</returns>
public static SegmentTableEntry? ParseSegmentTableEntry(Stream data)
{
return data.ReadType<SegmentTableEntry>();
}
/// <summary>
/// Parse a Stream into a resource table
/// </summary>
/// <param name="data">Stream to parse</param>
/// <param name="count">Number of resource table entries to read</param>
/// <returns>Filled resource table on success, null on error</returns>
public static ResourceTable ParseResourceTable(Stream data, int count)
public static ResourceTable? ParseResourceTable(Stream data, ushort count)
{
long initialOffset = data.Position;
@@ -297,39 +270,50 @@ namespace SabreTools.Serialization.Deserializers
var resourceTable = new ResourceTable();
resourceTable.AlignmentShiftCount = data.ReadUInt16();
resourceTable.ResourceTypes = new ResourceTypeInformationEntry[count];
for (int i = 0; i < resourceTable.ResourceTypes.Length; i++)
var resourceTypes = new List<ResourceTypeInformationEntry>();
for (int i = 0; i < count; i++)
{
var entry = new ResourceTypeInformationEntry();
entry.TypeID = data.ReadUInt16();
entry.ResourceCount = data.ReadUInt16();
entry.Reserved = data.ReadUInt32();
// A zero type ID marks the end of the resource type information blocks.
if (entry.TypeID == 0)
{
resourceTypes.Add(entry);
break;
}
entry.Resources = new ResourceTypeResourceEntry[entry.ResourceCount];
for (int j = 0; j < entry.ResourceCount; j++)
{
// TODO: Should we read and store the resource data?
var resource = new ResourceTypeResourceEntry();
resource.Offset = data.ReadUInt16();
resource.Length = data.ReadUInt16();
resource.FlagWord = (ResourceTypeResourceFlag)data.ReadUInt16();
resource.ResourceID = data.ReadUInt16();
resource.Reserved = data.ReadUInt32();
var resource = ParseResourceTypeResourceEntry(data);
if (resource == null)
return null;
entry.Resources[j] = resource;
}
resourceTable.ResourceTypes[i] = entry;
resourceTypes.Add(entry);
}
resourceTable.ResourceTypes = [.. resourceTypes];
// Get the full list of unique string offsets
var stringOffsets = resourceTable.ResourceTypes
.Where(rt => rt != null)
.Where(rt => rt!.IsIntegerType() == false)
.Where(rt => !rt!.IsIntegerType() && rt!.TypeID != 0)
.Select(rt => rt!.TypeID)
.Union(resourceTable.ResourceTypes
.Where(rt => rt != null)
.Where(rt => rt != null && rt!.TypeID != 0)
.SelectMany(rt => rt!.Resources ?? [])
.Where(r => r!.IsIntegerType() == false)
.Where(r => !r!.IsIntegerType())
.Select(r => r!.ResourceID))
.Distinct()
.Where(o => o != 0)
.OrderBy(o => o)
.ToList();
@@ -339,82 +323,157 @@ namespace SabreTools.Serialization.Deserializers
{
int stringOffset = (int)(stringOffsets[i] + initialOffset);
data.Seek(stringOffset, SeekOrigin.Begin);
var str = new ResourceTypeAndNameString();
str.Length = data.ReadByteValue();
str.Text = data.ReadBytes(str.Length);
var str = ParseResourceTypeAndNameString(data);
if (str == null)
return null;
resourceTable.TypeAndNameStrings[stringOffsets[i]] = str;
}
return resourceTable;
}
/// <summary>
/// Parse a Stream into a resource entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled resource entry on success, null on error</returns>
public static ResourceTypeResourceEntry? ParseResourceTypeResourceEntry(Stream data)
{
// TODO: Should we read and store the resource data?
return data.ReadType<ResourceTypeResourceEntry>();
}
/// <summary>
/// Parse a Stream into a resource type and name string
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled resource type and name string on success, null on error</returns>
public static ResourceTypeAndNameString? ParseResourceTypeAndNameString(Stream data)
{
// TODO: Use marshalling here instead of building
var str = new ResourceTypeAndNameString();
str.Length = data.ReadByteValue();
str.Text = data.ReadBytes(str.Length);
return str;
}
/// <summary>
/// Parse a Stream into a resident-name table
/// </summary>
/// <param name="data">Stream to parse</param>
/// <param name="endOffset">First address not part of the resident-name table</param>
/// <returns>Filled resident-name table on success, null on error</returns>
public static ResidentNameTableEntry[] ParseResidentNameTable(Stream data, int endOffset)
public static ResidentNameTableEntry[]? ParseResidentNameTable(Stream data, int endOffset)
{
// TODO: Use marshalling here instead of building
var residentNameTable = new List<ResidentNameTableEntry>();
while (data.Position < endOffset)
while (data.Position < endOffset && data.Position < data.Length)
{
var entry = new ResidentNameTableEntry();
entry.Length = data.ReadByteValue();
entry.NameString = data.ReadBytes(entry.Length);
entry.OrdinalNumber = data.ReadUInt16();
var entry = ParseResidentNameTableEntry(data);
if (entry == null)
return null;
residentNameTable.Add(entry);
}
return [.. residentNameTable];
}
/// <summary>
/// Parse a Stream into a resident-name table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled resident-name table entry on success, null on error</returns>
public static ResidentNameTableEntry? ParseResidentNameTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new ResidentNameTableEntry();
entry.Length = data.ReadByteValue();
entry.NameString = data.ReadBytes(entry.Length);
entry.OrdinalNumber = data.ReadUInt16();
return entry;
}
/// <summary>
/// Parse a Stream into a module-reference table
/// </summary>
/// <param name="data">Stream to parse</param>
/// <param name="count">Number of module-reference table entries to read</param>
/// <returns>Filled module-reference table on success, null on error</returns>
public static ModuleReferenceTableEntry[] ParseModuleReferenceTable(Stream data, int count)
public static ModuleReferenceTableEntry[]? ParseModuleReferenceTable(Stream data, int count)
{
// TODO: Use marshalling here instead of building
var moduleReferenceTable = new ModuleReferenceTableEntry[count];
for (int i = 0; i < count; i++)
{
var entry = new ModuleReferenceTableEntry();
entry.Offset = data.ReadUInt16();
var entry = ParseModuleReferenceTableEntry(data);
if (entry == null)
return null;
moduleReferenceTable[i] = entry;
}
return moduleReferenceTable;
}
/// <summary>
/// Parse a Stream into a module-reference table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled module-reference table entry on success, null on error</returns>
public static ModuleReferenceTableEntry? ParseModuleReferenceTableEntry(Stream data)
{
return data.ReadType<ModuleReferenceTableEntry>();
}
/// <summary>
/// Parse a Stream into an imported-name table
/// </summary>
/// <param name="data">Stream to parse</param>
/// <param name="endOffset">First address not part of the imported-name table</param>
/// <returns>Filled imported-name table on success, null on error</returns>
public static Dictionary<ushort, ImportedNameTableEntry?> ParseImportedNameTable(Stream data, int endOffset)
public static Dictionary<ushort, ImportedNameTableEntry>? ParseImportedNameTable(Stream data, int endOffset)
{
// TODO: Use marshalling here instead of building
var importedNameTable = new Dictionary<ushort, ImportedNameTableEntry?>();
var importedNameTable = new Dictionary<ushort, ImportedNameTableEntry>();
while (data.Position < endOffset)
while (data.Position < endOffset && data.Position < data.Length)
{
ushort currentOffset = (ushort)data.Position;
var entry = new ImportedNameTableEntry();
entry.Length = data.ReadByteValue();
entry.NameString = data.ReadBytes(entry.Length);
var entry = ParseImportedNameTableEntry(data);
if (entry == null)
return null;
importedNameTable[currentOffset] = entry;
}
return importedNameTable;
}
/// <summary>
/// Parse a Stream into an imported-name table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled imported-name table entry on success, null on error</returns>
public static ImportedNameTableEntry? ParseImportedNameTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new ImportedNameTableEntry();
entry.Length = data.ReadByteValue();
entry.NameString = data.ReadBytes(entry.Length);
return entry;
}
/// <summary>
/// Parse a Stream into an entry table
/// </summary>
@@ -426,7 +485,7 @@ namespace SabreTools.Serialization.Deserializers
// TODO: Use marshalling here instead of building
var entryTable = new List<EntryTableBundle>();
while (data.Position < endOffset)
while (data.Position < endOffset && data.Position < data.Length)
{
var entry = new EntryTableBundle();
entry.EntryCount = data.ReadByteValue();
@@ -460,21 +519,38 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="endOffset">First address not part of the nonresident-name table</param>
/// <returns>Filled nonresident-name table on success, null on error</returns>
public static NonResidentNameTableEntry[] ParseNonResidentNameTable(Stream data, int endOffset)
public static NonResidentNameTableEntry[]? ParseNonResidentNameTable(Stream data, int endOffset)
{
// TODO: Use marshalling here instead of building
var residentNameTable = new List<NonResidentNameTableEntry>();
while (data.Position < endOffset)
while (data.Position < endOffset && data.Position < data.Length)
{
var entry = new NonResidentNameTableEntry();
entry.Length = data.ReadByteValue();
entry.NameString = data.ReadBytes(entry.Length);
entry.OrdinalNumber = data.ReadUInt16();
var entry = ParseNonResidentNameTableEntry(data);
if (entry == null)
return null;
residentNameTable.Add(entry);
}
return [.. residentNameTable];
}
/// <summary>
/// Parse a Stream into a nonresident-name table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled nonresident-name table entry on success, null on error</returns>
public static NonResidentNameTableEntry? ParseNonResidentNameTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
var entry = new NonResidentNameTableEntry();
entry.Length = data.ReadByteValue();
entry.NameString = data.ReadBytes(entry.Length);
entry.OrdinalNumber = data.ReadUInt16();
return entry;
}
}
}

View File

@@ -103,6 +103,9 @@ namespace SabreTools.Serialization.Deserializers
while (data.Position - fileAllocationTableOffset < header.FileAllocationTableLength)
{
var entry = ParseFileAllocationTableEntry(data);
if (entry == null)
return null;
fileAllocationTable.Add(entry);
}
@@ -122,58 +125,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled common header on success, null on error</returns>
private static CommonHeader ParseCommonHeader(Stream data)
private static CommonHeader? ParseCommonHeader(Stream data)
{
// TODO: Use marshalling here instead of building
CommonHeader commonHeader = new CommonHeader();
byte[]? gameTitle = data.ReadBytes(12);
if (gameTitle != null)
commonHeader.GameTitle = Encoding.ASCII.GetString(gameTitle).TrimEnd('\0');
commonHeader.GameCode = data.ReadUInt32();
byte[]? makerCode = data.ReadBytes(2);
if (makerCode != null)
commonHeader.MakerCode = Encoding.ASCII.GetString(bytes: makerCode).TrimEnd('\0');
commonHeader.UnitCode = (Unitcode)data.ReadByteValue();
commonHeader.EncryptionSeedSelect = data.ReadByteValue();
commonHeader.DeviceCapacity = data.ReadByteValue();
commonHeader.Reserved1 = data.ReadBytes(7);
commonHeader.GameRevision = data.ReadUInt16();
commonHeader.RomVersion = data.ReadByteValue();
commonHeader.InternalFlags = data.ReadByteValue();
commonHeader.ARM9RomOffset = data.ReadUInt32();
commonHeader.ARM9EntryAddress = data.ReadUInt32();
commonHeader.ARM9LoadAddress = data.ReadUInt32();
commonHeader.ARM9Size = data.ReadUInt32();
commonHeader.ARM7RomOffset = data.ReadUInt32();
commonHeader.ARM7EntryAddress = data.ReadUInt32();
commonHeader.ARM7LoadAddress = data.ReadUInt32();
commonHeader.ARM7Size = data.ReadUInt32();
commonHeader.FileNameTableOffset = data.ReadUInt32();
commonHeader.FileNameTableLength = data.ReadUInt32();
commonHeader.FileAllocationTableOffset = data.ReadUInt32();
commonHeader.FileAllocationTableLength = data.ReadUInt32();
commonHeader.ARM9OverlayOffset = data.ReadUInt32();
commonHeader.ARM9OverlayLength = data.ReadUInt32();
commonHeader.ARM7OverlayOffset = data.ReadUInt32();
commonHeader.ARM7OverlayLength = data.ReadUInt32();
commonHeader.NormalCardControlRegisterSettings = data.ReadUInt32();
commonHeader.SecureCardControlRegisterSettings = data.ReadUInt32();
commonHeader.IconBannerOffset = data.ReadUInt32();
commonHeader.SecureAreaCRC = data.ReadUInt16();
commonHeader.SecureTransferTimeout = data.ReadUInt16();
commonHeader.ARM9Autoload = data.ReadUInt32();
commonHeader.ARM7Autoload = data.ReadUInt32();
commonHeader.SecureDisable = data.ReadBytes(8);
commonHeader.NTRRegionRomSize = data.ReadUInt32();
commonHeader.HeaderSize = data.ReadUInt32();
commonHeader.Reserved2 = data.ReadBytes(56);
commonHeader.NintendoLogo = data.ReadBytes(156);
commonHeader.NintendoLogoCRC = data.ReadUInt16();
commonHeader.HeaderCRC = data.ReadUInt16();
commonHeader.DebuggerReserved = data.ReadBytes(0x20);
return commonHeader;
return data.ReadType<CommonHeader>();
}
/// <summary>
@@ -181,73 +135,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled extended DSi header on success, null on error</returns>
private static ExtendedDSiHeader ParseExtendedDSiHeader(Stream data)
private static ExtendedDSiHeader? ParseExtendedDSiHeader(Stream data)
{
// TODO: Use marshalling here instead of building
ExtendedDSiHeader extendedDSiHeader = new ExtendedDSiHeader();
extendedDSiHeader.GlobalMBK15Settings = new uint[5];
for (int i = 0; i < 5; i++)
{
extendedDSiHeader.GlobalMBK15Settings[i] = data.ReadUInt32();
}
extendedDSiHeader.LocalMBK68SettingsARM9 = new uint[3];
for (int i = 0; i < 3; i++)
{
extendedDSiHeader.LocalMBK68SettingsARM9[i] = data.ReadUInt32();
}
extendedDSiHeader.LocalMBK68SettingsARM7 = new uint[3];
for (int i = 0; i < 3; i++)
{
extendedDSiHeader.LocalMBK68SettingsARM7[i] = data.ReadUInt32();
}
extendedDSiHeader.GlobalMBK9Setting = data.ReadUInt32();
extendedDSiHeader.RegionFlags = data.ReadUInt32();
extendedDSiHeader.AccessControl = data.ReadUInt32();
extendedDSiHeader.ARM7SCFGEXTMask = data.ReadUInt32();
extendedDSiHeader.ReservedFlags = data.ReadUInt32();
extendedDSiHeader.ARM9iRomOffset = data.ReadUInt32();
extendedDSiHeader.Reserved3 = data.ReadUInt32();
extendedDSiHeader.ARM9iLoadAddress = data.ReadUInt32();
extendedDSiHeader.ARM9iSize = data.ReadUInt32();
extendedDSiHeader.ARM7iRomOffset = data.ReadUInt32();
extendedDSiHeader.Reserved4 = data.ReadUInt32();
extendedDSiHeader.ARM7iLoadAddress = data.ReadUInt32();
extendedDSiHeader.ARM7iSize = data.ReadUInt32();
extendedDSiHeader.DigestNTRRegionOffset = data.ReadUInt32();
extendedDSiHeader.DigestNTRRegionLength = data.ReadUInt32();
extendedDSiHeader.DigestTWLRegionOffset = data.ReadUInt32();
extendedDSiHeader.DigestTWLRegionLength = data.ReadUInt32();
extendedDSiHeader.DigestSectorHashtableRegionOffset = data.ReadUInt32();
extendedDSiHeader.DigestSectorHashtableRegionLength = data.ReadUInt32();
extendedDSiHeader.DigestBlockHashtableRegionOffset = data.ReadUInt32();
extendedDSiHeader.DigestBlockHashtableRegionLength = data.ReadUInt32();
extendedDSiHeader.DigestSectorSize = data.ReadUInt32();
extendedDSiHeader.DigestBlockSectorCount = data.ReadUInt32();
extendedDSiHeader.IconBannerSize = data.ReadUInt32();
extendedDSiHeader.Unknown1 = data.ReadUInt32();
extendedDSiHeader.ModcryptArea1Offset = data.ReadUInt32();
extendedDSiHeader.ModcryptArea1Size = data.ReadUInt32();
extendedDSiHeader.ModcryptArea2Offset = data.ReadUInt32();
extendedDSiHeader.ModcryptArea2Size = data.ReadUInt32();
extendedDSiHeader.TitleID = data.ReadBytes(8);
extendedDSiHeader.DSiWarePublicSavSize = data.ReadUInt32();
extendedDSiHeader.DSiWarePrivateSavSize = data.ReadUInt32();
extendedDSiHeader.ReservedZero = data.ReadBytes(176);
extendedDSiHeader.Unknown2 = data.ReadBytes(0x10);
extendedDSiHeader.ARM9WithSecureAreaSHA1HMACHash = data.ReadBytes(20);
extendedDSiHeader.ARM7SHA1HMACHash = data.ReadBytes(20);
extendedDSiHeader.DigestMasterSHA1HMACHash = data.ReadBytes(20);
extendedDSiHeader.BannerSHA1HMACHash = data.ReadBytes(20);
extendedDSiHeader.ARM9iDecryptedSHA1HMACHash = data.ReadBytes(20);
extendedDSiHeader.ARM7iDecryptedSHA1HMACHash = data.ReadBytes(20);
extendedDSiHeader.Reserved5 = data.ReadBytes(40);
extendedDSiHeader.ARM9NoSecureAreaSHA1HMACHash = data.ReadBytes(20);
extendedDSiHeader.Reserved6 = data.ReadBytes(2636);
extendedDSiHeader.ReservedAndUnchecked = data.ReadBytes(0x180);
extendedDSiHeader.RSASignature = data.ReadBytes(0x80);
return extendedDSiHeader;
return data.ReadType<ExtendedDSiHeader>();
}
/// <summary>
@@ -255,10 +145,10 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled name table on success, null on error</returns>
private static NameTable ParseNameTable(Stream data)
private static NameTable? ParseNameTable(Stream data)
{
// TODO: Use marshalling here instead of building
NameTable nameTable = new NameTable();
var nameTable = new NameTable();
// Create a variable-length table
var folderAllocationTable = new List<FolderAllocationTableEntry>();
@@ -266,6 +156,9 @@ namespace SabreTools.Serialization.Deserializers
while (entryCount > 0)
{
var entry = ParseFolderAllocationTableEntry(data);
if (entry == null)
return null;
folderAllocationTable.Add(entry);
// If we have the root entry
@@ -301,17 +194,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled folder allocation table entry on success, null on error</returns>
private static FolderAllocationTableEntry ParseFolderAllocationTableEntry(Stream data)
private static FolderAllocationTableEntry? ParseFolderAllocationTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
FolderAllocationTableEntry entry = new FolderAllocationTableEntry();
entry.StartOffset = data.ReadUInt32();
entry.FirstFileIndex = data.ReadUInt16();
entry.ParentFolderIndex = data.ReadByteValue();
entry.Unknown = data.ReadByteValue();
return entry;
return data.ReadType<FolderAllocationTableEntry>();
}
/// <summary>
@@ -322,7 +207,7 @@ namespace SabreTools.Serialization.Deserializers
private static NameListEntry? ParseNameListEntry(Stream data)
{
// TODO: Use marshalling here instead of building
NameListEntry entry = new NameListEntry();
var entry = new NameListEntry();
byte flagAndSize = data.ReadByteValue();
if (flagAndSize == 0xFF)
@@ -349,15 +234,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled name list entry on success, null on error</returns>
private static FileAllocationTableEntry ParseFileAllocationTableEntry(Stream data)
private static FileAllocationTableEntry? ParseFileAllocationTableEntry(Stream data)
{
// TODO: Use marshalling here instead of building
FileAllocationTableEntry entry = new FileAllocationTableEntry();
entry.StartOffset = data.ReadUInt32();
entry.EndOffset = data.ReadUInt32();
return entry;
return data.ReadType<FileAllocationTableEntry>();
}
}
}

View File

@@ -1,5 +1,4 @@
using System.IO;
using System.Text;
using SabreTools.IO.Extensions;
using SabreTools.Models.PAK;
using static SabreTools.Models.PAK.Constants;
@@ -54,6 +53,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < file.DirectoryItems.Length; i++)
{
var directoryItem = ParseDirectoryItem(data);
if (directoryItem == null)
return null;
file.DirectoryItems[i] = directoryItem;
}
@@ -69,20 +71,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life Package header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
if (header == null)
return null;
header.Signature = Encoding.ASCII.GetString(signature);
if (header.Signature != SignatureString)
return null;
header.DirectoryOffset = data.ReadUInt32();
header.DirectoryLength = data.ReadUInt32();
return header;
}
@@ -91,18 +86,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Package directory item on success, null on error</returns>
private static DirectoryItem ParseDirectoryItem(Stream data)
private static DirectoryItem? ParseDirectoryItem(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryItem directoryItem = new DirectoryItem();
byte[]? itemName = data.ReadBytes(56);
if (itemName != null)
directoryItem.ItemName = Encoding.ASCII.GetString(itemName).TrimEnd('\0');
directoryItem.ItemOffset = data.ReadUInt32();
directoryItem.ItemLength = data.ReadUInt32();
return directoryItem;
return data.ReadType<DirectoryItem>();
}
}
}

View File

@@ -1,4 +1,5 @@
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using SabreTools.IO.Extensions;
using SabreTools.Models.PFF;
@@ -92,47 +93,27 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
header.HeaderSize = data.ReadUInt32();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
var header = data.ReadType<Header>();
if (header == null)
return null;
header.Signature = Encoding.ASCII.GetString(signature);
header.NumberOfFiles = data.ReadUInt32();
header.FileSegmentSize = data.ReadUInt32();
switch (header.Signature)
return header.Signature switch
{
case Version0SignatureString:
if (header.FileSegmentSize != Version0HSegmentSize)
return null;
break;
Version0SignatureString when header.FileSegmentSize != Version0HSegmentSize => null,
Version0SignatureString => header,
case Version2SignatureString:
if (header.FileSegmentSize != Version2SegmentSize)
return null;
break;
Version2SignatureString when header.FileSegmentSize != Version2SegmentSize => null,
Version2SignatureString => header,
// Version 3 can sometimes have Version 2 segment sizes
case Version3SignatureString:
if (header.FileSegmentSize != Version2SegmentSize && header.FileSegmentSize != Version3SegmentSize)
return null;
break;
Version3SignatureString when header.FileSegmentSize != Version2SegmentSize
&& header.FileSegmentSize != Version3SegmentSize => null,
Version3SignatureString => header,
case Version4SignatureString:
if (header.FileSegmentSize != Version4SegmentSize)
return null;
break;
Version4SignatureString when header.FileSegmentSize != Version4SegmentSize => null,
Version4SignatureString => header,
default:
return null;
}
header.FileListOffset = data.ReadUInt32();
return header;
_ => null,
};
}
/// <summary>
@@ -140,18 +121,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled footer on success, null on error</returns>
private static Footer ParseFooter(Stream data)
private static Footer? ParseFooter(Stream data)
{
// TODO: Use marshalling here instead of building
Footer footer = new Footer();
footer.SystemIP = data.ReadUInt32();
footer.Reserved = data.ReadUInt32();
byte[]? kingTag = data.ReadBytes(4);
if (kingTag != null)
footer.KingTag = Encoding.ASCII.GetString(kingTag);
return footer;
return data.ReadType<Footer>();
}
/// <summary>
@@ -163,7 +135,7 @@ namespace SabreTools.Serialization.Deserializers
private static Segment ParseSegment(Stream data, uint segmentSize)
{
// TODO: Use marshalling here instead of building
Segment segment = new Segment();
var segment = new Segment();
segment.Deleted = data.ReadUInt32();
segment.FileLocation = data.ReadUInt32();

View File

@@ -106,25 +106,12 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled disc information unit header on success, null on error</returns>
private static DiscInformationUnitHeader? ParseDiscInformationUnitHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var header = new DiscInformationUnitHeader();
var header = data.ReadType<DiscInformationUnitHeader>();
// We only accept Disc Information units, not Emergency Brake or other
byte[]? dic = data.ReadBytes(2);
if (dic == null)
if (header?.DiscInformationIdentifier != "DI")
return null;
header.DiscInformationIdentifier = Encoding.ASCII.GetString(dic);
if (header.DiscInformationIdentifier != "DI")
return null;
header.DiscInformationFormat = data.ReadByteValue();
header.NumberOfUnitsInBlock = data.ReadByteValue();
header.Reserved0 = data.ReadByteValue();
header.SequenceNumber = data.ReadByteValue();
header.BytesInUse = data.ReadByteValue();
header.Reserved1 = data.ReadByteValue();
return header;
}
@@ -165,17 +152,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled disc information unit trailer on success, null on error</returns>
private static DiscInformationUnitTrailer ParseDiscInformationUnitTrailer(Stream data)
private static DiscInformationUnitTrailer? ParseDiscInformationUnitTrailer(Stream data)
{
// TODO: Use marshalling here instead of building
var trailer = new DiscInformationUnitTrailer();
trailer.DiscManufacturerID = data.ReadBytes(6);
trailer.MediaTypeID = data.ReadBytes(3);
trailer.TimeStamp = data.ReadUInt16();
trailer.ProductRevisionNumber = data.ReadByteValue();
return trailer;
return data.ReadType<DiscInformationUnitTrailer>();
}
#endregion

View File

@@ -0,0 +1,697 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using SabreTools.IO.Extensions;
using SabreTools.Models.PKZIP;
using static SabreTools.Models.PKZIP.Constants;
namespace SabreTools.Serialization.Deserializers
{
public class PKZIP : BaseBinaryDeserializer<Archive>
{
/// <inheritdoc/>
protected override bool SkipCompression => true;
/// <inheritdoc/>
public override Archive? Deserialize(Stream? data)
{
// If the data is invalid
if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead)
return null;
// If the offset is out of bounds
if (data.Position < 0 || data.Position >= data.Length)
return null;
var archive = new Archive();
#region End of Central Directory Record
// Find the end of central directory record
long eocdrOffset = SearchForEndOfCentralDirectoryRecord(data);
if (eocdrOffset < 0 || eocdrOffset >= data.Length)
return null;
// Seek to the end of central directory record
data.Seek(eocdrOffset, SeekOrigin.Begin);
// Read the end of central directory record
var eocdr = ParseEndOfCentralDirectoryRecord(data);
if (eocdr == null)
return null;
// Assign the end of central directory record
archive.EndOfCentralDirectoryRecord = eocdr;
#endregion
#region ZIP64 End of Central Directory Locator and Record
// Set a flag for ZIP64 not found by default
bool zip64 = false;
// Process ZIP64 if any fields are set to max value
if (eocdr.DiskNumber == 0xFFFF
|| eocdr.StartDiskNumber == 0xFFFF
|| eocdr.TotalEntriesOnDisk == 0xFFFF
|| eocdr.TotalEntries == 0xFFFF
|| eocdr.CentralDirectorySize == 0xFFFFFFFF
|| eocdr.CentralDirectoryOffset == 0xFFFFFFFF)
{
// Set the ZIP64 flag
zip64 = true;
// Find the ZIP64 end of central directory locator
long eocdlOffset = SearchForZIP64EndOfCentralDirectoryLocator(data);
if (eocdlOffset < 0 || eocdlOffset >= data.Length)
return null;
// Seek to the ZIP64 end of central directory locator
data.Seek(eocdlOffset, SeekOrigin.Begin);
// Read the ZIP64 end of central directory locator
var eocdl64 = ParseEndOfCentralDirectoryLocator64(data);
if (eocdl64 == null)
return null;
// Assign the ZIP64 end of central directory record
archive.ZIP64EndOfCentralDirectoryLocator = eocdl64;
// Try to get the ZIP64 end of central directory record offset
if ((long)eocdl64.CentralDirectoryOffset < 0 || (long)eocdl64.CentralDirectoryOffset >= data.Length)
return null;
// Seek to the ZIP64 end of central directory record
data.Seek((long)eocdl64.CentralDirectoryOffset, SeekOrigin.Begin);
// Read the ZIP64 end of central directory record
var eocdr64 = ParseEndOfCentralDirectoryRecord64(data);
if (eocdr64 == null)
return null;
// Assign the ZIP64 end of central directory record
archive.ZIP64EndOfCentralDirectoryRecord = eocdr64;
}
#endregion
#region Central Directory Records
// Try to get the central directory record offset
long cdrOffset, cdrSize;
if (zip64 && archive.ZIP64EndOfCentralDirectoryRecord != null)
{
cdrOffset = (long)archive.ZIP64EndOfCentralDirectoryRecord.CentralDirectoryOffset;
cdrSize = (long)archive.ZIP64EndOfCentralDirectoryRecord.CentralDirectorySize;
}
else if (archive.EndOfCentralDirectoryRecord != null)
{
cdrOffset = archive.EndOfCentralDirectoryRecord.CentralDirectoryOffset;
cdrSize = archive.EndOfCentralDirectoryRecord.CentralDirectorySize;
}
else
{
return null;
}
// Try to get the central directory record offset
if (cdrOffset < 0 || cdrOffset >= data.Length)
return null;
// Seek to the first central directory record
data.Seek(cdrOffset, SeekOrigin.Begin);
// Cache the current offset
long currentOffset = data.Position;
// Read the central directory records
var cdrs = new List<CentralDirectoryFileHeader>();
while (data.Position < currentOffset + cdrSize)
{
// Read the central directory record
var cdr = ParseCentralDirectoryFileHeader(data);
if (cdr == null)
return null;
// Add the central directory record
cdrs.Add(cdr);
}
// Assign the central directory records
archive.CentralDirectoryHeaders = [.. cdrs];
#endregion
// TODO: Handle digital signature -- immediately following central directory records
#region Archive Extra Data Record
// Find the archive extra data record
long aedrOffset = SearchForArchiveExtraDataRecord(data, cdrOffset);
if (aedrOffset >= 0 && aedrOffset < data.Length)
{
// Seek to the archive extra data record
data.Seek(aedrOffset, SeekOrigin.Begin);
// Read the archive extra data record
var aedr = ParseArchiveExtraDataRecord(data);
if (aedr == null)
return null;
// Assign the archive extra data record
archive.ArchiveExtraDataRecord = aedr;
}
#endregion
#region Local File
// Setup all of the collections
var localFileHeaders = new List<LocalFileHeader?>();
var encryptionHeaders = new List<byte[]?>();
var fileData = new List<byte[]>(); // TODO: Should this data be read here?
var dataDescriptors = new List<DataDescriptor?>();
var zip64DataDescriptors = new List<DataDescriptor64?>();
// Read the local file headers
for (int i = 0; i < archive.CentralDirectoryHeaders.Length; i++)
{
var header = archive.CentralDirectoryHeaders[i];
// Get the local file header offset
long headerOffset = header.RelativeOffsetOfLocalHeader;
if (headerOffset == 0xFFFFFFFF && header.ExtraField != null)
{
// TODO: Parse into a proper structure instead of this
byte[] extraData = header.ExtraField;
if (BitConverter.ToUInt16(extraData, 0) == 0x0001)
headerOffset = BitConverter.ToInt64(extraData, 4);
}
if (headerOffset < 0 || headerOffset >= data.Length)
return null;
// Seek to the local file header
data.Seek(headerOffset, SeekOrigin.Begin);
// Try to parse the local header
var localFileHeader = ParseLocalFileHeader(data);
if (localFileHeader == null)
{
// Add a placeholder null item
localFileHeaders.Add(null);
encryptionHeaders.Add(null);
fileData.Add([]);
dataDescriptors.Add(null);
zip64DataDescriptors.Add(null);
continue;
}
// Add the local file header
localFileHeaders.Add(localFileHeader);
// Only read the encryption header if necessary
#if NET20 || NET35
if ((header.Flags & GeneralPurposeBitFlags.FileEncrypted) != 0)
#else
if (header.Flags.HasFlag(GeneralPurposeBitFlags.FileEncrypted))
#endif
{
// Try to read the encryption header data -- TODO: Verify amount to read
byte[] encryptionHeader = data.ReadBytes(12);
if (encryptionHeader.Length != 12)
return null;
// Add the encryption header
encryptionHeaders.Add(encryptionHeader);
}
else
{
// Add the null encryption header
encryptionHeaders.Add(null);
}
// Try to read the file data
byte[] fileDatum = data.ReadBytes((int)header.CompressedSize);
if (fileDatum.Length < header.CompressedSize)
return null;
// Add the file data
fileData.Add(fileDatum);
// Only read the data descriptor if necessary
#if NET20 || NET35
if ((header.Flags & GeneralPurposeBitFlags.NoCRC) != 0)
#else
if (header.Flags.HasFlag(GeneralPurposeBitFlags.NoCRC))
#endif
{
// Select the data descriptor that is being used
if (zip64)
{
// Try to parse the data descriptor
var dataDescriptor64 = ParseDataDescriptor64(data);
if (dataDescriptor64 == null)
return null;
// Add the data descriptor
dataDescriptors.Add(null);
zip64DataDescriptors.Add(dataDescriptor64);
}
else
{
// Try to parse the data descriptor
var dataDescriptor = ParseDataDescriptor(data);
if (dataDescriptor == null)
return null;
// Add the data descriptor
dataDescriptors.Add(dataDescriptor);
zip64DataDescriptors.Add(null);
}
}
else
{
// Add the null data descriptor
dataDescriptors.Add(null);
zip64DataDescriptors.Add(null);
}
}
// Assign the local file headers
archive.LocalFileHeaders = [.. localFileHeaders];
// Assign the encryption headers
archive.EncryptionHeaders = [.. encryptionHeaders];
// Assign the file data
archive.FileData = [.. fileData];
// Assign the data descriptors
archive.DataDescriptors = [.. dataDescriptors];
archive.ZIP64DataDescriptors = [.. zip64DataDescriptors];
#endregion
// TODO: Handle archive decryption header
return archive;
}
/// <summary>
/// Search for the end of central directory record
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Position of the end of central directory record, -1 on error</returns>
public static long SearchForEndOfCentralDirectoryRecord(Stream data)
{
// Cache the current offset
long current = data.Position;
// Seek to the minimum size of the record from the end
data.Seek(-22, SeekOrigin.End);
// Attempt to find the end of central directory signature
while (data.Position > 0)
{
// Read the potential signature
uint possibleSignature = data.ReadUInt32();
if (possibleSignature == EndOfCentralDirectoryRecordSignature)
{
long signaturePosition = data.Position - 4;
data.Seek(current, SeekOrigin.Begin);
return signaturePosition;
}
// If we find any other signature
switch (possibleSignature)
{
case ArchiveExtraDataRecordSignature:
case CentralDirectoryFileHeaderSignature:
case DataDescriptorSignature:
case DigitalSignatureSignature:
case EndOfCentralDirectoryLocator64Signature:
case EndOfCentralDirectoryRecord64Signature:
case LocalFileHeaderSignature:
data.Seek(current, SeekOrigin.Begin);
return -1;
}
// Seek backward 5 bytes, if possible
data.Seek(-5, SeekOrigin.Current);
}
// No signature was found
data.Seek(current, SeekOrigin.Begin);
return -1;
}
/// <summary>
/// Parse a Stream into an end of central directory record
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled end of central directory record on success, null on error</returns>
public static EndOfCentralDirectoryRecord? ParseEndOfCentralDirectoryRecord(Stream data)
{
// TODO: Use marshalling here instead of building
var record = new EndOfCentralDirectoryRecord();
record.Signature = data.ReadUInt32();
if (record.Signature != EndOfCentralDirectoryRecordSignature)
return null;
record.DiskNumber = data.ReadUInt16();
record.StartDiskNumber = data.ReadUInt16();
record.TotalEntriesOnDisk = data.ReadUInt16();
record.TotalEntries = data.ReadUInt16();
record.CentralDirectorySize = data.ReadUInt32();
record.CentralDirectoryOffset = data.ReadUInt32();
record.FileCommentLength = data.ReadUInt16();
if (record.FileCommentLength > 0 && data.Position + record.FileCommentLength <= data.Length)
{
byte[] commentBytes = data.ReadBytes(record.FileCommentLength);
if (commentBytes.Length != record.FileCommentLength)
return null;
record.FileComment = Encoding.ASCII.GetString(commentBytes);
}
return record;
}
/// <summary>
/// Search for the ZIP64 end of central directory locator
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Position of the ZIP64 end of central directory locator, -1 on error</returns>
public static long SearchForZIP64EndOfCentralDirectoryLocator(Stream data)
{
// Cache the current offset
long current = data.Position;
// Seek to the minimum size of the record from the minimum start
// of theend of central directory record
data.Seek(-22 + -20, SeekOrigin.Current);
// Attempt to find the ZIP64 end of central directory locator signature
while (data.Position > 0)
{
// Read the potential signature
uint possibleSignature = data.ReadUInt32();
if (possibleSignature == EndOfCentralDirectoryLocator64Signature)
{
long signaturePosition = data.Position - 4;
data.Seek(current, SeekOrigin.Begin);
return signaturePosition;
}
// If we find any other signature
switch (possibleSignature)
{
case ArchiveExtraDataRecordSignature:
case CentralDirectoryFileHeaderSignature:
case DataDescriptorSignature:
case DigitalSignatureSignature:
case EndOfCentralDirectoryRecordSignature:
case EndOfCentralDirectoryRecord64Signature:
case LocalFileHeaderSignature:
data.Seek(current, SeekOrigin.Begin);
return -1;
}
// Seek backward 5 bytes, if possible
data.Seek(-5, SeekOrigin.Current);
}
// No signature was found
data.Seek(current, SeekOrigin.Begin);
return -1;
}
/// <summary>
/// Parse a Stream into a ZIP64 end of central directory locator
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ZIP64 end of central directory locator on success, null on error</returns>
public static EndOfCentralDirectoryLocator64? ParseEndOfCentralDirectoryLocator64(Stream data)
{
return data.ReadType<EndOfCentralDirectoryLocator64>();
}
/// <summary>
/// Parse a Stream into a ZIP64 end of central directory record
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ZIP64 end of central directory record on success, null on error</returns>
public static EndOfCentralDirectoryRecord64? ParseEndOfCentralDirectoryRecord64(Stream data)
{
// TODO: Use marshalling here instead of building
var record = new EndOfCentralDirectoryRecord64();
record.Signature = data.ReadUInt32();
if (record.Signature != EndOfCentralDirectoryRecord64Signature)
return null;
record.DirectoryRecordSize = data.ReadUInt64();
record.HostSystem = (HostSystem)data.ReadByteValue();
record.VersionMadeBy = data.ReadByteValue();
record.VersionNeededToExtract = data.ReadUInt16();
record.DiskNumber = data.ReadUInt32();
record.StartDiskNumber = data.ReadUInt32();
record.TotalEntriesOnDisk = data.ReadUInt64();
record.TotalEntries = data.ReadUInt64();
record.CentralDirectorySize = data.ReadUInt64();
record.CentralDirectoryOffset = data.ReadUInt64();
// TODO: Handle the ExtensibleDataSector -- How to detect if exists?
return record;
}
/// <summary>
/// Parse a Stream into a central directory file header
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled central directory file header on success, null on error</returns>
public static CentralDirectoryFileHeader? ParseCentralDirectoryFileHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var header = new CentralDirectoryFileHeader();
header.Signature = data.ReadUInt32();
if (header.Signature != CentralDirectoryFileHeaderSignature)
return null;
header.HostSystem = (HostSystem)data.ReadByteValue();
header.VersionMadeBy = data.ReadByteValue();
header.VersionNeededToExtract = data.ReadUInt16();
header.Flags = (GeneralPurposeBitFlags)data.ReadUInt16();
header.CompressionMethod = (CompressionMethod)data.ReadUInt16();
header.LastModifedFileTime = data.ReadUInt16();
header.LastModifiedFileDate = data.ReadUInt16();
header.CRC32 = data.ReadUInt32();
header.CompressedSize = data.ReadUInt32();
header.UncompressedSize = data.ReadUInt32();
header.FileNameLength = data.ReadUInt16();
header.ExtraFieldLength = data.ReadUInt16();
header.FileCommentLength = data.ReadUInt16();
header.DiskNumberStart = data.ReadUInt16();
header.InternalFileAttributes = (InternalFileAttributes)data.ReadUInt16();
header.ExternalFileAttributes = data.ReadUInt32();
header.RelativeOffsetOfLocalHeader = data.ReadUInt32();
if (header.FileNameLength > 0 && data.Position + header.FileNameLength <= data.Length)
{
byte[] filenameBytes = data.ReadBytes(header.FileNameLength);
if (filenameBytes.Length != header.FileNameLength)
return null;
header.FileName = Encoding.ASCII.GetString(filenameBytes);
}
if (header.ExtraFieldLength > 0 && data.Position + header.ExtraFieldLength <= data.Length)
{
byte[] extraBytes = data.ReadBytes(header.ExtraFieldLength);
if (extraBytes.Length != header.ExtraFieldLength)
return null;
header.ExtraField = extraBytes;
}
if (header.FileCommentLength > 0 && data.Position + header.FileCommentLength <= data.Length)
{
byte[] commentBytes = data.ReadBytes(header.FileCommentLength);
if (commentBytes.Length != header.FileCommentLength)
return null;
header.FileComment = Encoding.ASCII.GetString(commentBytes);
}
return header;
}
/// <summary>
/// Search for the archive extra data record
/// </summary>
/// <param name="data">Stream to parse</param>
/// <param name="centralDirectoryoffset">Offset to the first central directory record</param>
/// <returns>Position of the archive extra data record, -1 on error</returns>
public static long SearchForArchiveExtraDataRecord(Stream data, long centralDirectoryoffset)
{
// Cache the current offset
long current = data.Position;
// Seek to the minimum size of the record from the central directory
data.Seek(centralDirectoryoffset - 8, SeekOrigin.Begin);
// Attempt to find the end of central directory signature
while (data.Position > 0)
{
// Read the potential signature
uint possibleSignature = data.ReadUInt32();
if (possibleSignature == ArchiveExtraDataRecordSignature)
{
long signaturePosition = data.Position - 4;
data.Seek(current, SeekOrigin.Begin);
return signaturePosition;
}
// If we find any other signature
switch (possibleSignature)
{
case CentralDirectoryFileHeaderSignature:
case DataDescriptorSignature:
case DigitalSignatureSignature:
case EndOfCentralDirectoryLocator64Signature:
case EndOfCentralDirectoryRecordSignature:
case EndOfCentralDirectoryRecord64Signature:
case LocalFileHeaderSignature:
data.Seek(current, SeekOrigin.Begin);
return -1;
}
// Seek backward 5 bytes, if possible
data.Seek(-5, SeekOrigin.Current);
}
// No signature was found
data.Seek(current, SeekOrigin.Begin);
return -1;
}
/// <summary>
/// Parse a Stream into an archive extra data record
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled archive extra data record on success, null on error</returns>
public static ArchiveExtraDataRecord? ParseArchiveExtraDataRecord(Stream data)
{
// TODO: Use marshalling here instead of building
var record = new ArchiveExtraDataRecord();
record.Signature = data.ReadUInt32();
if (record.Signature != ArchiveExtraDataRecordSignature)
return null;
record.ExtraFieldLength = data.ReadUInt32();
if (record.ExtraFieldLength > 0 && data.Position + record.ExtraFieldLength <= data.Length)
{
byte[] extraBytes = data.ReadBytes((int)record.ExtraFieldLength);
if (extraBytes.Length != record.ExtraFieldLength)
return null;
record.ExtraFieldData = extraBytes;
}
return record;
}
/// <summary>
/// Parse a Stream into a local file header
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled local file header on success, null on error</returns>
public static LocalFileHeader? ParseLocalFileHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var header = new LocalFileHeader();
header.Signature = data.ReadUInt32();
if (header.Signature != LocalFileHeaderSignature)
return null;
header.Version = data.ReadUInt16();
header.Flags = (GeneralPurposeBitFlags)data.ReadUInt16();
header.CompressionMethod = (CompressionMethod)data.ReadUInt16();
header.LastModifedFileTime = data.ReadUInt16();
header.LastModifiedFileDate = data.ReadUInt16();
header.CRC32 = data.ReadUInt32();
header.CompressedSize = data.ReadUInt32();
header.UncompressedSize = data.ReadUInt32();
header.FileNameLength = data.ReadUInt16();
header.ExtraFieldLength = data.ReadUInt16();
if (header.FileNameLength > 0 && data.Position + header.FileNameLength <= data.Length)
{
byte[] filenameBytes = data.ReadBytes(header.FileNameLength);
if (filenameBytes.Length != header.FileNameLength)
return null;
header.FileName = Encoding.ASCII.GetString(filenameBytes);
}
if (header.ExtraFieldLength > 0 && data.Position + header.ExtraFieldLength <= data.Length)
{
byte[] extraBytes = data.ReadBytes(header.ExtraFieldLength);
if (extraBytes.Length != header.ExtraFieldLength)
return null;
header.ExtraField = extraBytes;
}
return header;
}
/// <summary>
/// Parse a Stream into a data descriptor
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled data descriptor on success, null on error</returns>
public static DataDescriptor? ParseDataDescriptor(Stream data)
{
// TODO: Use marshalling here instead of building
var dataDescriptor = new DataDescriptor();
// Signatures are expected but not required
dataDescriptor.Signature = data.ReadUInt32();
if (dataDescriptor.Signature != DataDescriptorSignature)
data.Seek(-4, SeekOrigin.Current);
dataDescriptor.CRC32 = data.ReadUInt32();
dataDescriptor.CompressedSize = data.ReadUInt32();
dataDescriptor.UncompressedSize = data.ReadUInt32();
return dataDescriptor;
}
/// <summary>
/// Parse a Stream into a ZIP64 data descriptor
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled ZIP64 data descriptor on success, null on error</returns>
public static DataDescriptor64? ParseDataDescriptor64(Stream data)
{
// TODO: Use marshalling here instead of building
var zip64DataDescriptor = new DataDescriptor64();
// Signatures are expected but not required
zip64DataDescriptor.Signature = data.ReadUInt32();
if (zip64DataDescriptor.Signature != DataDescriptorSignature)
data.Seek(-4, SeekOrigin.Current);
zip64DataDescriptor.CRC32 = data.ReadUInt32();
zip64DataDescriptor.CompressedSize = data.ReadUInt64();
zip64DataDescriptor.UncompressedSize = data.ReadUInt64();
return zip64DataDescriptor;
}
}
}

View File

@@ -203,7 +203,7 @@ namespace SabreTools.Serialization.Deserializers
// Try to parse the debug table
data.Seek(debugTableAddress, SeekOrigin.Begin);
int endOffset = (int)(debugTableAddress + optionalHeader.Debug.Size);
var debugTable = ParseDebugTable(data, endOffset, executable.SectionTable);
var debugTable = ParseDebugTable(data, endOffset);
if (debugTable == null)
return null;
@@ -291,20 +291,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled executable header on success, null on error</returns>
public static COFFFileHeader ParseCOFFFileHeader(Stream data)
public static COFFFileHeader? ParseCOFFFileHeader(Stream data)
{
// TODO: Use marshalling here instead of building
var fileHeader = new COFFFileHeader();
fileHeader.Machine = (MachineType)data.ReadUInt16();
fileHeader.NumberOfSections = data.ReadUInt16();
fileHeader.TimeDateStamp = data.ReadUInt32();
fileHeader.PointerToSymbolTable = data.ReadUInt32();
fileHeader.NumberOfSymbols = data.ReadUInt32();
fileHeader.SizeOfOptionalHeader = data.ReadUInt16();
fileHeader.Characteristics = (Characteristics)data.ReadUInt16();
return fileHeader;
return data.ReadType<COFFFileHeader>();
}
/// <summary>
@@ -380,97 +369,52 @@ namespace SabreTools.Serialization.Deserializers
#region Data Directories
if (optionalHeader.NumberOfRvaAndSizes >= 1 && data.Position - initialOffset < optionalSize)
{
optionalHeader.ExportTable = new DataDirectory();
optionalHeader.ExportTable.VirtualAddress = data.ReadUInt32();
optionalHeader.ExportTable.Size = data.ReadUInt32();
}
optionalHeader.ExportTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 2 && data.Position - initialOffset < optionalSize)
{
optionalHeader.ImportTable = new DataDirectory();
optionalHeader.ImportTable.VirtualAddress = data.ReadUInt32();
optionalHeader.ImportTable.Size = data.ReadUInt32();
}
optionalHeader.ImportTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 3 && data.Position - initialOffset < optionalSize)
{
optionalHeader.ResourceTable = new DataDirectory();
optionalHeader.ResourceTable.VirtualAddress = data.ReadUInt32();
optionalHeader.ResourceTable.Size = data.ReadUInt32();
}
optionalHeader.ResourceTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 4 && data.Position - initialOffset < optionalSize)
{
optionalHeader.ExceptionTable = new DataDirectory();
optionalHeader.ExceptionTable.VirtualAddress = data.ReadUInt32();
optionalHeader.ExceptionTable.Size = data.ReadUInt32();
}
optionalHeader.ExceptionTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 5 && data.Position - initialOffset < optionalSize)
{
optionalHeader.CertificateTable = new DataDirectory();
optionalHeader.CertificateTable.VirtualAddress = data.ReadUInt32();
optionalHeader.CertificateTable.Size = data.ReadUInt32();
}
optionalHeader.CertificateTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 6 && data.Position - initialOffset < optionalSize)
{
optionalHeader.BaseRelocationTable = new DataDirectory();
optionalHeader.BaseRelocationTable.VirtualAddress = data.ReadUInt32();
optionalHeader.BaseRelocationTable.Size = data.ReadUInt32();
}
optionalHeader.BaseRelocationTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 7 && data.Position - initialOffset < optionalSize)
{
optionalHeader.Debug = new DataDirectory();
optionalHeader.Debug.VirtualAddress = data.ReadUInt32();
optionalHeader.Debug.Size = data.ReadUInt32();
}
optionalHeader.Debug = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 8 && data.Position - initialOffset < optionalSize)
{
optionalHeader.Architecture = data.ReadUInt64();
}
if (optionalHeader.NumberOfRvaAndSizes >= 9 && data.Position - initialOffset < optionalSize)
{
optionalHeader.GlobalPtr = new DataDirectory();
optionalHeader.GlobalPtr.VirtualAddress = data.ReadUInt32();
optionalHeader.GlobalPtr.Size = data.ReadUInt32();
}
optionalHeader.GlobalPtr = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 10 && data.Position - initialOffset < optionalSize)
{
optionalHeader.ThreadLocalStorageTable = new DataDirectory();
optionalHeader.ThreadLocalStorageTable.VirtualAddress = data.ReadUInt32();
optionalHeader.ThreadLocalStorageTable.Size = data.ReadUInt32();
}
optionalHeader.ThreadLocalStorageTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 11 && data.Position - initialOffset < optionalSize)
{
optionalHeader.LoadConfigTable = new DataDirectory();
optionalHeader.LoadConfigTable.VirtualAddress = data.ReadUInt32();
optionalHeader.LoadConfigTable.Size = data.ReadUInt32();
}
optionalHeader.LoadConfigTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 12 && data.Position - initialOffset < optionalSize)
{
optionalHeader.BoundImport = new DataDirectory();
optionalHeader.BoundImport.VirtualAddress = data.ReadUInt32();
optionalHeader.BoundImport.Size = data.ReadUInt32();
}
optionalHeader.BoundImport = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 13 && data.Position - initialOffset < optionalSize)
{
optionalHeader.ImportAddressTable = new DataDirectory();
optionalHeader.ImportAddressTable.VirtualAddress = data.ReadUInt32();
optionalHeader.ImportAddressTable.Size = data.ReadUInt32();
}
optionalHeader.ImportAddressTable = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 14 && data.Position - initialOffset < optionalSize)
{
optionalHeader.DelayImportDescriptor = new DataDirectory();
optionalHeader.DelayImportDescriptor.VirtualAddress = data.ReadUInt32();
optionalHeader.DelayImportDescriptor.Size = data.ReadUInt32();
}
optionalHeader.DelayImportDescriptor = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 15 && data.Position - initialOffset < optionalSize)
{
optionalHeader.CLRRuntimeHeader = new DataDirectory();
optionalHeader.CLRRuntimeHeader.VirtualAddress = data.ReadUInt32();
optionalHeader.CLRRuntimeHeader.Size = data.ReadUInt32();
}
optionalHeader.CLRRuntimeHeader = data.ReadType<DataDirectory>();
if (optionalHeader.NumberOfRvaAndSizes >= 16 && data.Position - initialOffset < optionalSize)
{
optionalHeader.Reserved = data.ReadUInt64();
}
#endregion
@@ -551,7 +495,7 @@ namespace SabreTools.Serialization.Deserializers
entry.Value = data.ReadUInt32();
entry.SectionNumber = data.ReadUInt16();
entry.SymbolType = (SymbolType)data.ReadUInt16();
entry.StorageClass = (StorageClass)data.ReadByte();
entry.StorageClass = (StorageClass)data.ReadByteValue();
entry.NumberOfAuxSymbols = data.ReadByteValue();
coffSymbolTable[i] = entry;
@@ -695,12 +639,12 @@ namespace SabreTools.Serialization.Deserializers
while (totalSize > 0 && data.Position < data.Length)
{
long initialPosition = data.Position;
string? str = data.ReadString();
string? str = data.ReadNullTerminatedAnsiString();
strings.Add(str ?? string.Empty);
totalSize -= (uint)(data.Position - initialPosition);
}
coffStringTable.Strings = strings.ToArray();
coffStringTable.Strings = [.. strings];
return coffStringTable;
}
@@ -724,7 +668,7 @@ namespace SabreTools.Serialization.Deserializers
entry.CertificateType = (WindowsCertificateType)data.ReadUInt16();
int certificateDataLength = (int)(entry.Length - 8);
if (certificateDataLength > 0)
if (certificateDataLength > 0 && data.Position + certificateDataLength <= data.Length)
entry.Certificate = data.ReadBytes(certificateDataLength);
attributeCertificateTable.Add(entry);
@@ -742,21 +686,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled delay-load directory table on success, null on error</returns>
public static DelayLoadDirectoryTable ParseDelayLoadDirectoryTable(Stream data)
public static DelayLoadDirectoryTable? ParseDelayLoadDirectoryTable(Stream data)
{
// TODO: Use marshalling here instead of building
var delayLoadDirectoryTable = new DelayLoadDirectoryTable();
delayLoadDirectoryTable.Attributes = data.ReadUInt32();
delayLoadDirectoryTable.Name = data.ReadUInt32();
delayLoadDirectoryTable.ModuleHandle = data.ReadUInt32();
delayLoadDirectoryTable.DelayImportAddressTable = data.ReadUInt32();
delayLoadDirectoryTable.DelayImportNameTable = data.ReadUInt32();
delayLoadDirectoryTable.BoundDelayImportTable = data.ReadUInt32();
delayLoadDirectoryTable.UnloadDelayImportTable = data.ReadUInt32();
delayLoadDirectoryTable.TimeStamp = data.ReadUInt32();
return delayLoadDirectoryTable;
return data.ReadType<DelayLoadDirectoryTable>();
}
/// <summary>
@@ -771,7 +703,7 @@ namespace SabreTools.Serialization.Deserializers
// TODO: Use marshalling here instead of building
var baseRelocationTable = new List<BaseRelocationBlock>();
while (data.Position < endOffset)
while (data.Position < endOffset && data.Position < data.Length)
{
var baseRelocationBlock = new BaseRelocationBlock();
@@ -792,12 +724,12 @@ namespace SabreTools.Serialization.Deserializers
totalSize += 2;
}
baseRelocationBlock.TypeOffsetFieldEntries = typeOffsetFieldEntries.ToArray();
baseRelocationBlock.TypeOffsetFieldEntries = [.. typeOffsetFieldEntries];
baseRelocationTable.Add(baseRelocationBlock);
}
return baseRelocationTable.ToArray();
return [.. baseRelocationTable];
}
/// <summary>
@@ -805,32 +737,24 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <param name="endOffset">First address not part of the debug table</param>
/// <param name="sections">Section table to use for virtual address translation</param>
/// <returns>Filled debug table on success, null on error</returns>
public static DebugTable ParseDebugTable(Stream data, int endOffset, SectionHeader?[] sections)
public static DebugTable? ParseDebugTable(Stream data, int endOffset)
{
// TODO: Use marshalling here instead of building
var debugTable = new DebugTable();
var debugDirectoryTable = new List<DebugDirectoryEntry>();
while (data.Position < endOffset)
while (data.Position < endOffset && data.Position < data.Length)
{
var debugDirectoryEntry = new DebugDirectoryEntry();
debugDirectoryEntry.Characteristics = data.ReadUInt32();
debugDirectoryEntry.TimeDateStamp = data.ReadUInt32();
debugDirectoryEntry.MajorVersion = data.ReadUInt16();
debugDirectoryEntry.MinorVersion = data.ReadUInt16();
debugDirectoryEntry.DebugType = (DebugType)data.ReadUInt32();
debugDirectoryEntry.SizeOfData = data.ReadUInt32();
debugDirectoryEntry.AddressOfRawData = data.ReadUInt32();
debugDirectoryEntry.PointerToRawData = data.ReadUInt32();
var debugDirectoryEntry = data.ReadType<DebugDirectoryEntry>();
if (debugDirectoryEntry == null)
return null;
debugDirectoryTable.Add(debugDirectoryEntry);
}
debugTable.DebugDirectoryTable = debugDirectoryTable.ToArray();
debugTable.DebugDirectoryTable = [.. debugDirectoryTable];
// TODO: Should we read the debug data in? Most of it is unformatted or undocumented
// TODO: Implement .debug$F (Object Only) / IMAGE_DEBUG_TYPE_FPO
@@ -844,7 +768,7 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="sections">Section table to use for virtual address translation</param>
/// <returns>Filled export table on success, null on error</returns>
public static ExportTable ParseExportTable(Stream data, SectionHeader?[] sections)
public static ExportTable? ParseExportTable(Stream data, SectionHeader?[] sections)
{
// TODO: Use marshalling here instead of building
var exportTable = new ExportTable();
@@ -871,7 +795,7 @@ namespace SabreTools.Serialization.Deserializers
uint nameAddress = exportDirectoryTable.NameRVA.ConvertVirtualAddress(sections);
data.Seek(nameAddress, SeekOrigin.Begin);
string? name = data.ReadString(Encoding.ASCII);
string? name = data.ReadNullTerminatedAnsiString();
exportDirectoryTable.Name = name;
}
@@ -885,11 +809,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < exportDirectoryTable.AddressTableEntries; i++)
{
var addressTableEntry = new ExportAddressTableEntry();
// TODO: Use the optional header address and length to determine if export or forwarder
addressTableEntry.ExportRVA = data.ReadUInt32();
addressTableEntry.ForwarderRVA = addressTableEntry.ExportRVA;
var addressTableEntry = data.ReadType<ExportAddressTableEntry>();
if (addressTableEntry == null)
return null;
exportAddressTable[i] = addressTableEntry;
}
@@ -944,7 +866,7 @@ namespace SabreTools.Serialization.Deserializers
exportNameTable.Strings = new string[exportDirectoryTable.NumberOfNamePointers];
for (int i = 0; i < exportDirectoryTable.NumberOfNamePointers; i++)
{
string? str = data.ReadString(Encoding.ASCII);
string? str = data.ReadNullTerminatedAnsiString();
exportNameTable.Strings[i] = str ?? string.Empty;
}
@@ -961,7 +883,7 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="magic">Optional header magic number indicating PE32 or PE32+</param>
/// <param name="sections">Section table to use for virtual address translation</param>
/// <returns>Filled import table on success, null on error</returns>
public static ImportTable ParseImportTable(Stream data, OptionalHeaderMagicNumber magic, SectionHeader?[] sections)
public static ImportTable? ParseImportTable(Stream data, OptionalHeaderMagicNumber magic, SectionHeader?[] sections)
{
// TODO: Use marshalling here instead of building
var importTable = new ImportTable();
@@ -1006,7 +928,7 @@ namespace SabreTools.Serialization.Deserializers
uint nameAddress = importDirectoryTableEntry.NameRVA.ConvertVirtualAddress(sections);
data.Seek(nameAddress, SeekOrigin.Begin);
string? name = data.ReadString(Encoding.ASCII);
string? name = data.ReadNullTerminatedAnsiString();
importDirectoryTableEntry.Name = name;
}
@@ -1163,21 +1085,30 @@ namespace SabreTools.Serialization.Deserializers
int hintNameTableEntryAddress = hintNameTableEntryAddresses[i];
data.Seek(hintNameTableEntryAddress, SeekOrigin.Begin);
var hintNameTableEntry = new HintNameTableEntry();
hintNameTableEntry.Hint = data.ReadUInt16();
hintNameTableEntry.Name = data.ReadString(Encoding.ASCII);
var hintNameTableEntry = ParseHintNameTableEntry(data);
if (hintNameTableEntry == null)
return null;
importHintNameTable.Add(hintNameTableEntry);
}
}
}
importTable.HintNameTable = importHintNameTable.ToArray();
importTable.HintNameTable = [.. importHintNameTable];
return importTable;
}
/// <summary>
/// Parse a Stream into a hint name table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled hint name table entry on success, null on error</returns>
public static HintNameTableEntry? ParseHintNameTableEntry(Stream data)
{
return data.ReadType<HintNameTableEntry>();
}
/// <summary>
/// Parse a Stream into a resource directory table
/// </summary>
@@ -1233,7 +1164,7 @@ namespace SabreTools.Serialization.Deserializers
var resourceDirectoryString = new ResourceDirectoryString();
resourceDirectoryString.Length = data.ReadUInt16();
if (resourceDirectoryString.Length > 0)
if (resourceDirectoryString.Length > 0 && data.Position + resourceDirectoryString.Length <= data.Length)
resourceDirectoryString.UnicodeString = data.ReadBytes(resourceDirectoryString.Length * 2);
entry.Name = resourceDirectoryString;
@@ -1263,7 +1194,7 @@ namespace SabreTools.Serialization.Deserializers
// Read the data from the offset
offset = resourceDataEntry.DataRVA.ConvertVirtualAddress(sections);
if (offset > 0 && resourceDataEntry.Size > 0)
if (offset > 0 && resourceDataEntry.Size > 0 && offset + (int)resourceDataEntry.Size < data.Length)
{
data.Seek(offset, SeekOrigin.Begin);
resourceDataEntry.Data = data.ReadBytes((int)resourceDataEntry.Size);
@@ -1315,7 +1246,7 @@ namespace SabreTools.Serialization.Deserializers
resourceDirectoryTable.Entries[totalEntryCount] = new ResourceDirectoryEntry
{
Name = new ResourceDirectoryString { UnicodeString = Encoding.ASCII.GetBytes("HIDDEN RESOURCE") },
Name = new ResourceDirectoryString { UnicodeString = Encoding.Unicode.GetBytes("HIDDEN RESOURCE") },
IntegerID = uint.MaxValue,
DataEntryOffset = (uint)data.Position,
DataEntry = new ResourceDataEntry

View File

@@ -73,23 +73,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
byte[]? signature = data.ReadBytes(2);
if (signature == null)
if (header == null)
return null;
header.Signature = Encoding.ASCII.GetString(signature);
if (header.Signature != SignatureString)
return null;
header.MajorVersion = data.ReadByteValue();
header.MinorVersion = data.ReadByteValue();
header.FileCount = data.ReadUInt16();
header.TableSize = data.ReadByteValue();
header.CompressionFlags = data.ReadByteValue();
return header;
}
@@ -102,7 +92,7 @@ namespace SabreTools.Serialization.Deserializers
private static FileDescriptor ParseFileDescriptor(Stream data, byte minorVersion)
{
// TODO: Use marshalling here instead of building
FileDescriptor fileDescriptor = new FileDescriptor();
var fileDescriptor = new FileDescriptor();
fileDescriptor.FileNameSize = ReadVariableLength(data);
if (fileDescriptor.FileNameSize > 0)

View File

@@ -0,0 +1,35 @@
using System.IO;
using System.Text;
using SabreTools.IO.Extensions;
namespace SabreTools.Serialization.Deserializers
{
public class SFB : BaseBinaryDeserializer<Models.PlayStation3.SFB>
{
/// <inheritdoc/>
public override Models.PlayStation3.SFB? Deserialize(Stream? data)
{
// If the data is invalid
if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead)
return null;
// If the offset is out of bounds
if (data.Position < 0 || data.Position >= data.Length)
return null;
// Cache the current offset
int initialOffset = (int)data.Position;
// Deserialize the SFB
var sfb = data.ReadType<Models.PlayStation3.SFB>();
if (sfb == null)
return null;
string magic = Encoding.ASCII.GetString(sfb!.Magic!);
if (magic != ".SFB")
return null;
return sfb;
}
}
}

View File

@@ -0,0 +1,91 @@
using System.IO;
using System.Text;
using SabreTools.IO.Extensions;
namespace SabreTools.Serialization.Deserializers
{
public class SFO : BaseBinaryDeserializer<Models.PlayStation3.SFO>
{
/// <inheritdoc/>
public override Models.PlayStation3.SFO? Deserialize(Stream? data)
{
// If the data is invalid
if (data == null || data.Length == 0 || !data.CanSeek || !data.CanRead)
return null;
// If the offset is out of bounds
if (data.Position < 0 || data.Position >= data.Length)
return null;
// Cache the current offset
int initialOffset = (int)data.Position;
// Create a new SFO to fill
var sfo = new Models.PlayStation3.SFO();
#region Header
// Try to parse the header
var header = ParseHeader(data);
if (header == null)
return null;
// Assign the header
sfo.Header = header;
#endregion
#region Index Table
// TODO: Determine how many entries are in the index table
#endregion
#region Key Table
// TODO: Finish implementation
#endregion
// Padding
// TODO: Finish implementation
#region Data Table
// TODO: Finish implementation
#endregion
return sfo;
}
/// <summary>
/// Parse a Stream into an SFO header
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled SFO header on success, null on error</returns>
public Models.PlayStation3.SFOHeader? ParseHeader(Stream data)
{
var sfoHeader = data.ReadType<Models.PlayStation3.SFOHeader>();
if (sfoHeader == null)
return null;
string magic = Encoding.ASCII.GetString(sfoHeader!.Magic!);
if (magic != "\0PSF")
return null;
return sfoHeader;
}
/// <summary>
/// Parse a Stream into an SFO index table entry
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled SFO index table entry on success, null on error</returns>
public Models.PlayStation3.SFOIndexTableEntry? ParseIndexTableEntry(Stream data)
{
return data.ReadType<Models.PlayStation3.SFOIndexTableEntry>();
}
}
}

View File

@@ -419,7 +419,7 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < stringCount; i++)
{
long currentPosition = data.Position - stringTableStart;
strings[currentPosition] = data.ReadString(Encoding.ASCII);
strings[currentPosition] = data.ReadNullTerminatedAnsiString();
}
// Assign the files

View File

@@ -48,7 +48,7 @@ namespace SabreTools.Serialization.Deserializers
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = new Header();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
@@ -65,7 +65,11 @@ namespace SabreTools.Serialization.Deserializers
header.Lumps = new Lump[HL_VBSP_LUMP_COUNT];
for (int i = 0; i < HL_VBSP_LUMP_COUNT; i++)
{
header.Lumps[i] = ParseLump(data, header.Version);
var lump = ParseLump(data, header.Version);
if (lump == null)
return null;
header.Lumps[i] = lump;
}
header.MapRevision = data.ReadInt32();
@@ -79,19 +83,9 @@ namespace SabreTools.Serialization.Deserializers
/// <param name="data">Stream to parse</param>
/// <param name="version">VBSP version</param>
/// <returns>Filled Half-Life 2 Level lump on success, null on error</returns>
private static Lump ParseLump(Stream data, int version)
private static Lump? ParseLump(Stream data, int version)
{
// TODO: Use marshalling here instead of building
Lump lump = new Lump();
lump.Offset = data.ReadUInt32();
lump.Length = data.ReadUInt32();
lump.Version = data.ReadUInt32();
lump.FourCC = new char[4];
for (int i = 0; i < 4; i++)
{
lump.FourCC[i] = (char)data.ReadByte();
}
return data.ReadType<Lump>();
// This block was commented out because test VBSPs with header
// version 21 had the values in the "right" order already and
@@ -104,8 +98,8 @@ namespace SabreTools.Serialization.Deserializers
// lump.Offset = lump.Length;
// lump.Length = temp;
//}
return lump;
//
//return lump
}
}
}

View File

@@ -1,6 +1,5 @@
using System.Collections.Generic;
using System.IO;
using System.Text;
using SabreTools.IO.Extensions;
using SabreTools.Models.VPK;
using static SabreTools.Models.VPK.Constants;
@@ -31,6 +30,8 @@ namespace SabreTools.Serialization.Deserializers
// Try to parse the header
// The original version had no signature.
var header = ParseHeader(data);
if (header == null)
return null;
// Set the package header
file.Header = header;
@@ -56,6 +57,8 @@ namespace SabreTools.Serialization.Deserializers
// Create the directory items tree
var directoryItems = ParseDirectoryItemTree(data);
if (directoryItems == null)
return null;
// Set the directory items
file.DirectoryItems = directoryItems;
@@ -64,7 +67,10 @@ namespace SabreTools.Serialization.Deserializers
#region Archive Hashes
if (header?.Version == 2 && file.ExtendedHeader != null && file.ExtendedHeader.ArchiveHashLength > 0)
if (header?.Version == 2
&& file.ExtendedHeader != null
&& file.ExtendedHeader.ArchiveHashLength > 0
&& data.Position + file.ExtendedHeader.ArchiveHashLength <= data.Length)
{
// Create the archive hashes list
var archiveHashes = new List<ArchiveHash>();
@@ -76,10 +82,13 @@ namespace SabreTools.Serialization.Deserializers
while (data.Position < initialOffset + file.ExtendedHeader.ArchiveHashLength)
{
var archiveHash = ParseArchiveHash(data);
if (archiveHash == null)
return null;
archiveHashes.Add(archiveHash);
}
file.ArchiveHashes = archiveHashes.ToArray();
file.ArchiveHashes = [.. archiveHashes];
}
#endregion
@@ -94,19 +103,15 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Valve Package header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
header.Signature = data.ReadUInt32();
if (header == null)
return null;
if (header.Signature != SignatureUInt32)
return null;
header.Version = data.ReadUInt32();
if (header.Version > 2)
return null;
header.DirectoryLength = data.ReadUInt32();
return header;
}
@@ -115,17 +120,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Valve Package extended header on success, null on error</returns>
private static ExtendedHeader ParseExtendedHeader(Stream data)
private static ExtendedHeader? ParseExtendedHeader(Stream data)
{
// TODO: Use marshalling here instead of building
ExtendedHeader extendedHeader = new ExtendedHeader();
extendedHeader.Dummy0 = data.ReadUInt32();
extendedHeader.ArchiveHashLength = data.ReadUInt32();
extendedHeader.ExtraLength = data.ReadUInt32();
extendedHeader.Dummy1 = data.ReadUInt32();
return extendedHeader;
return data.ReadType<ExtendedHeader>();
}
/// <summary>
@@ -133,17 +130,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Valve Package archive hash on success, null on error</returns>
private static ArchiveHash ParseArchiveHash(Stream data)
private static ArchiveHash? ParseArchiveHash(Stream data)
{
// TODO: Use marshalling here instead of building
ArchiveHash archiveHash = new ArchiveHash();
archiveHash.ArchiveIndex = data.ReadUInt32();
archiveHash.ArchiveOffset = data.ReadUInt32();
archiveHash.Length = data.ReadUInt32();
archiveHash.Hash = data.ReadBytes(0x10);
return archiveHash;
return data.ReadType<ArchiveHash>();
}
/// <summary>
@@ -151,7 +140,7 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Valve Package directory item tree on success, null on error</returns>
private static DirectoryItem[] ParseDirectoryItemTree(Stream data)
private static DirectoryItem[]? ParseDirectoryItemTree(Stream data)
{
// Create the directory items list
var directoryItems = new List<DirectoryItem>();
@@ -159,7 +148,7 @@ namespace SabreTools.Serialization.Deserializers
while (true)
{
// Get the extension
string? extensionString = data.ReadString(Encoding.ASCII);
string? extensionString = data.ReadNullTerminatedAnsiString();
if (string.IsNullOrEmpty(extensionString))
break;
@@ -172,7 +161,7 @@ namespace SabreTools.Serialization.Deserializers
while (true)
{
// Get the path
string? pathString = data.ReadString(Encoding.ASCII);
string? pathString = data.ReadNullTerminatedAnsiString();
if (string.IsNullOrEmpty(pathString))
break;
@@ -185,7 +174,7 @@ namespace SabreTools.Serialization.Deserializers
while (true)
{
// Get the name
string? nameString = data.ReadString(Encoding.ASCII);
string? nameString = data.ReadNullTerminatedAnsiString();
if (string.IsNullOrEmpty(nameString))
break;
@@ -197,6 +186,8 @@ namespace SabreTools.Serialization.Deserializers
// Get the directory item
var directoryItem = ParseDirectoryItem(data, extensionString!, pathString!, nameString!);
if (directoryItem == null)
return null;
// Add the directory item
directoryItems.Add(directoryItem);
@@ -212,9 +203,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Valve Package directory item on success, null on error</returns>
private static DirectoryItem ParseDirectoryItem(Stream data, string extension, string path, string name)
private static DirectoryItem? ParseDirectoryItem(Stream data, string extension, string path, string name)
{
DirectoryItem directoryItem = new DirectoryItem();
var directoryItem = new DirectoryItem();
directoryItem.Extension = extension;
directoryItem.Path = path;
@@ -222,13 +213,17 @@ namespace SabreTools.Serialization.Deserializers
// Get the directory entry
var directoryEntry = ParseDirectoryEntry(data);
if (directoryEntry == null)
return null;
// Set the directory entry
directoryItem.DirectoryEntry = directoryEntry;
// Get the preload data pointer
long preloadDataPointer = -1; int preloadDataLength = -1;
if (directoryEntry.ArchiveIndex == HL_VPK_NO_ARCHIVE && directoryEntry.EntryLength > 0)
if (directoryEntry.ArchiveIndex == HL_VPK_NO_ARCHIVE
&& directoryEntry.EntryLength > 0
&& data.Position + directoryEntry.EntryLength <= data.Length)
{
preloadDataPointer = directoryEntry.EntryOffset;
preloadDataLength = (int)directoryEntry.EntryLength;
@@ -241,7 +236,9 @@ namespace SabreTools.Serialization.Deserializers
// If we had a valid preload data pointer
byte[]? preloadData = null;
if (preloadDataPointer >= 0 && preloadDataLength > 0)
if (preloadDataPointer >= 0
&& preloadDataLength > 0
&& data.Position + preloadDataLength <= data.Length)
{
// Cache the current offset
long initialOffset = data.Position;
@@ -267,19 +264,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Valve Package directory entry on success, null on error</returns>
private static DirectoryEntry ParseDirectoryEntry(Stream data)
private static DirectoryEntry? ParseDirectoryEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryEntry directoryEntry = new DirectoryEntry();
directoryEntry.CRC = data.ReadUInt32();
directoryEntry.PreloadBytes = data.ReadUInt16();
directoryEntry.ArchiveIndex = data.ReadUInt16();
directoryEntry.EntryOffset = data.ReadUInt32();
directoryEntry.EntryLength = data.ReadUInt32();
directoryEntry.Dummy0 = data.ReadUInt16();
return directoryEntry;
return data.ReadType<DirectoryEntry>();
}
}
}

View File

@@ -52,6 +52,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < header.LumpCount; i++)
{
var lump = ParseLump(data);
if (lump == null)
return null;
file.Lumps[i] = lump;
}
@@ -104,20 +107,13 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled Half-Life Texture Package header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
if (header == null)
return null;
header.Signature = Encoding.ASCII.GetString(signature);
if (header.Signature != SignatureString)
return null;
header.LumpCount = data.ReadUInt32();
header.LumpOffset = data.ReadUInt32();
return header;
}
@@ -126,23 +122,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled Half-Life Texture Package lump on success, null on error</returns>
private static Lump ParseLump(Stream data)
private static Lump? ParseLump(Stream data)
{
// TODO: Use marshalling here instead of building
Lump lump = new Lump();
lump.Offset = data.ReadUInt32();
lump.DiskLength = data.ReadUInt32();
lump.Length = data.ReadUInt32();
lump.Type = data.ReadByteValue();
lump.Compression = data.ReadByteValue();
lump.Padding0 = data.ReadByteValue();
lump.Padding1 = data.ReadByteValue();
byte[]? name = data.ReadBytes(16);
if (name != null)
lump.Name = Encoding.ASCII.GetString(name).TrimEnd('\0');
return lump;
return data.ReadType<Lump>();
}
/// <summary>
@@ -182,7 +164,7 @@ namespace SabreTools.Serialization.Deserializers
lumpInfo.Width = data.ReadUInt32();
lumpInfo.Height = data.ReadUInt32();
lumpInfo.PixelOffset = data.ReadUInt32();
_ = data.ReadBytes(12); // Unknown data
lumpInfo.UnknownData = data.ReadBytes(12);
// Cache the current offset
long currentOffset = data.Position;

View File

@@ -46,6 +46,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < header.DirectoryEntryCount; i++)
{
var directoryEntry = ParseDirectoryEntry(data);
if (directoryEntry == null)
return null;
file.DirectoryEntries[i] = directoryEntry;
}
@@ -62,6 +65,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < header.PreloadDirectoryEntryCount; i++)
{
var directoryEntry = ParseDirectoryEntry(data);
if (directoryEntry == null)
return null;
file.PreloadDirectoryEntries[i] = directoryEntry;
}
}
@@ -79,6 +85,9 @@ namespace SabreTools.Serialization.Deserializers
for (int i = 0; i < header.PreloadDirectoryEntryCount; i++)
{
var directoryMapping = ParseDirectoryMapping(data);
if (directoryMapping == null)
return null;
file.PreloadDirectoryMappings[i] = directoryMapping;
}
}
@@ -135,29 +144,15 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled XBox Package File header on success, null on error</returns>
private static Header? ParseHeader(Stream data)
{
// TODO: Use marshalling here instead of building
Header header = new Header();
var header = data.ReadType<Header>();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
if (header == null)
return null;
header.Signature = Encoding.ASCII.GetString(signature);
if (header.Signature != HeaderSignatureString)
return null;
header.Version = data.ReadUInt32();
if (header.Version != 6)
return null;
header.PreloadDirectoryEntryCount = data.ReadUInt32();
header.DirectoryEntryCount = data.ReadUInt32();
header.PreloadBytes = data.ReadUInt32();
header.HeaderLength = data.ReadUInt32();
header.DirectoryItemCount = data.ReadUInt32();
header.DirectoryItemOffset = data.ReadUInt32();
header.DirectoryItemLength = data.ReadUInt32();
return header;
}
@@ -166,16 +161,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled XBox Package File directory entry on success, null on error</returns>
private static DirectoryEntry ParseDirectoryEntry(Stream data)
private static DirectoryEntry? ParseDirectoryEntry(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryEntry directoryEntry = new DirectoryEntry();
directoryEntry.FileNameCRC = data.ReadUInt32();
directoryEntry.EntryLength = data.ReadUInt32();
directoryEntry.EntryOffset = data.ReadUInt32();
return directoryEntry;
return data.ReadType<DirectoryEntry>();
}
/// <summary>
@@ -183,14 +171,9 @@ namespace SabreTools.Serialization.Deserializers
/// </summary>
/// <param name="data">Stream to parse</param>
/// <returns>Filled XBox Package File directory mapping on success, null on error</returns>
private static DirectoryMapping ParseDirectoryMapping(Stream data)
private static DirectoryMapping? ParseDirectoryMapping(Stream data)
{
// TODO: Use marshalling here instead of building
DirectoryMapping directoryMapping = new DirectoryMapping();
directoryMapping.PreloadDirectoryEntryIndex = data.ReadUInt16();
return directoryMapping;
return data.ReadType<DirectoryMapping>();
}
/// <summary>
@@ -214,7 +197,7 @@ namespace SabreTools.Serialization.Deserializers
data.Seek(directoryItem.NameOffset, SeekOrigin.Begin);
// Read the name
directoryItem.Name = data.ReadString(Encoding.ASCII);
directoryItem.Name = data.ReadNullTerminatedAnsiString();
// Seek back to the right position
data.Seek(currentPosition, SeekOrigin.Begin);
@@ -229,15 +212,10 @@ namespace SabreTools.Serialization.Deserializers
/// <returns>Filled XBox Package File footer on success, null on error</returns>
private static Footer? ParseFooter(Stream data)
{
// TODO: Use marshalling here instead of building
Footer footer = new Footer();
var footer = data.ReadType<Footer>();
footer.FileLength = data.ReadUInt32();
byte[]? signature = data.ReadBytes(4);
if (signature == null)
if (footer == null)
return null;
footer.Signature = Encoding.ASCII.GetString(signature);
if (footer.Signature != FooterSignatureString)
return null;

View File

@@ -9,13 +9,8 @@ namespace SabreTools.Serialization
/// </summary>
/// <param name="entry">Resource type information entry to check</param>
/// <returns>True if the entry is an integer type, false if an offset, null on error</returns>
public static bool? IsIntegerType(this ResourceTypeInformationEntry entry)
public static bool IsIntegerType(this ResourceTypeInformationEntry entry)
{
// We can't do anything with an invalid entry
if (entry == null)
return null;
// If the highest order bit is set, it's an integer type
return (entry.TypeID & 0x8000) != 0;
}
@@ -24,13 +19,8 @@ namespace SabreTools.Serialization
/// </summary>
/// <param name="entry">Resource type resource entry to check</param>
/// <returns>True if the entry is an integer type, false if an offset, null on error</returns>
public static bool? IsIntegerType(this ResourceTypeResourceEntry entry)
public static bool IsIntegerType(this ResourceTypeResourceEntry entry)
{
// We can't do anything with an invalid entry
if (entry == null)
return null;
// If the highest order bit is set, it's an integer type
return (entry.ResourceID & 0x8000) != 0;
}
@@ -41,10 +31,6 @@ namespace SabreTools.Serialization
/// <returns>SegmentEntryType corresponding to the type</returns>
public static SegmentEntryType GetEntryType(this EntryTableBundle entry)
{
// We can't do anything with an invalid entry
if (entry == null)
return SegmentEntryType.Unused;
// Determine the entry type based on segment indicator
if (entry.SegmentIndicator == 0x00)
return SegmentEntryType.Unused;

View File

@@ -102,21 +102,13 @@ namespace SabreTools.Serialization
/// <returns>A filled NB10 Program Database on success, null on error</returns>
public static NB10ProgramDatabase? AsNB10ProgramDatabase(this byte[] data, ref int offset)
{
// If we have data that's invalid, we can't do anything
if (data == null)
var nb10ProgramDatabase = data.ReadType<NB10ProgramDatabase>(ref offset);
if (nb10ProgramDatabase == null)
return null;
var nb10ProgramDatabase = new NB10ProgramDatabase();
nb10ProgramDatabase.Signature = data.ReadUInt32(ref offset);
if (nb10ProgramDatabase.Signature != 0x3031424E)
return null;
nb10ProgramDatabase.Offset = data.ReadUInt32(ref offset);
nb10ProgramDatabase.Timestamp = data.ReadUInt32(ref offset);
nb10ProgramDatabase.Age = data.ReadUInt32(ref offset);
nb10ProgramDatabase.PdbFileName = data.ReadString(ref offset, Encoding.ASCII); // TODO: Actually null-terminated UTF-8?
return nb10ProgramDatabase;
}
@@ -126,23 +118,23 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a database</param>
/// <param name="offset">Offset into the byte array</param>
/// <returns>A filled RSDS Program Database on success, null on error</returns>
public static RSDSProgramDatabase? AsRSDSProgramDatabase(this byte[]? data, ref int offset)
public static RSDSProgramDatabase? AsRSDSProgramDatabase(this byte[] data, ref int offset)
{
// If we have data that's invalid, we can't do anything
if (data == null)
var rsdsProgramDatabase = data.ReadType<RSDSProgramDatabase>(ref offset);
if (rsdsProgramDatabase == null)
return null;
var rsdsProgramDatabase = new RSDSProgramDatabase();
rsdsProgramDatabase.Signature = data.ReadUInt32(ref offset);
if (rsdsProgramDatabase.Signature != 0x53445352)
return null;
var guid = data.ReadBytes(ref offset, 0x10);
if (guid != null)
rsdsProgramDatabase.GUID = new Guid(guid);
rsdsProgramDatabase.Age = data.ReadUInt32(ref offset);
rsdsProgramDatabase.PathAndFileName = data.ReadString(ref offset, Encoding.ASCII); // TODO: Actually null-terminated UTF-8
#if NET20 || NET35 || NET40 || NET452 || NET462
// Convert ASCII string to UTF-8
if (rsdsProgramDatabase.PathAndFileName != null)
{
byte[] bytes = Encoding.ASCII.GetBytes(rsdsProgramDatabase.PathAndFileName);
rsdsProgramDatabase.PathAndFileName = Encoding.UTF8.GetString(bytes);
}
#endif
return rsdsProgramDatabase;
}
@@ -157,12 +149,8 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into overlay data</param>
/// <param name="offset">Offset into the byte array</param>
/// <returns>A filled SecuROM AddD overlay data on success, null on error</returns>
public static SecuROMAddD? AsSecuROMAddD(this byte[]? data, ref int offset)
public static SecuROMAddD? AsSecuROMAddD(this byte[] data, ref int offset)
{
// If we have data that's invalid, we can't do anything
if (data == null)
return null;
// Read in the table
var addD = new SecuROMAddD();
@@ -173,7 +161,7 @@ namespace SabreTools.Serialization
int originalOffset = offset;
addD.EntryCount = data.ReadUInt32(ref offset);
addD.Version = data.ReadString(ref offset, Encoding.ASCII);
addD.Version = data.ReadNullTerminatedAnsiString(ref offset);
if (string.IsNullOrEmpty(addD.Version))
offset = originalOffset + 0x10;
@@ -193,18 +181,9 @@ namespace SabreTools.Serialization
addD.Entries = new SecuROMAddDEntry[addD.EntryCount];
for (int i = 0; i < addD.EntryCount; i++)
{
var addDEntry = new SecuROMAddDEntry();
addDEntry.PhysicalOffset = data.ReadUInt32(ref offset);
addDEntry.Length = data.ReadUInt32(ref offset);
addDEntry.Unknown08h = data.ReadUInt32(ref offset);
addDEntry.Unknown0Ch = data.ReadUInt32(ref offset);
addDEntry.Unknown10h = data.ReadUInt32(ref offset);
addDEntry.Unknown14h = data.ReadUInt32(ref offset);
addDEntry.Unknown18h = data.ReadUInt32(ref offset);
addDEntry.Unknown1Ch = data.ReadUInt32(ref offset);
addDEntry.FileName = data.ReadString(ref offset, Encoding.ASCII);
addDEntry.Unknown2Ch = data.ReadUInt32(ref offset);
var addDEntry = data.ReadType<SecuROMAddDEntry>(ref offset);
if (addDEntry == null)
return null;
addD.Entries[i] = addDEntry;
}
@@ -223,7 +202,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a resource header</param>
/// <param name="offset">Offset into the byte array</param>
/// <returns>A filled resource header on success, null on error</returns>
public static ResourceHeader? AsResourceHeader(this byte[]? data, ref int offset)
public static ResourceHeader? AsResourceHeader(this byte[] data, ref int offset)
{
// If we have data that's invalid, we can't do anything
if (data == null)
@@ -267,12 +246,9 @@ namespace SabreTools.Serialization
// Read in the table
for (int i = 0; i < count; i++)
{
var acceleratorTableEntry = new AcceleratorTableEntry();
acceleratorTableEntry.Flags = (AcceleratorTableFlags)entry.Data.ReadUInt16(ref offset);
acceleratorTableEntry.Ansi = entry.Data.ReadUInt16(ref offset);
acceleratorTableEntry.Id = entry.Data.ReadUInt16(ref offset);
acceleratorTableEntry.Padding = entry.Data.ReadUInt16(ref offset);
var acceleratorTableEntry = entry.Data.ReadType<AcceleratorTableEntry>(ref offset);
if (acceleratorTableEntry == null)
return null;
table[i] = acceleratorTableEntry;
}
@@ -359,7 +335,7 @@ namespace SabreTools.Serialization
offset += sizeof(ushort);
// Read the menu resource as a string
dialogTemplateExtended.MenuResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplateExtended.MenuResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -395,7 +371,7 @@ namespace SabreTools.Serialization
offset += sizeof(ushort);
// Read the class resource as a string
dialogTemplateExtended.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplateExtended.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -426,7 +402,7 @@ namespace SabreTools.Serialization
else
{
// Read the title resource as a string
dialogTemplateExtended.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplateExtended.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -451,7 +427,7 @@ namespace SabreTools.Serialization
dialogTemplateExtended.Weight = entry.Data.ReadUInt16(ref offset);
dialogTemplateExtended.Italic = entry.Data.ReadByte(ref offset);
dialogTemplateExtended.CharSet = entry.Data.ReadByte(ref offset);
dialogTemplateExtended.Typeface = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplateExtended.Typeface = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
}
// Align to the DWORD boundary if we're not at the end
@@ -507,7 +483,7 @@ namespace SabreTools.Serialization
offset += sizeof(ushort);
// Read the class resource as a string
dialogItemTemplate.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogItemTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -537,7 +513,7 @@ namespace SabreTools.Serialization
else
{
// Read the title resource as a string
dialogItemTemplate.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogItemTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -609,7 +585,7 @@ namespace SabreTools.Serialization
offset += sizeof(ushort);
// Read the menu resource as a string
dialogTemplate.MenuResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplate.MenuResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -628,7 +604,11 @@ namespace SabreTools.Serialization
#region Class resource
currentOffset = offset;
ushort classResourceIdentifier = entry.Data.ReadUInt16(ref offset);
ushort classResourceIdentifier;
if (offset >= entry.Data.Length)
classResourceIdentifier = 0x0000;
else
classResourceIdentifier = entry.Data.ReadUInt16(ref offset);
offset = currentOffset;
// 0x0000 means no elements
@@ -645,7 +625,7 @@ namespace SabreTools.Serialization
offset += sizeof(ushort);
// Read the class resource as a string
dialogTemplate.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -664,7 +644,11 @@ namespace SabreTools.Serialization
#region Title resource
currentOffset = offset;
ushort titleResourceIdentifier = entry.Data.ReadUInt16(ref offset);
ushort titleResourceIdentifier;
if (offset >= entry.Data.Length)
titleResourceIdentifier = 0x0000;
else
titleResourceIdentifier = entry.Data.ReadUInt16(ref offset);
offset = currentOffset;
// 0x0000 means no elements
@@ -676,7 +660,7 @@ namespace SabreTools.Serialization
else
{
// Read the title resource as a string
dialogTemplate.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -700,7 +684,7 @@ namespace SabreTools.Serialization
dialogTemplate.PointSizeValue = entry.Data.ReadUInt16(ref offset);
// Read the font name as a string
dialogTemplate.Typeface = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogTemplate.Typeface = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
}
// Align to the DWORD boundary if we're not at the end
@@ -755,7 +739,7 @@ namespace SabreTools.Serialization
offset += sizeof(ushort);
// Read the class resource as a string
dialogItemTemplate.ClassResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogItemTemplate.ClassResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -785,7 +769,7 @@ namespace SabreTools.Serialization
else
{
// Read the title resource as a string
dialogItemTemplate.TitleResource = entry.Data.ReadString(ref offset, Encoding.Unicode);
dialogItemTemplate.TitleResource = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the WORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -885,8 +869,8 @@ namespace SabreTools.Serialization
dirEntry.Entry.Reserved = entry.Data.ReadUInt32(ref offset);
// TODO: Determine how to read these two? Immediately after?
dirEntry.Entry.DeviceName = entry.Data.ReadString(ref offset);
dirEntry.Entry.FaceName = entry.Data.ReadString(ref offset);
dirEntry.Entry.DeviceName = entry.Data.ReadNullTerminatedAnsiString(ref offset);
dirEntry.Entry.FaceName = entry.Data.ReadNullTerminatedAnsiString(ref offset);
fontGroupHeader.DE[i] = dirEntry;
}
@@ -920,13 +904,11 @@ namespace SabreTools.Serialization
{
#region Extended menu header
var menuHeaderExtended = new MenuHeaderExtended();
var menuHeaderExtended = entry.Data.ReadType<MenuHeaderExtended>(ref offset);
if (menuHeaderExtended == null)
return null;
menuHeaderExtended.Version = entry.Data.ReadUInt16(ref offset);
menuHeaderExtended.Offset = entry.Data.ReadUInt16(ref offset);
menuHeaderExtended.HelpID = entry.Data.ReadUInt32(ref offset);
menuResource.ExtendedMenuHeader = menuHeaderExtended;
menuResource.MenuHeader = menuHeaderExtended;
#endregion
@@ -940,13 +922,9 @@ namespace SabreTools.Serialization
while (offset < entry.Data.Length)
{
var extendedMenuItem = new MenuItemExtended();
extendedMenuItem.ItemType = (MenuFlags)entry.Data.ReadUInt32(ref offset);
extendedMenuItem.State = (MenuFlags)entry.Data.ReadUInt32(ref offset);
extendedMenuItem.ID = entry.Data.ReadUInt32(ref offset);
extendedMenuItem.Flags = (MenuFlags)entry.Data.ReadUInt32(ref offset);
extendedMenuItem.MenuText = entry.Data.ReadString(ref offset, Encoding.Unicode);
var extendedMenuItem = entry.Data.ReadType<MenuItemExtended>(ref offset);
if (extendedMenuItem == null)
return null;
// Align to the DWORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -959,7 +937,7 @@ namespace SabreTools.Serialization
}
}
menuResource.ExtendedMenuItems = [.. extendedMenuItems];
menuResource.MenuItems = [.. extendedMenuItems];
#endregion
}
@@ -967,10 +945,9 @@ namespace SabreTools.Serialization
{
#region Menu header
var menuHeader = new MenuHeader();
menuHeader.Version = entry.Data.ReadUInt16(ref offset);
menuHeader.HeaderSize = entry.Data.ReadUInt16(ref offset);
var menuHeader = entry.Data.ReadType<NormalMenuHeader>(ref offset);
if (menuHeader == null)
return null;
menuResource.MenuHeader = menuHeader;
@@ -982,28 +959,19 @@ namespace SabreTools.Serialization
while (offset < entry.Data.Length)
{
var menuItem = new MenuItem();
// Determine if this is a popup
int flagsOffset = offset;
var initialFlags = (MenuFlags)entry.Data.ReadUInt16(ref flagsOffset);
MenuItem? menuItem;
#if NET20 || NET35
if ((initialFlags & MenuFlags.MF_POPUP) != 0)
#else
if (initialFlags.HasFlag(MenuFlags.MF_POPUP))
#endif
{
menuItem.PopupItemType = (MenuFlags)entry.Data.ReadUInt32(ref offset);
menuItem.PopupState = (MenuFlags)entry.Data.ReadUInt32(ref offset);
menuItem.PopupID = entry.Data.ReadUInt32(ref offset);
menuItem.PopupResInfo = (MenuFlags)entry.Data.ReadUInt32(ref offset);
menuItem.PopupMenuText = entry.Data.ReadString(ref offset, Encoding.Unicode);
}
menuItem = entry.Data.ReadType<PopupMenuItem>(ref offset);
else
{
menuItem.NormalResInfo = (MenuFlags)entry.Data.ReadUInt16(ref offset);
menuItem.NormalMenuText = entry.Data.ReadString(ref offset, Encoding.Unicode);
}
menuItem = entry.Data.ReadType<NormalMenuItem>(ref offset);
// Align to the DWORD boundary if we're not at the end
if (offset < entry.Data.Length)
@@ -1012,6 +980,9 @@ namespace SabreTools.Serialization
_ = entry.Data.ReadByte(ref offset);
}
if (menuItem == null)
return null;
menuItems.Add(menuItem);
}
@@ -1048,11 +1019,9 @@ namespace SabreTools.Serialization
for (int i = 0; i < messageResourceData.NumberOfBlocks; i++)
{
var messageResourceBlock = new MessageResourceBlock();
messageResourceBlock.LowId = entry.Data.ReadUInt32(ref offset);
messageResourceBlock.HighId = entry.Data.ReadUInt32(ref offset);
messageResourceBlock.OffsetToEntries = entry.Data.ReadUInt32(ref offset);
var messageResourceBlock = entry.Data.ReadType<MessageResourceBlock>(ref offset);
if (messageResourceBlock == null)
return null;
messageResourceBlocks.Add(messageResourceBlock);
}
@@ -1115,21 +1084,9 @@ namespace SabreTools.Serialization
// Loop through and add
while (offset < entry.Data.Length)
{
ushort stringLength = entry.Data.ReadUInt16(ref offset);
if (stringLength == 0)
string? stringValue = entry.Data.ReadPrefixedUnicodeString(ref offset);
if (stringValue != null)
{
stringTable[stringIndex++] = "[EMPTY]";
}
else
{
if (stringLength * 2 > entry.Data.Length - offset)
{
Console.WriteLine($"{stringLength * 2} requested but {entry.Data.Length - offset} remains");
stringLength = (ushort)((entry.Data.Length - offset) / 2);
}
string stringValue = Encoding.Unicode.GetString(entry.Data, offset, stringLength * 2);
offset += stringLength * 2;
stringValue = stringValue.Replace("\n", "\\n").Replace("\r", newValue: "\\r");
stringTable[stringIndex++] = stringValue;
}
@@ -1158,7 +1115,7 @@ namespace SabreTools.Serialization
versionInfo.Length = entry.Data.ReadUInt16(ref offset);
versionInfo.ValueLength = entry.Data.ReadUInt16(ref offset);
versionInfo.ResourceType = (VersionResourceType)entry.Data.ReadUInt16(ref offset);
versionInfo.Key = entry.Data.ReadString(ref offset, Encoding.Unicode);
versionInfo.Key = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
if (versionInfo.Key != "VS_VERSION_INFO")
return null;
@@ -1166,25 +1123,15 @@ namespace SabreTools.Serialization
versionInfo.Padding1 = entry.Data.ReadUInt16(ref offset);
// Read fixed file info
if (versionInfo.ValueLength > 0)
if (versionInfo.ValueLength > 0 && offset + versionInfo.ValueLength <= entry.Data.Length)
{
var fixedFileInfo = new FixedFileInfo();
fixedFileInfo.Signature = entry.Data.ReadUInt32(ref offset);
var fixedFileInfo = entry.Data.ReadType<FixedFileInfo>(ref offset);
if (fixedFileInfo == null)
return null;
if (fixedFileInfo.Signature != 0xFEEF04BD)
return null;
fixedFileInfo.StrucVersion = entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileVersionMS = entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileVersionLS = entry.Data.ReadUInt32(ref offset);
fixedFileInfo.ProductVersionMS = entry.Data.ReadUInt32(ref offset);
fixedFileInfo.ProductVersionLS = entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileFlagsMask = entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileFlags = (FixedFileInfoFlags)(entry.Data.ReadUInt32(ref offset) & fixedFileInfo.FileFlagsMask);
fixedFileInfo.FileOS = (FixedFileInfoOS)entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileType = (FixedFileInfoFileType)entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileSubtype = (FixedFileInfoFileSubtype)entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileDateMS = entry.Data.ReadUInt32(ref offset);
fixedFileInfo.FileDateLS = entry.Data.ReadUInt32(ref offset);
versionInfo.Value = fixedFileInfo;
}
@@ -1200,7 +1147,7 @@ namespace SabreTools.Serialization
int currentOffset = offset;
offset += 6;
string? nextKey = entry.Data.ReadString(ref offset, Encoding.Unicode);
string? nextKey = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
offset = currentOffset;
if (nextKey == "StringFileInfo")
@@ -1222,7 +1169,7 @@ namespace SabreTools.Serialization
int currentOffset = offset;
offset += 6;
string? nextKey = entry.Data.ReadString(ref offset, Encoding.Unicode);
string? nextKey = entry.Data.ReadNullTerminatedUnicodeString(ref offset);
offset = currentOffset;
if (nextKey == "StringFileInfo")
@@ -1246,7 +1193,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a string file info</param>
/// <param name="offset">Offset into the byte array</param>
/// <returns>A filled string file info resource on success, null on error</returns>
private static StringFileInfo? AsStringFileInfo(byte[] data, ref int offset)
public static StringFileInfo? AsStringFileInfo(byte[] data, ref int offset)
{
var stringFileInfo = new StringFileInfo();
@@ -1256,7 +1203,7 @@ namespace SabreTools.Serialization
stringFileInfo.Length = data.ReadUInt16(ref offset);
stringFileInfo.ValueLength = data.ReadUInt16(ref offset);
stringFileInfo.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
stringFileInfo.Key = data.ReadString(ref offset, Encoding.Unicode);
stringFileInfo.Key = data.ReadNullTerminatedUnicodeString(ref offset);
if (stringFileInfo.Key != "StringFileInfo")
{
offset -= 6 + ((stringFileInfo.Key?.Length ?? 0 + 1) * 2);
@@ -1278,7 +1225,7 @@ namespace SabreTools.Serialization
stringTable.Length = data.ReadUInt16(ref offset);
stringTable.ValueLength = data.ReadUInt16(ref offset);
stringTable.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
stringTable.Key = data.ReadString(ref offset, Encoding.Unicode);
stringTable.Key = data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the DWORD boundary if we're not at the end
if (offset < data.Length)
@@ -1296,7 +1243,7 @@ namespace SabreTools.Serialization
stringData.Length = data.ReadUInt16(ref offset);
stringData.ValueLength = data.ReadUInt16(ref offset);
stringData.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
stringData.Key = data.ReadString(ref offset, Encoding.Unicode);
stringData.Key = data.ReadNullTerminatedUnicodeString(ref offset);
// Align to the DWORD boundary if we're not at the end
if (offset < data.Length)
@@ -1341,7 +1288,7 @@ namespace SabreTools.Serialization
/// <param name="data">Data to parse into a var file info</param>
/// <param name="offset">Offset into the byte array</param>
/// <returns>A filled var file info resource on success, null on error</returns>
private static VarFileInfo? AsVarFileInfo(byte[] data, ref int offset)
public static VarFileInfo? AsVarFileInfo(byte[] data, ref int offset)
{
var varFileInfo = new VarFileInfo();
@@ -1351,7 +1298,7 @@ namespace SabreTools.Serialization
varFileInfo.Length = data.ReadUInt16(ref offset);
varFileInfo.ValueLength = data.ReadUInt16(ref offset);
varFileInfo.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
varFileInfo.Key = data.ReadString(ref offset, Encoding.Unicode);
varFileInfo.Key = data.ReadNullTerminatedUnicodeString(ref offset);
if (varFileInfo.Key != "VarFileInfo")
return null;
@@ -1370,7 +1317,7 @@ namespace SabreTools.Serialization
varData.Length = data.ReadUInt16(ref offset);
varData.ValueLength = data.ReadUInt16(ref offset);
varData.ResourceType = (VersionResourceType)data.ReadUInt16(ref offset);
varData.Key = data.ReadString(ref offset, Encoding.Unicode);
varData.Key = data.ReadNullTerminatedUnicodeString(ref offset);
if (varData.Key != "Translation")
{
offset -= 6 + ((varData.Key?.Length ?? 0 + 1) * 2);

View File

@@ -0,0 +1,18 @@
using System.Text;
namespace SabreTools.Serialization.Interfaces
{
/// <summary>
/// Marks a class as a printer associated with a model
/// </summary>
/// <typeparam name="TModel">Type of the top-level model</typeparam>
public interface IPrinter<TModel>
{
/// <summary>
/// Print information associated with a model
/// </summary>
/// <param name="builder">StringBuilder to append information to</param>
/// <param name="model">Model to print</param>
void PrintInformation(StringBuilder builder, TModel model);
}
}

View File

@@ -11,7 +11,7 @@ namespace SabreTools.Serialization
/// </summary>
/// <param name="path">Path to open as a stream</param>
/// <returns>Stream representing the file, null on error</returns>
public static Stream? OpenStream(string? path)
public static Stream? OpenStream(string? path, bool skipCompression = false)
{
try
{
@@ -26,11 +26,11 @@ namespace SabreTools.Serialization
string ext = Path.GetExtension(path).TrimStart('.');
// Determine what we do based on the extension
if (string.Equals(ext, "gz", StringComparison.OrdinalIgnoreCase))
if (!skipCompression && string.Equals(ext, "gz", StringComparison.OrdinalIgnoreCase))
{
return new GZipStream(stream, CompressionMode.Decompress);
}
else if (string.Equals(ext, "zip", StringComparison.OrdinalIgnoreCase))
else if (!skipCompression && string.Equals(ext, "zip", StringComparison.OrdinalIgnoreCase))
{
// TODO: Support zip-compressed files
return null;

View File

@@ -0,0 +1,442 @@
using System;
using System.Text;
using SabreTools.Serialization.Interfaces;
using SabreTools.Serialization.Printers;
using Wrapper = SabreTools.Serialization.Wrappers;
namespace SabreTools.Serialization
{
/// <summary>
/// Generic wrapper around printing methods
/// </summary>
public static class Printer
{
/// <summary>
/// Print the item information from a wrapper to console as
/// pretty-printed text
/// </summary>
public static void PrintToConsole(this IWrapper wrapper)
{
var sb = wrapper.ExportStringBuilder();
if (sb == null)
{
Console.WriteLine("No item information could be generated");
return;
}
Console.WriteLine(sb.ToString());
}
/// <summary>
/// Export the item information as a StringBuilder
/// </summary>
public static StringBuilder? ExportStringBuilder(this IWrapper wrapper)
{
return wrapper switch
{
Wrapper.AACSMediaKeyBlock item => item.PrettyPrint(),
Wrapper.BDPlusSVM item => item.PrettyPrint(),
Wrapper.BFPK item => item.PrettyPrint(),
Wrapper.BSP item => item.PrettyPrint(),
Wrapper.CFB item => item.PrettyPrint(),
Wrapper.CIA item => item.PrettyPrint(),
Wrapper.GCF item => item.PrettyPrint(),
Wrapper.InstallShieldCabinet item => item.PrettyPrint(),
Wrapper.IRD item => item.PrettyPrint(),
Wrapper.LinearExecutable item => item.PrettyPrint(),
Wrapper.MicrosoftCabinet item => item.PrettyPrint(),
Wrapper.MoPaQ item => item.PrettyPrint(),
Wrapper.MSDOS item => item.PrettyPrint(),
Wrapper.N3DS item => item.PrettyPrint(),
Wrapper.NCF item => item.PrettyPrint(),
Wrapper.NewExecutable item => item.PrettyPrint(),
Wrapper.Nitro item => item.PrettyPrint(),
Wrapper.PAK item => item.PrettyPrint(),
Wrapper.PFF item => item.PrettyPrint(),
Wrapper.PIC item => item.PrettyPrint(),
Wrapper.PKZIP item => item.PrettyPrint(),
Wrapper.PlayJAudioFile item => item.PrettyPrint(),
Wrapper.PlayJPlaylist item => item.PrettyPrint(),
Wrapper.PortableExecutable item => item.PrettyPrint(),
Wrapper.Quantum item => item.PrettyPrint(),
Wrapper.SGA item => item.PrettyPrint(),
Wrapper.VBSP item => item.PrettyPrint(),
Wrapper.VPK item => item.PrettyPrint(),
Wrapper.WAD item => item.PrettyPrint(),
Wrapper.XeMID item => item.PrettyPrint(),
Wrapper.XMID item => item.PrettyPrint(),
Wrapper.XZP item => item.PrettyPrint(),
_ => null,
};
}
#if NET6_0_OR_GREATER
/// <summary>
/// Export the item information as JSON
/// </summary>
public static string ExportJSON(this IWrapper wrapper)
{
return wrapper switch
{
Wrapper.AACSMediaKeyBlock item => item.ExportJSON(),
Wrapper.BDPlusSVM item => item.ExportJSON(),
Wrapper.BFPK item => item.ExportJSON(),
Wrapper.BSP item => item.ExportJSON(),
Wrapper.CFB item => item.ExportJSON(),
Wrapper.CIA item => item.ExportJSON(),
Wrapper.GCF item => item.ExportJSON(),
Wrapper.InstallShieldCabinet item => item.ExportJSON(),
Wrapper.IRD item => item.ExportJSON(),
Wrapper.LinearExecutable item => item.ExportJSON(),
Wrapper.MicrosoftCabinet item => item.ExportJSON(),
Wrapper.MoPaQ item => item.ExportJSON(),
Wrapper.MSDOS item => item.ExportJSON(),
Wrapper.N3DS item => item.ExportJSON(),
Wrapper.NCF item => item.ExportJSON(),
Wrapper.NewExecutable item => item.ExportJSON(),
Wrapper.Nitro item => item.ExportJSON(),
Wrapper.PAK item => item.ExportJSON(),
Wrapper.PFF item => item.ExportJSON(),
Wrapper.PIC item => item.ExportJSON(),
Wrapper.PKZIP item => item.ExportJSON(),
Wrapper.PlayJAudioFile item => item.ExportJSON(),
Wrapper.PlayJPlaylist item => item.ExportJSON(),
Wrapper.PortableExecutable item => item.ExportJSON(),
Wrapper.Quantum item => item.ExportJSON(),
Wrapper.SGA item => item.ExportJSON(),
Wrapper.VBSP item => item.ExportJSON(),
Wrapper.VPK item => item.ExportJSON(),
Wrapper.WAD item => item.ExportJSON(),
Wrapper.XeMID item => item.ExportJSON(),
Wrapper.XMID item => item.ExportJSON(),
Wrapper.XZP item => item.ExportJSON(),
_ => string.Empty,
};
}
#endif
#region Static Printing Implementations
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.AACSMediaKeyBlock item)
{
var builder = new StringBuilder();
AACSMediaKeyBlock.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.BDPlusSVM item)
{
var builder = new StringBuilder();
BDPlusSVM.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.BFPK item)
{
var builder = new StringBuilder();
BFPK.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.BSP item)
{
var builder = new StringBuilder();
BSP.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.CFB item)
{
var builder = new StringBuilder();
CFB.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.CIA item)
{
var builder = new StringBuilder();
CIA.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.GCF item)
{
var builder = new StringBuilder();
GCF.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.InstallShieldCabinet item)
{
var builder = new StringBuilder();
InstallShieldCabinet.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.IRD item)
{
var builder = new StringBuilder();
IRD.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.LinearExecutable item)
{
var builder = new StringBuilder();
LinearExecutable.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.MicrosoftCabinet item)
{
var builder = new StringBuilder();
MicrosoftCabinet.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.MoPaQ item)
{
var builder = new StringBuilder();
MoPaQ.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.MSDOS item)
{
var builder = new StringBuilder();
MSDOS.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.N3DS item)
{
var builder = new StringBuilder();
N3DS.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.NCF item)
{
var builder = new StringBuilder();
NCF.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.NewExecutable item)
{
var builder = new StringBuilder();
NewExecutable.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.Nitro item)
{
var builder = new StringBuilder();
Nitro.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.PAK item)
{
var builder = new StringBuilder();
PAK.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.PFF item)
{
var builder = new StringBuilder();
PFF.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.PIC item)
{
var builder = new StringBuilder();
PIC.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.PKZIP item)
{
var builder = new StringBuilder();
PKZIP.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.PlayJAudioFile item)
{
var builder = new StringBuilder();
PlayJAudioFile.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.PlayJPlaylist item)
{
var builder = new StringBuilder();
PlayJPlaylist.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.PortableExecutable item)
{
var builder = new StringBuilder();
PortableExecutable.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.Quantum item)
{
var builder = new StringBuilder();
Quantum.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.SGA item)
{
var builder = new StringBuilder();
SGA.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.VBSP item)
{
var builder = new StringBuilder();
VBSP.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.VPK item)
{
var builder = new StringBuilder();
VPK.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.WAD item)
{
var builder = new StringBuilder();
WAD.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.XeMID item)
{
var builder = new StringBuilder();
XeMID.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.XMID item)
{
var builder = new StringBuilder();
XMID.Print(builder, item.Model);
return builder;
}
/// <summary>
/// Export the item information as pretty-printed text
/// </summary>
private static StringBuilder PrettyPrint(this Wrapper.XZP item)
{
var builder = new StringBuilder();
XZP.Print(builder, item.Model);
return builder;
}
#endregion
}
}

View File

@@ -0,0 +1,290 @@
using System.Text;
using SabreTools.Models.AACS;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class AACSMediaKeyBlock : IPrinter<MediaKeyBlock>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, MediaKeyBlock model)
=> Print(builder, model);
public static void Print(StringBuilder builder, MediaKeyBlock mediaKeyBlock)
{
builder.AppendLine("AACS Media Key Block Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, mediaKeyBlock.Records);
}
private static void Print(StringBuilder builder, Record?[]? records)
{
builder.AppendLine(" Records Information:");
builder.AppendLine(" -------------------------");
if (records == null || records.Length == 0)
{
builder.AppendLine(" No records");
builder.AppendLine();
return;
}
for (int i = 0; i < records.Length; i++)
{
var record = records[i];
Print(builder, record, i);
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Record? record, int index)
{
builder.AppendLine($" Record Entry {index}");
if (record == null)
{
builder.AppendLine(" [NULL]");
return;
}
builder.AppendLine($" Record type: {record.RecordType} (0x{record.RecordType:X})");
builder.AppendLine(record.RecordLength, " Record length");
switch (record)
{
case EndOfMediaKeyBlockRecord eomkb:
Print(builder, eomkb);
break;
case ExplicitSubsetDifferenceRecord esd:
Print(builder, esd);
break;
case MediaKeyDataRecord mkd:
Print(builder, mkd);
break;
case SubsetDifferenceIndexRecord sdi:
Print(builder, sdi);
break;
case TypeAndVersionRecord tav:
Print(builder, tav);
break;
case DriveRevocationListRecord drl:
Print(builder, drl);
break;
case HostRevocationListRecord hrl:
Print(builder, hrl);
break;
case VerifyMediaKeyRecord vmk:
Print(builder, vmk);
break;
case CopyrightRecord c:
Print(builder, c);
break;
}
}
private static void Print(StringBuilder builder, EndOfMediaKeyBlockRecord record)
{
if (record == null)
return;
builder.AppendLine(record.SignatureData, " Signature data");
}
private static void Print(StringBuilder builder, ExplicitSubsetDifferenceRecord? record)
{
if (record == null)
return;
builder.AppendLine(" Subset Differences:");
builder.AppendLine(" -------------------------");
if (record?.SubsetDifferences == null || record.SubsetDifferences.Length == 0)
{
builder.AppendLine(" No subset differences");
return;
}
for (int j = 0; j < record.SubsetDifferences.Length; j++)
{
var sd = record.SubsetDifferences[j];
builder.AppendLine($" Subset Difference {j}");
if (sd == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(sd.Mask, " Mask");
builder.AppendLine(sd.Number, " Number");
}
}
}
private static void Print(StringBuilder builder, MediaKeyDataRecord? record)
{
if (record == null)
return;
builder.AppendLine(" Media Keys:");
builder.AppendLine(" -------------------------");
if (record?.MediaKeyData == null || record.MediaKeyData.Length == 0)
{
builder.AppendLine(" No media keys");
return;
}
for (int j = 0; j < record.MediaKeyData.Length; j++)
{
var mk = record.MediaKeyData[j];
builder.AppendLine(mk, $" Media key {j}");
}
}
private static void Print(StringBuilder builder, SubsetDifferenceIndexRecord? record)
{
if (record == null)
return;
builder.AppendLine($" Span: {record.Span} (0x{record.Span:X})");
builder.AppendLine(" Offsets:");
builder.AppendLine(" -------------------------");
if (record.Offsets == null || record.Offsets.Length == 0)
{
builder.AppendLine(" No offsets");
return;
}
for (int j = 0; j < record.Offsets.Length; j++)
{
var offset = record.Offsets[j];
builder.AppendLine(offset, $" Offset {j}");
}
}
private static void Print(StringBuilder builder, TypeAndVersionRecord? record)
{
if (record == null)
return;
builder.AppendLine($" Media key block type: {record.MediaKeyBlockType} (0x{record.MediaKeyBlockType:X})");
builder.AppendLine(record.VersionNumber, " Version number");
}
private static void Print(StringBuilder builder, DriveRevocationListRecord? record)
{
if (record == null)
return;
builder.AppendLine(record.TotalNumberOfEntries, " Total number of entries");
builder.AppendLine(" Signature Blocks:");
builder.AppendLine(" -------------------------");
if (record.SignatureBlocks == null || record.SignatureBlocks.Length == 0)
{
builder.AppendLine(" No signature blocks");
return;
}
for (int j = 0; j < record.SignatureBlocks.Length; j++)
{
var block = record.SignatureBlocks[j];
builder.AppendLine($" Signature Block {j}");
if (block == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(block.NumberOfEntries, " Number of entries");
builder.AppendLine(" Entry Fields:");
builder.AppendLine(" -------------------------");
if (block.EntryFields == null || block.EntryFields.Length == 0)
{
builder.AppendLine(" No entry fields");
}
else
{
for (int k = 0; k < block.EntryFields.Length; k++)
{
var ef = block.EntryFields[k];
builder.AppendLine($" Entry {k}");
if (ef == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(ef.Range, " Range");
builder.AppendLine(ef.DriveID, " Drive ID");
}
}
}
}
}
private static void Print(StringBuilder builder, HostRevocationListRecord? record)
{
if (record == null)
return;
builder.AppendLine($" Total number of entries: {record.TotalNumberOfEntries} (0x{record.TotalNumberOfEntries:X})");
builder.AppendLine(" Signature Blocks:");
builder.AppendLine(" -------------------------");
if (record.SignatureBlocks == null || record.SignatureBlocks.Length == 0)
{
builder.AppendLine(" No signature blocks");
return;
}
for (int j = 0; j < record.SignatureBlocks.Length; j++)
{
builder.AppendLine($" Signature Block {j}");
var block = record.SignatureBlocks[j];
if (block == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(block.NumberOfEntries, " Number of entries");
builder.AppendLine(" Entry Fields:");
builder.AppendLine(" -------------------------");
if (block.EntryFields == null || block.EntryFields.Length == 0)
{
builder.AppendLine(" No entry fields");
continue;
}
for (int k = 0; k < block.EntryFields.Length; k++)
{
var ef = block.EntryFields[k];
builder.AppendLine($" Entry {k}");
if (ef == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(ef.Range, " Range");
builder.AppendLine(ef.HostID, " Host ID");
}
}
}
}
private static void Print(StringBuilder builder, VerifyMediaKeyRecord? record)
{
if (record == null)
return;
builder.AppendLine(record.CiphertextValue, " Ciphertext value");
}
private static void Print(StringBuilder builder, CopyrightRecord? record)
{
if (record == null)
return;
builder.AppendLine(record.Copyright, " Copyright");
}
}
}

View File

@@ -0,0 +1,28 @@
using System.Text;
using SabreTools.Models.BDPlus;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class BDPlusSVM : IPrinter<SVM>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, SVM model)
=> Print(builder, model);
public static void Print(StringBuilder builder, SVM svm)
{
builder.AppendLine("BD+ SVM Information:");
builder.AppendLine("-------------------------");
builder.AppendLine(svm.Signature, "Signature");
builder.AppendLine(svm.Unknown1, "Unknown 1");
builder.AppendLine(svm.Year, "Year");
builder.AppendLine(svm.Month, "Month");
builder.AppendLine(svm.Day, "Day");
builder.AppendLine(svm.Unknown2, "Unknown 2");
builder.AppendLine(svm.Length, "Length");
//builder.AppendLine(svm.Data, "Data");
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,68 @@
using System.Text;
using SabreTools.Models.BFPK;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class BFPK : IPrinter<Archive>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Archive model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Archive archive)
{
builder.AppendLine("BFPK Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, archive.Header);
Print(builder, archive.Files);
}
private static void Print(StringBuilder builder, Header? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Magic, " Magic");
builder.AppendLine(header.Version, " Version");
builder.AppendLine(header.Files, " Files");
builder.AppendLine();
}
private static void Print(StringBuilder builder, FileEntry?[]? files)
{
builder.AppendLine(" File Table Information:");
builder.AppendLine(" -------------------------");
if (files == null || files.Length == 0)
{
builder.AppendLine(" No file table items");
return;
}
for (int i = 0; i < files.Length; i++)
{
var entry = files[i];
builder.AppendLine($" File Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.NameSize, " Name size");
builder.AppendLine(entry.Name, " Name");
builder.AppendLine(entry.UncompressedSize, " Uncompressed size");
builder.AppendLine(entry.Offset, " Offset");
builder.AppendLine(entry.CompressedSize, " Compressed size");
}
}
}
}

View File

@@ -0,0 +1,150 @@
using System.Text;
using SabreTools.Models.BSP;
using SabreTools.Serialization.Interfaces;
using static SabreTools.Models.BSP.Constants;
namespace SabreTools.Serialization.Printers
{
public class BSP : IPrinter<File>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, File model)
=> Print(builder, model);
public static void Print(StringBuilder builder, File file)
{
builder.AppendLine("BSP Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, file.Header);
Print(builder, file.Lumps);
Print(builder, file.TextureHeader);
Print(builder, file.Textures);
}
private static void Print(StringBuilder builder, Header? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Version, " Version");
builder.AppendLine();
}
private static void Print(StringBuilder builder, Lump?[]? lumps)
{
builder.AppendLine(" Lumps Information:");
builder.AppendLine(" -------------------------");
if (lumps == null || lumps.Length == 0)
{
builder.AppendLine(" No lumps");
builder.AppendLine();
return;
}
for (int i = 0; i < lumps.Length; i++)
{
var lump = lumps[i];
string specialLumpName = string.Empty;
switch (i)
{
case HL_BSP_LUMP_ENTITIES:
specialLumpName = " (entities)";
break;
case HL_BSP_LUMP_TEXTUREDATA:
specialLumpName = " (texture data)";
break;
}
builder.AppendLine($" Lump {i}{specialLumpName}");
if (lump == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(lump.Offset, " Offset");
builder.AppendLine(lump.Length, " Length");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, TextureHeader? header)
{
builder.AppendLine(" Texture Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No texture header");
builder.AppendLine();
return;
}
builder.AppendLine(header.TextureCount, " Texture count");
builder.AppendLine(" Offsets:");
if (header.Offsets == null || header.Offsets.Length == 0)
{
builder.AppendLine(" No offsets");
builder.AppendLine();
return;
}
for (int i = 0; i < header.Offsets.Length; i++)
{
builder.AppendLine(header.Offsets[i], $" Offset {i}");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Texture?[]? textures)
{
builder.AppendLine(" Textures Information:");
builder.AppendLine(" -------------------------");
if (textures == null || textures.Length == 0)
{
builder.AppendLine(" No textures");
builder.AppendLine();
return;
}
for (int i = 0; i < textures.Length; i++)
{
var texture = textures[i];
builder.AppendLine($" Texture {i}");
if (texture == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(texture.Name, " Name");
builder.AppendLine(texture.Width, " Width");
builder.AppendLine(texture.Height, " Height");
builder.AppendLine(" Offsets:");
if (texture.Offsets == null || texture.Offsets.Length == 0)
{
builder.AppendLine(" No offsets");
continue;
}
else
{
for (int j = 0; j < texture.Offsets.Length; j++)
{
builder.AppendLine(texture.Offsets[i], $" Offset {j}");
}
}
// Skip texture data
builder.AppendLine(texture.PaletteSize, " Palette size");
// Skip palette data
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,125 @@
using System;
using System.Text;
using SabreTools.Models.CFB;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class CFB : IPrinter<Binary>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Binary model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Binary binary)
{
builder.AppendLine("Compound File Binary Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, binary.Header);
Print(builder, binary.FATSectorNumbers, "FAT");
Print(builder, binary.MiniFATSectorNumbers, "Mini FAT");
Print(builder, binary.DIFATSectorNumbers, "DIFAT");
Print(builder, binary.DirectoryEntries);
}
private static void Print(StringBuilder builder, FileHeader? header)
{
builder.AppendLine(" File Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No file header");
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.CLSID, " CLSID");
builder.AppendLine(header.MinorVersion, " Minor version");
builder.AppendLine(header.MajorVersion, " Major version");
builder.AppendLine(header.ByteOrder, " Byte order");
builder.AppendLine($" Sector shift: {header.SectorShift} (0x{header.SectorShift:X}) => {Math.Pow(2, header.SectorShift)}");
builder.AppendLine($" Mini sector shift: {header.MiniSectorShift} (0x{header.MiniSectorShift:X}) => {Math.Pow(2, header.MiniSectorShift)}");
builder.AppendLine(header.Reserved, " Reserved");
builder.AppendLine(header.NumberOfDirectorySectors, " Number of directory sectors");
builder.AppendLine(header.NumberOfFATSectors, " Number of FAT sectors");
builder.AppendLine(header.FirstDirectorySectorLocation, " First directory sector location");
builder.AppendLine(header.TransactionSignatureNumber, " Transaction signature number");
builder.AppendLine(header.MiniStreamCutoffSize, " Mini stream cutoff size");
builder.AppendLine(header.FirstMiniFATSectorLocation, " First mini FAT sector location");
builder.AppendLine(header.NumberOfMiniFATSectors, " Number of mini FAT sectors");
builder.AppendLine(header.FirstDIFATSectorLocation, " First DIFAT sector location");
builder.AppendLine(header.NumberOfDIFATSectors, " Number of DIFAT sectors");
builder.AppendLine(" DIFAT:");
if (header.DIFAT == null || header.DIFAT.Length == 0)
{
builder.AppendLine(" No DIFAT entries");
builder.AppendLine();
return;
}
for (int i = 0; i < header.DIFAT.Length; i++)
{
builder.AppendLine($" DIFAT Entry {i}: {header.DIFAT[i]} (0x{header.DIFAT[i]:X})");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, SectorNumber[]? sectorNumbers, string name)
{
builder.AppendLine($" {name} Sectors Information:");
builder.AppendLine(" -------------------------");
if (sectorNumbers == null || sectorNumbers.Length == 0)
{
builder.AppendLine($" No {name} sectors");
builder.AppendLine();
return;
}
for (int i = 0; i < sectorNumbers.Length; i++)
{
builder.AppendLine($" {name} Sector Entry {i}: {sectorNumbers[i]} (0x{sectorNumbers[i]:X})");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryEntry?[]? directoryEntries)
{
builder.AppendLine(" Directory Entries Information:");
builder.AppendLine(" -------------------------");
if (directoryEntries == null || directoryEntries.Length == 0)
{
builder.AppendLine(" No directory entries");
builder.AppendLine();
return;
}
for (int i = 0; i < directoryEntries.Length; i++)
{
var directoryEntry = directoryEntries[i];
builder.AppendLine($" Directory Entry {i}");
if (directoryEntry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(directoryEntry.Name, " Name");
builder.AppendLine(directoryEntry.NameLength, " Name length");
builder.AppendLine($" Object type: {directoryEntry.ObjectType} (0x{directoryEntry.ObjectType:X})");
builder.AppendLine($" Color flag: {directoryEntry.ColorFlag} (0x{directoryEntry.ColorFlag:X})");
builder.AppendLine($" Left sibling ID: {directoryEntry.LeftSiblingID} (0x{directoryEntry.LeftSiblingID:X})");
builder.AppendLine($" Right sibling ID: {directoryEntry.RightSiblingID} (0x{directoryEntry.RightSiblingID:X})");
builder.AppendLine($" Child ID: {directoryEntry.ChildID} (0x{directoryEntry.ChildID:X})");
builder.AppendLine(directoryEntry.CLSID, " CLSID");
builder.AppendLine(directoryEntry.StateBits, " State bits");
builder.AppendLine(directoryEntry.CreationTime, " Creation time");
builder.AppendLine(directoryEntry.ModifiedTime, " Modification time");
builder.AppendLine(directoryEntry.StartingSectorLocation, " Staring sector location");
builder.AppendLine(directoryEntry.StreamSize, " Stream size");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,454 @@
using System.Text;
using SabreTools.Models.N3DS;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class CIA : IPrinter<Models.N3DS.CIA>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Models.N3DS.CIA model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Models.N3DS.CIA cia)
{
builder.AppendLine("CIA Archive Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, cia.Header);
Print(builder, cia.CertificateChain);
Print(builder, cia.Ticket);
Print(builder, cia.TMDFileData);
Print(builder, cia.Partitions);
Print(builder, cia.MetaData);
}
private static void Print(StringBuilder builder, CIAHeader? header)
{
builder.AppendLine(" CIA Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No CIA header");
builder.AppendLine();
return;
}
builder.AppendLine(header.HeaderSize, " Header size");
builder.AppendLine(header.Type, " Type");
builder.AppendLine(header.Version, " Version");
builder.AppendLine(header.CertificateChainSize, " Certificate chain size");
builder.AppendLine(header.TicketSize, " Ticket size");
builder.AppendLine(header.TMDFileSize, " TMD file size");
builder.AppendLine(header.MetaSize, " Meta size");
builder.AppendLine(header.ContentSize, " Content size");
builder.AppendLine(header.ContentIndex, " Content index");
builder.AppendLine();
}
private static void Print(StringBuilder builder, Certificate?[]? certificateChain)
{
builder.AppendLine(" Certificate Chain Information:");
builder.AppendLine(" -------------------------");
if (certificateChain == null || certificateChain.Length == 0)
{
builder.AppendLine(" No certificates, expected 3");
builder.AppendLine();
return;
}
for (int i = 0; i < certificateChain.Length; i++)
{
var certificate = certificateChain[i];
string certificateName = string.Empty;
switch (i)
{
case 0: certificateName = " (CA)"; break;
case 1: certificateName = " (Ticket)"; break;
case 2: certificateName = " (TMD)"; break;
}
builder.AppendLine($" Certificate {i}{certificateName}");
if (certificate == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})");
builder.AppendLine(certificate.SignatureSize, " Signature size");
builder.AppendLine(certificate.PaddingSize, " Padding size");
builder.AppendLine(certificate.Signature, " Signature");
builder.AppendLine(certificate.Padding, " Padding");
builder.AppendLine(certificate.Issuer, " Issuer");
builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})");
builder.AppendLine(certificate.Name, " Name");
builder.AppendLine(certificate.ExpirationTime, " Expiration time");
switch (certificate.KeyType)
{
case PublicKeyType.RSA_4096:
case PublicKeyType.RSA_2048:
builder.AppendLine(certificate.RSAModulus, " Modulus");
builder.AppendLine(certificate.RSAPublicExponent, " Public exponent");
builder.AppendLine(certificate.RSAPadding, " Padding");
break;
case PublicKeyType.EllipticCurve:
builder.AppendLine(certificate.ECCPublicKey, " Public key");
builder.AppendLine(certificate.ECCPadding, " Padding");
break;
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Ticket? ticket)
{
builder.AppendLine(" Ticket Information:");
builder.AppendLine(" -------------------------");
if (ticket == null)
{
builder.AppendLine(" No ticket");
builder.AppendLine();
return;
}
builder.AppendLine($" Signature type: {ticket.SignatureType} (0x{ticket.SignatureType:X})");
builder.AppendLine(ticket.SignatureSize, " Signature size");
builder.AppendLine(ticket.PaddingSize, " Padding size");
builder.AppendLine(ticket.Signature, " Signature");
builder.AppendLine(ticket.Padding, " Padding");
builder.AppendLine(ticket.Issuer, " Issuer");
builder.AppendLine(ticket.ECCPublicKey, " ECC public key");
builder.AppendLine(ticket.Version, " Version");
builder.AppendLine(ticket.CaCrlVersion, " CaCrlVersion");
builder.AppendLine(ticket.SignerCrlVersion, " SignerCrlVersion");
builder.AppendLine(ticket.TitleKey, " Title key");
builder.AppendLine(ticket.Reserved1, " Reserved 1");
builder.AppendLine(ticket.TicketID, " Ticket ID");
builder.AppendLine(ticket.ConsoleID, " Console ID");
builder.AppendLine(ticket.TitleID, " Title ID");
builder.AppendLine(ticket.Reserved2, " Reserved 2");
builder.AppendLine(ticket.TicketTitleVersion, " Ticket title version");
builder.AppendLine(ticket.Reserved3, " Reserved 3");
builder.AppendLine(ticket.LicenseType, " License type");
builder.AppendLine(ticket.CommonKeyYIndex, " Common key Y index");
builder.AppendLine(ticket.Reserved4, " Reserved 4");
builder.AppendLine(ticket.eShopAccountID, " eShop Account ID");
builder.AppendLine(ticket.Reserved5, " Reserved 5");
builder.AppendLine(ticket.Audit, " Audit");
builder.AppendLine(ticket.Reserved6, " Reserved 6");
builder.AppendLine(" Limits:");
if (ticket.Limits == null || ticket.Limits.Length == 0)
{
builder.AppendLine(" No limits");
}
else
{
for (int i = 0; i < ticket.Limits.Length; i++)
{
builder.AppendLine(ticket.Limits[i], $" Limit {i}");
}
}
builder.AppendLine(ticket.ContentIndexSize, " Content index size");
builder.AppendLine(ticket.ContentIndex, " Content index");
builder.AppendLine();
builder.AppendLine(" Ticket Certificate Chain Information:");
builder.AppendLine(" -------------------------");
if (ticket.CertificateChain == null || ticket.CertificateChain.Length == 0)
{
builder.AppendLine(" No certificates, expected 2");
}
else
{
for (int i = 0; i < ticket.CertificateChain.Length; i++)
{
var certificate = ticket.CertificateChain[i];
string certificateName = string.Empty;
switch (i)
{
case 0: certificateName = " (Ticket)"; break;
case 1: certificateName = " (CA)"; break;
}
builder.AppendLine($" Certificate {i}{certificateName}");
if (certificate == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})");
builder.AppendLine(certificate.SignatureSize, " Signature size");
builder.AppendLine(certificate.PaddingSize, " Padding size");
builder.AppendLine(certificate.Signature, " Signature");
builder.AppendLine(certificate.Padding, " Padding");
builder.AppendLine(certificate.Issuer, " Issuer");
builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})");
builder.AppendLine(certificate.Name, " Name");
builder.AppendLine(certificate.ExpirationTime, " Expiration time");
switch (certificate.KeyType)
{
case PublicKeyType.RSA_4096:
case PublicKeyType.RSA_2048:
builder.AppendLine(certificate.RSAModulus, " Modulus");
builder.AppendLine(certificate.RSAPublicExponent, " Public exponent");
builder.AppendLine(certificate.RSAPadding, " Padding");
break;
case PublicKeyType.EllipticCurve:
builder.AppendLine(certificate.ECCPublicKey, " Public key");
builder.AppendLine(certificate.ECCPadding, " Padding");
break;
}
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, TitleMetadata? tmd)
{
builder.AppendLine(" Title Metadata Information:");
builder.AppendLine(" -------------------------");
if (tmd == null)
{
builder.AppendLine(" No title metadata");
builder.AppendLine();
return;
}
builder.AppendLine($" Signature type: {tmd.SignatureType} (0x{tmd.SignatureType:X})");
builder.AppendLine(tmd.SignatureSize, " Signature size");
builder.AppendLine(tmd.PaddingSize, " Padding size");
builder.AppendLine(tmd.Signature, " Signature");
builder.AppendLine(tmd.Padding1, " Padding 1");
builder.AppendLine(tmd.Issuer, " Issuer");
builder.AppendLine(tmd.Version, " Version");
builder.AppendLine(tmd.CaCrlVersion, " CaCrlVersion");
builder.AppendLine(tmd.SignerCrlVersion, " SignerCrlVersion");
builder.AppendLine(tmd.Reserved1, " Reserved 1");
builder.AppendLine(tmd.SystemVersion, " System version");
builder.AppendLine(tmd.TitleID, " Title ID");
builder.AppendLine(tmd.TitleType, " Title type");
builder.AppendLine(tmd.GroupID, " Group ID");
builder.AppendLine(tmd.SaveDataSize, " Save data size");
builder.AppendLine(tmd.SRLPrivateSaveDataSize, " SRL private save data size");
builder.AppendLine(tmd.Reserved2, " Reserved 2");
builder.AppendLine(tmd.SRLFlag, " SRL flag");
builder.AppendLine(tmd.Reserved3, " Reserved 3");
builder.AppendLine(tmd.AccessRights, " Access rights");
builder.AppendLine(tmd.TitleVersion, " Title version");
builder.AppendLine(tmd.ContentCount, " Content count");
builder.AppendLine(tmd.BootContent, " Boot content");
builder.AppendLine(tmd.Padding2, " Padding 2");
builder.AppendLine(tmd.SHA256HashContentInfoRecords, " SHA-256 hash of the content info records");
builder.AppendLine();
builder.AppendLine(" Ticket Content Info Records Information:");
builder.AppendLine(" -------------------------");
if (tmd.ContentInfoRecords == null || tmd.ContentInfoRecords.Length == 0)
{
builder.AppendLine(" No content info records, expected 64");
}
else
{
for (int i = 0; i < tmd.ContentInfoRecords.Length; i++)
{
var contentInfoRecord = tmd.ContentInfoRecords[i];
builder.AppendLine($" Content Info Record {i}");
if (contentInfoRecord == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(contentInfoRecord.ContentIndexOffset, " Content index offset");
builder.AppendLine(contentInfoRecord.ContentCommandCount, " Content command count");
builder.AppendLine(contentInfoRecord.UnhashedContentRecordsSHA256Hash, $" SHA-256 hash of the next {contentInfoRecord.ContentCommandCount} records not hashed");
}
}
builder.AppendLine();
builder.AppendLine(" Ticket Content Chunk Records Information:");
builder.AppendLine(" -------------------------");
if (tmd.ContentChunkRecords == null || tmd.ContentChunkRecords.Length == 0)
{
builder.AppendLine($" No content chunk records, expected {tmd.ContentCount}");
}
else
{
for (int i = 0; i < tmd.ContentChunkRecords.Length; i++)
{
var contentChunkRecord = tmd.ContentChunkRecords[i];
builder.AppendLine($" Content Chunk Record {i}");
if (contentChunkRecord == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(contentChunkRecord.ContentId, " Content ID");
builder.AppendLine($" Content index: {contentChunkRecord.ContentIndex} (0x{contentChunkRecord.ContentIndex:X})");
builder.AppendLine($" Content type: {contentChunkRecord.ContentType} (0x{contentChunkRecord.ContentType:X})");
builder.AppendLine(contentChunkRecord.ContentSize, " Content size");
builder.AppendLine(contentChunkRecord.SHA256Hash, " SHA-256 hash");
}
}
builder.AppendLine();
builder.AppendLine(" Ticket Certificate Chain Information:");
builder.AppendLine(" -------------------------");
if (tmd.CertificateChain == null || tmd.CertificateChain.Length == 0)
{
builder.AppendLine(" No certificates, expected 2");
}
else
{
for (int i = 0; i < tmd.CertificateChain.Length; i++)
{
var certificate = tmd.CertificateChain[i];
string certificateName = string.Empty;
switch (i)
{
case 0: certificateName = " (TMD)"; break;
case 1: certificateName = " (CA)"; break;
}
builder.AppendLine($" Certificate {i}{certificateName}");
if (certificate == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine($" Signature type: {certificate.SignatureType} (0x{certificate.SignatureType:X})");
builder.AppendLine(certificate.SignatureSize, " Signature size");
builder.AppendLine(certificate.PaddingSize, " Padding size");
builder.AppendLine(certificate.Signature, " Signature");
builder.AppendLine(certificate.Padding, " Padding");
builder.AppendLine(certificate.Issuer, " Issuer");
builder.AppendLine($" Key type: {certificate.KeyType} (0x{certificate.KeyType:X})");
builder.AppendLine(certificate.Name, " Name");
builder.AppendLine(certificate.ExpirationTime, " Expiration time");
switch (certificate.KeyType)
{
case PublicKeyType.RSA_4096:
case PublicKeyType.RSA_2048:
builder.AppendLine(certificate.RSAModulus, " Modulus");
builder.AppendLine(certificate.RSAPublicExponent, " Public exponent");
builder.AppendLine(certificate.RSAPadding, " Padding");
break;
case PublicKeyType.EllipticCurve:
builder.AppendLine(certificate.ECCPublicKey, " Public key");
builder.AppendLine(certificate.ECCPadding, " Padding");
break;
}
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, NCCHHeader?[]? partitions)
{
builder.AppendLine(" NCCH Partition Header Information:");
builder.AppendLine(" -------------------------");
if (partitions == null || partitions.Length == 0)
{
builder.AppendLine(" No NCCH partition headers");
builder.AppendLine();
return;
}
for (int i = 0; i < partitions.Length; i++)
{
var partitionHeader = partitions[i];
builder.AppendLine($" NCCH Partition Header {i}");
if (partitionHeader == null)
{
builder.AppendLine(" [NULL]");
continue;
}
if (partitionHeader.MagicID == string.Empty)
{
builder.AppendLine(" Empty partition, no data can be parsed");
continue;
}
else if (partitionHeader.MagicID != Constants.NCCHMagicNumber)
{
builder.AppendLine(" Unrecognized partition data, no data can be parsed");
continue;
}
builder.AppendLine(partitionHeader.RSA2048Signature, " RSA-2048 SHA-256 signature");
builder.AppendLine(partitionHeader.MagicID, " Magic ID");
builder.AppendLine(partitionHeader.ContentSizeInMediaUnits, " Content size in media units");
builder.AppendLine(partitionHeader.PartitionId, " Partition ID");
builder.AppendLine(partitionHeader.MakerCode, " Maker code");
builder.AppendLine(partitionHeader.Version, " Version");
builder.AppendLine(partitionHeader.VerificationHash, " Verification hash");
builder.AppendLine(partitionHeader.ProgramId, " Program ID");
builder.AppendLine(partitionHeader.Reserved1, " Reserved 1");
builder.AppendLine(partitionHeader.LogoRegionHash, " Logo region SHA-256 hash");
builder.AppendLine(partitionHeader.ProductCode, " Product code");
builder.AppendLine(partitionHeader.ExtendedHeaderHash, " Extended header SHA-256 hash");
builder.AppendLine(partitionHeader.ExtendedHeaderSizeInBytes, " Extended header size in bytes");
builder.AppendLine(partitionHeader.Reserved2, " Reserved 2");
builder.AppendLine(" Flags:");
if (partitionHeader.Flags == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(partitionHeader.Flags.Reserved0, " Reserved 0");
builder.AppendLine(partitionHeader.Flags.Reserved1, " Reserved 1");
builder.AppendLine(partitionHeader.Flags.Reserved2, " Reserved 2");
builder.AppendLine($" Crypto method: {partitionHeader.Flags.CryptoMethod} (0x{partitionHeader.Flags.CryptoMethod:X})");
builder.AppendLine($" Content platform: {partitionHeader.Flags.ContentPlatform} (0x{partitionHeader.Flags.ContentPlatform:X})");
builder.AppendLine($" Content type: {partitionHeader.Flags.MediaPlatformIndex} (0x{partitionHeader.Flags.MediaPlatformIndex:X})");
builder.AppendLine(partitionHeader.Flags.ContentUnitSize, " Content unit size");
builder.AppendLine($" Bitmasks: {partitionHeader.Flags.BitMasks} (0x{partitionHeader.Flags.BitMasks:X})");
}
builder.AppendLine(partitionHeader.PlainRegionOffsetInMediaUnits, " Plain region offset, in media units");
builder.AppendLine(partitionHeader.PlainRegionSizeInMediaUnits, " Plain region size, in media units");
builder.AppendLine(partitionHeader.LogoRegionOffsetInMediaUnits, " Logo region offset, in media units");
builder.AppendLine(partitionHeader.LogoRegionSizeInMediaUnits, " Logo region size, in media units");
builder.AppendLine(partitionHeader.ExeFSOffsetInMediaUnits, " ExeFS offset, in media units");
builder.AppendLine(partitionHeader.ExeFSSizeInMediaUnits, " ExeFS size, in media units");
builder.AppendLine(partitionHeader.ExeFSHashRegionSizeInMediaUnits, " ExeFS hash region offset, in media units");
builder.AppendLine(partitionHeader.Reserved3, " Reserved 3");
builder.AppendLine(partitionHeader.RomFSOffsetInMediaUnits, " RomFS offset, in media units");
builder.AppendLine(partitionHeader.RomFSSizeInMediaUnits, " RomFS size, in media units");
builder.AppendLine(partitionHeader.RomFSHashRegionSizeInMediaUnits, " RomFS hash region offset, in media units");
builder.AppendLine(partitionHeader.Reserved4, " Reserved 4");
builder.AppendLine(partitionHeader.ExeFSSuperblockHash, " ExeFS superblock SHA-256 hash");
builder.AppendLine(partitionHeader.RomFSSuperblockHash, " RomFS superblock SHA-256 hash");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, MetaData? metaData)
{
builder.AppendLine(" Meta Data Information:");
builder.AppendLine(" -------------------------");
if (metaData == null)
{
builder.AppendLine(" No meta file data");
builder.AppendLine();
return;
}
builder.AppendLine(metaData.TitleIDDependencyList, " Title ID dependency list");
builder.AppendLine(metaData.Reserved1, " Reserved 1");
builder.AppendLine(metaData.CoreVersion, " Core version");
builder.AppendLine(metaData.Reserved2, " Reserved 2");
builder.AppendLine(metaData.IconData, " Icon data");
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,539 @@
using System.Collections.Generic;
using System.Text;
using SabreTools.Models.GCF;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class GCF : IPrinter<File>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, File model)
=> Print(builder, model);
public static void Print(StringBuilder builder, File file)
{
builder.AppendLine("GCF Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
// Header
Print(builder, file.Header);
// Block Entries
Print(builder, file.BlockEntryHeader);
Print(builder, file.BlockEntries);
// Fragmentation Maps
Print(builder, file.FragmentationMapHeader);
Print(builder, file.FragmentationMaps);
// Block Entry Maps
Print(builder, file.BlockEntryMapHeader);
Print(builder, file.BlockEntryMaps);
// Directory and Directory Maps
Print(builder, file.DirectoryHeader);
Print(builder, file.DirectoryEntries, file.DirectoryNames);
// TODO: Should we print out the entire string table?
Print(builder, file.DirectoryInfo1Entries);
Print(builder, file.DirectoryInfo2Entries);
Print(builder, file.DirectoryCopyEntries);
Print(builder, file.DirectoryLocalEntries);
Print(builder, file.DirectoryMapHeader);
Print(builder, file.DirectoryMapEntries);
// Checksums and Checksum Maps
Print(builder, file.ChecksumHeader);
Print(builder, file.ChecksumMapHeader);
Print(builder, file.ChecksumMapEntries);
Print(builder, file.ChecksumEntries);
// Data Blocks
Print(builder, file.DataBlockHeader);
}
private static void Print(StringBuilder builder, Header? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.MajorVersion, " Major version");
builder.AppendLine(header.MinorVersion, " Minor version");
builder.AppendLine(header.CacheID, " Cache ID");
builder.AppendLine(header.LastVersionPlayed, " Last version played");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine(header.Dummy2, " Dummy 2");
builder.AppendLine(header.FileSize, " File size");
builder.AppendLine(header.BlockSize, " Block size");
builder.AppendLine(header.BlockCount, " Block count");
builder.AppendLine(header.Dummy3, " Dummy 3");
builder.AppendLine();
}
private static void Print(StringBuilder builder, BlockEntryHeader? header)
{
builder.AppendLine(" Block Entry Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No block entry header");
builder.AppendLine();
return;
}
builder.AppendLine(header.BlockCount, " Block count");
builder.AppendLine(header.BlocksUsed, " Blocks used");
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine(header.Dummy2, " Dummy 2");
builder.AppendLine(header.Dummy3, " Dummy 3");
builder.AppendLine(header.Dummy4, " Dummy 4");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine();
}
private static void Print(StringBuilder builder, BlockEntry?[]? entries)
{
builder.AppendLine(" Block Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No block entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Block Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.EntryFlags, " Entry flags");
builder.AppendLine(entry.FileDataOffset, " File data offset");
builder.AppendLine(entry.FileDataSize, " File data size");
builder.AppendLine(entry.FirstDataBlockIndex, " First data block index");
builder.AppendLine(entry.NextBlockEntryIndex, " Next block entry index");
builder.AppendLine(entry.PreviousBlockEntryIndex, " Previous block entry index");
builder.AppendLine(entry.DirectoryIndex, " Directory index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, FragmentationMapHeader? header)
{
builder.AppendLine(" Fragmentation Map Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No fragmentation map header");
builder.AppendLine();
return;
}
builder.AppendLine(header.BlockCount, " Block count");
builder.AppendLine(header.FirstUnusedEntry, " First unused entry");
builder.AppendLine(header.Terminator, " Terminator");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine();
}
private static void Print(StringBuilder builder, FragmentationMap?[]? entries)
{
builder.AppendLine(" Fragmentation Maps Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No fragmentation maps");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Fragmentation Map {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.NextDataBlockIndex, " Next data block index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, BlockEntryMapHeader? header)
{
builder.AppendLine(" Block Entry Map Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No block entry map header");
builder.AppendLine();
return;
}
builder.AppendLine(header.BlockCount, " Block count");
builder.AppendLine(header.FirstBlockEntryIndex, " First block entry index");
builder.AppendLine(header.LastBlockEntryIndex, " Last block entry index");
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine();
}
private static void Print(StringBuilder builder, BlockEntryMap?[]? entries)
{
builder.AppendLine(" Block Entry Maps Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No block entry maps");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Block Entry Map {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.PreviousBlockEntryIndex, " Previous data block index");
builder.AppendLine(entry.NextBlockEntryIndex, " Next data block index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryHeader? header)
{
builder.AppendLine(" Directory Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No directory header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.CacheID, " Cache ID");
builder.AppendLine(header.LastVersionPlayed, " Last version played");
builder.AppendLine(header.ItemCount, " Item count");
builder.AppendLine(header.FileCount, " File count");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine(header.DirectorySize, " Directory size");
builder.AppendLine(header.NameSize, " Name size");
builder.AppendLine(header.Info1Count, " Info 1 count");
builder.AppendLine(header.CopyCount, " Copy count");
builder.AppendLine(header.LocalCount, " Local count");
builder.AppendLine(header.Dummy2, " Dummy 2");
builder.AppendLine(header.Dummy3, " Dummy 3");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryEntry?[]? entries, Dictionary<long, string?>? entryNames)
{
builder.AppendLine(" Directory Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.NameOffset, " Name offset");
builder.AppendLine(entryNames![entry.NameOffset], " Name");
builder.AppendLine(entry.ItemSize, " Item size");
builder.AppendLine(entry.ChecksumIndex, " Checksum index");
builder.AppendLine($" Directory flags: {entry.DirectoryFlags} (0x{entry.DirectoryFlags:X})");
builder.AppendLine(entry.ParentIndex, " Parent index");
builder.AppendLine(entry.NextIndex, " Next index");
builder.AppendLine(entry.FirstIndex, " First index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryInfo1Entry?[]? entries)
{
builder.AppendLine(" Directory Info 1 Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory info 1 entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Info 1 Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Dummy0, " Dummy 0");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryInfo2Entry?[]? entries)
{
builder.AppendLine(" Directory Info 2 Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory info 2 entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Info 2 Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Dummy0, " Dummy 0");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryCopyEntry?[]? entries)
{
builder.AppendLine(" Directory Copy Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory copy entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Copy Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.DirectoryIndex, " Directory index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryLocalEntry?[]? entries)
{
builder.AppendLine(" Directory Local Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory local entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Local Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.DirectoryIndex, " Directory index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryMapHeader? header)
{
builder.AppendLine(" Directory Map Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No directory map header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryMapEntry?[]? entries)
{
builder.AppendLine(" Directory Map Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory map entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Map Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.FirstBlockIndex, " First block index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumHeader? header)
{
builder.AppendLine(" Checksum Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No checksum header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.ChecksumSize, " Checksum size");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumMapHeader? header)
{
builder.AppendLine(" Checksum Map Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No checksum map header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine(header.ItemCount, " Item count");
builder.AppendLine(header.ChecksumCount, " Checksum count");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumMapEntry?[]? entries)
{
builder.AppendLine(" Checksum Map Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No checksum map entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Checksum Map Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.ChecksumCount, " Checksum count");
builder.AppendLine(entry.FirstChecksumIndex, " First checksum index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumEntry?[]? entries)
{
builder.AppendLine(" Checksum Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No checksum entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Checksum Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Checksum, " Checksum");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DataBlockHeader? header)
{
builder.AppendLine(" Data Block Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No data block header");
builder.AppendLine();
return;
}
builder.AppendLine(header.LastVersionPlayed, " Last version played");
builder.AppendLine(header.BlockCount, " Block count");
builder.AppendLine(header.BlockSize, " Block size");
builder.AppendLine(header.FirstBlockOffset, " First block offset");
builder.AppendLine(header.BlocksUsed, " Blocks used");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,55 @@
using System.Text;
using SabreTools.Models.IRD;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class IRD : IPrinter<File>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, File model)
=> Print(builder, model);
public static void Print(StringBuilder builder, File ird)
{
builder.AppendLine("IRD Information:");
builder.AppendLine("-------------------------");
builder.AppendLine(ird.Magic, "Magic", Encoding.ASCII);
builder.AppendLine(ird.Version, "Version");
builder.AppendLine(ird.TitleID, "Title ID");
builder.AppendLine(ird.TitleLength, "Title length");
builder.AppendLine(ird.Title, "Title");
builder.AppendLine(ird.SystemVersion, "System version");
builder.AppendLine(ird.GameVersion, "Game version");
builder.AppendLine(ird.AppVersion, "App version");
builder.AppendLine(ird.HeaderLength, "Header length");
builder.AppendLine(ird.Header, "Header");
builder.AppendLine(ird.FooterLength, "Footer length");
builder.AppendLine(ird.Footer, "Footer");
builder.AppendLine(ird.RegionCount, "Region count");
if (ird.RegionCount != 0 && ird.RegionHashes != null && ird.RegionHashes.Length != 0)
{
for (int i = 0; i < ird.RegionCount; i++)
{
builder.AppendLine(ird.RegionHashes[i], $"Region {i} hash");
}
}
builder.AppendLine(ird.FileCount, "File count");
for (int i = 0; i < ird.FileCount; i++)
{
if (ird.FileKeys != null)
builder.AppendLine(ird.FileKeys[i], $"File {i} key");
if (ird.FileHashes != null)
builder.AppendLine(ird.FileHashes[i], $"File {i} hash");
}
builder.AppendLine(ird.ExtraConfig, "Extra config");
builder.AppendLine(ird.Attachments, "Attachments");
builder.AppendLine(ird.Data1Key, "Data 1 key");
builder.AppendLine(ird.Data2Key, "Data 2 key");
builder.AppendLine(ird.PIC, "PIC");
builder.AppendLine(ird.UID, "UID");
builder.AppendLine(ird.CRC, "CRC");
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,417 @@
using System.Collections.Generic;
using System.Text;
using SabreTools.Models.InstallShieldCabinet;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class InstallShieldCabinet : IPrinter<Cabinet>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Cabinet model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Cabinet cabinet)
{
builder.AppendLine("InstallShield Cabinet Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
// Major Version
int majorVersion = GetMajorVersion(cabinet.CommonHeader);
// Headers
Print(builder, cabinet.CommonHeader, majorVersion);
Print(builder, cabinet.VolumeHeader, majorVersion);
Print(builder, cabinet.Descriptor);
// File Descriptors
Print(builder, cabinet.FileDescriptorOffsets);
Print(builder, cabinet.DirectoryNames);
Print(builder, cabinet.FileDescriptors);
// File Groups
Print(builder, cabinet.FileGroupOffsets, "File Group");
Print(builder, cabinet.FileGroups);
// Components
Print(builder, cabinet.ComponentOffsets, "Component");
Print(builder, cabinet.Components);
}
private static int GetMajorVersion(CommonHeader? header)
{
uint majorVersion = header?.Version ?? 0;
if (majorVersion >> 24 == 1)
{
majorVersion = (majorVersion >> 12) & 0x0F;
}
else if (majorVersion >> 24 == 2 || majorVersion >> 24 == 4)
{
majorVersion = majorVersion & 0xFFFF;
if (majorVersion != 0)
majorVersion /= 100;
}
return (int)majorVersion;
}
private static void Print(StringBuilder builder, CommonHeader? header, int majorVersion)
{
builder.AppendLine(" Common Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(value: " No common header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine($" Version: {header.Version} (0x{header.Version:X}) [{majorVersion}]");
builder.AppendLine(header.VolumeInfo, " Volume info");
builder.AppendLine(header.DescriptorOffset, " Descriptor offset");
builder.AppendLine(header.DescriptorSize, " Descriptor size");
builder.AppendLine();
}
private static void Print(StringBuilder builder, VolumeHeader? header, int majorVersion)
{
builder.AppendLine(" Volume Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(value: " No volume header");
builder.AppendLine();
return;
}
if (majorVersion <= 5)
{
builder.AppendLine(header.DataOffset, " Data offset");
builder.AppendLine(header.FirstFileIndex, " First file index");
builder.AppendLine(header.LastFileIndex, " Last file index");
builder.AppendLine(header.FirstFileOffset, " First file offset");
builder.AppendLine(header.FirstFileSizeExpanded, " First file size expanded");
builder.AppendLine(header.FirstFileSizeCompressed, " First file size compressed");
builder.AppendLine(header.LastFileOffset, " Last file offset");
builder.AppendLine(header.LastFileSizeExpanded, " Last file size expanded");
builder.AppendLine(header.LastFileSizeCompressed, " Last file size compressed");
}
else
{
builder.AppendLine(header.DataOffset, " Data offset");
builder.AppendLine(header.DataOffsetHigh, " Data offset high");
builder.AppendLine(header.FirstFileIndex, " First file index");
builder.AppendLine(header.LastFileIndex, " Last file index");
builder.AppendLine(header.FirstFileOffset, " First file offset");
builder.AppendLine(header.FirstFileOffsetHigh, " First file offset high");
builder.AppendLine(header.FirstFileSizeExpanded, " First file size expanded");
builder.AppendLine(header.FirstFileSizeExpandedHigh, " First file size expanded high");
builder.AppendLine(header.FirstFileSizeCompressed, " First file size compressed");
builder.AppendLine(header.FirstFileSizeCompressedHigh, " First file size compressed high");
builder.AppendLine(header.LastFileOffset, " Last file offset");
builder.AppendLine(header.LastFileOffsetHigh, " Last file offset high");
builder.AppendLine(header.LastFileSizeExpanded, " Last file size expanded");
builder.AppendLine(header.LastFileSizeExpandedHigh, " Last file size expanded high");
builder.AppendLine(header.LastFileSizeCompressed, " Last file size compressed");
builder.AppendLine(header.LastFileSizeCompressedHigh, " Last file size compressed high");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Descriptor? descriptor)
{
builder.AppendLine(" Descriptor Information:");
builder.AppendLine(" -------------------------");
if (descriptor == null)
{
builder.AppendLine(" No descriptor");
builder.AppendLine();
return;
}
builder.AppendLine(descriptor.StringsOffset, " Strings offset");
builder.AppendLine(descriptor.Reserved0, " Reserved 0");
builder.AppendLine(descriptor.ComponentListOffset, " Component list offset");
builder.AppendLine(descriptor.FileTableOffset, " File table offset");
builder.AppendLine(descriptor.Reserved1, " Reserved 1");
builder.AppendLine(descriptor.FileTableSize, " File table size");
builder.AppendLine(descriptor.FileTableSize2, " File table size 2");
builder.AppendLine(descriptor.DirectoryCount, " Directory count");
builder.AppendLine(descriptor.Reserved2, " Reserved 2");
builder.AppendLine(descriptor.Reserved3, " Reserved 3");
builder.AppendLine(descriptor.Reserved4, " Reserved 4");
builder.AppendLine(descriptor.FileCount, " File count");
builder.AppendLine(descriptor.FileTableOffset2, " File table offset 2");
builder.AppendLine(descriptor.ComponentTableInfoCount, " Component table info count");
builder.AppendLine(descriptor.ComponentTableOffset, " Component table offset");
builder.AppendLine(descriptor.Reserved5, " Reserved 5");
builder.AppendLine(descriptor.Reserved6, " Reserved 6");
builder.AppendLine();
builder.AppendLine(" File group offsets:");
builder.AppendLine(" -------------------------");
if (descriptor.FileGroupOffsets == null || descriptor.FileGroupOffsets.Length == 0)
{
builder.AppendLine(" No file group offsets");
}
else
{
for (int i = 0; i < descriptor.FileGroupOffsets.Length; i++)
{
builder.AppendLine(descriptor.FileGroupOffsets[i], $" File Group Offset {i}");
}
}
builder.AppendLine();
builder.AppendLine(" Component offsets:");
builder.AppendLine(" -------------------------");
if (descriptor.ComponentOffsets == null || descriptor.ComponentOffsets.Length == 0)
{
builder.AppendLine(" No component offsets");
}
else
{
for (int i = 0; i < descriptor.ComponentOffsets.Length; i++)
{
builder.AppendLine(descriptor.ComponentOffsets[i], $" Component Offset {i}");
}
}
builder.AppendLine();
builder.AppendLine(descriptor.SetupTypesOffset, " Setup types offset");
builder.AppendLine(descriptor.SetupTableOffset, " Setup table offset");
builder.AppendLine(descriptor.Reserved7, " Reserved 7");
builder.AppendLine(descriptor.Reserved8, " Reserved 8");
builder.AppendLine();
}
private static void Print(StringBuilder builder, uint[]? entries)
{
builder.AppendLine(" File Descriptor Offsets:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No file descriptor offsets");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
builder.AppendLine(entries[i], $" File Descriptor Offset {i}");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, string?[]? entries)
{
builder.AppendLine(" Directory Names:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory names");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
builder.AppendLine(entries[i], $" Directory Name {i}");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, FileDescriptor?[]? entries)
{
builder.AppendLine(" File Descriptors:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No file descriptors");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" File Descriptor {i}:");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.NameOffset, " Name offset");
builder.AppendLine(entry.Name, " Name");
builder.AppendLine(entry.DirectoryIndex, " Directory index");
builder.AppendLine($" Flags: {entry.Flags} (0x{entry.Flags:X})");
builder.AppendLine(entry.ExpandedSize, " Expanded size");
builder.AppendLine(entry.CompressedSize, " Compressed size");
builder.AppendLine(entry.DataOffset, " Data offset");
builder.AppendLine(entry.MD5, " MD5");
builder.AppendLine(entry.Volume, " Volume");
builder.AppendLine(entry.LinkPrevious, " Link previous");
builder.AppendLine(entry.LinkNext, " Link next");
builder.AppendLine($" Link flags: {entry.LinkFlags} (0x{entry.LinkFlags:X})");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Dictionary<long, OffsetList?>? entries, string name)
{
builder.AppendLine($" {name} Offsets:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Count == 0)
{
builder.AppendLine($" No {name.ToLowerInvariant()} offsets");
builder.AppendLine();
return;
}
foreach (var kvp in entries)
{
long offset = kvp.Key;
var value = kvp.Value;
builder.AppendLine($" {name} Offset {offset}:");
if (value == null)
{
builder.AppendLine($" Unassigned {name.ToLowerInvariant()}");
continue;
}
builder.AppendLine(value.NameOffset, " Name offset");
builder.AppendLine(value.Name, " Name");
builder.AppendLine(value.DescriptorOffset, " Descriptor offset");
builder.AppendLine(value.NextOffset, " Next offset");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, FileGroup?[]? entries)
{
builder.AppendLine(" File Groups:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No file groups");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var fileGroup = entries[i];
builder.AppendLine($" File Group {i}:");
if (fileGroup == null)
{
builder.AppendLine(" Unassigned file group");
continue;
}
builder.AppendLine(fileGroup.NameOffset, " Name offset");
builder.AppendLine(fileGroup.Name, " Name");
builder.AppendLine(fileGroup.ExpandedSize, " Expanded size");
builder.AppendLine(fileGroup.Reserved0, " Reserved 0");
builder.AppendLine(fileGroup.CompressedSize, " Compressed size");
builder.AppendLine(fileGroup.Reserved1, " Reserved 1");
builder.AppendLine(fileGroup.Reserved2, " Reserved 2");
builder.AppendLine(fileGroup.Attribute1, " Attribute 1");
builder.AppendLine(fileGroup.Attribute2, " Attribute 2");
builder.AppendLine(fileGroup.FirstFile, " First file");
builder.AppendLine(fileGroup.LastFile, " Last file");
builder.AppendLine(fileGroup.UnknownOffset, " Unknown offset");
builder.AppendLine(fileGroup.Var4Offset, " Var 4 offset");
builder.AppendLine(fileGroup.Var1Offset, " Var 1 offset");
builder.AppendLine(fileGroup.HTTPLocationOffset, " HTTP location offset");
builder.AppendLine(fileGroup.FTPLocationOffset, " FTP location offset");
builder.AppendLine(fileGroup.MiscOffset, " Misc. offset");
builder.AppendLine(fileGroup.Var2Offset, " Var 2 offset");
builder.AppendLine(fileGroup.TargetDirectoryOffset, " Target directory offset");
builder.AppendLine(fileGroup.Reserved3, " Reserved 3");
builder.AppendLine(fileGroup.Reserved4, " Reserved 4");
builder.AppendLine(fileGroup.Reserved5, " Reserved 5");
builder.AppendLine(fileGroup.Reserved6, " Reserved 6");
builder.AppendLine(fileGroup.Reserved7, " Reserved 7");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Component?[]? entries)
{
builder.AppendLine(" Components:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No components");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var component = entries[i];
builder.AppendLine($" Component {i}:");
if (component == null)
{
builder.AppendLine(" Unassigned component");
continue;
}
builder.AppendLine(component.IdentifierOffset, " Identifier offset");
builder.AppendLine(component.Identifier, " Identifier");
builder.AppendLine(component.DescriptorOffset, " Descriptor offset");
builder.AppendLine(component.DisplayNameOffset, " Display name offset");
builder.AppendLine(component.DisplayName, " Display name");
builder.AppendLine(component.Reserved0, " Reserved 0");
builder.AppendLine(component.ReservedOffset0, " Reserved offset 0");
builder.AppendLine(component.ReservedOffset1, " Reserved offset 1");
builder.AppendLine(component.ComponentIndex, " Component index");
builder.AppendLine(component.NameOffset, " Name offset");
builder.AppendLine(component.Name, " Name");
builder.AppendLine(component.ReservedOffset2, " Reserved offset 2");
builder.AppendLine(component.ReservedOffset3, " Reserved offset 3");
builder.AppendLine(component.ReservedOffset4, " Reserved offset 4");
builder.AppendLine(component.Reserved1, " Reserved 1");
builder.AppendLine(component.CLSIDOffset, " CLSID offset");
builder.AppendLine(component.CLSID, " CLSID");
builder.AppendLine(component.Reserved2, " Reserved 2");
builder.AppendLine(component.Reserved3, " Reserved 3");
builder.AppendLine(component.DependsCount, " Depends count");
builder.AppendLine(component.DependsOffset, " Depends offset");
builder.AppendLine(component.FileGroupCount, " File group count");
builder.AppendLine(component.FileGroupNamesOffset, " File group names offset");
builder.AppendLine();
builder.AppendLine(" File group names:");
builder.AppendLine(" -------------------------");
if (component.FileGroupNames == null || component.FileGroupNames.Length == 0)
{
builder.AppendLine(" No file group names");
}
else
{
for (int j = 0; j < component.FileGroupNames.Length; j++)
{
builder.AppendLine(component.FileGroupNames[j], $" File Group Name {j}");
}
}
builder.AppendLine();
builder.AppendLine(component.X3Count, " X3 count");
builder.AppendLine(component.X3Offset, " X3 offset");
builder.AppendLine(component.SubComponentsCount, " Sub-components count");
builder.AppendLine(component.SubComponentsOffset, " Sub-components offset");
builder.AppendLine(component.NextComponentOffset, " Next component offset");
builder.AppendLine(component.ReservedOffset5, " Reserved offset 5");
builder.AppendLine(component.ReservedOffset6, " Reserved offset 6");
builder.AppendLine(component.ReservedOffset7, " Reserved offset 7");
builder.AppendLine(component.ReservedOffset8, " Reserved offset 8");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,783 @@
using System.Text;
using SabreTools.Models.LinearExecutable;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class LinearExecutable : IPrinter<Executable>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Executable model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Executable executable)
{
builder.AppendLine("New Executable Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
// Stub
Print(builder, executable.Stub?.Header);
// Information Block
Print(builder, executable.InformationBlock);
// Tables
Print(builder, executable.ObjectTable);
Print(builder, executable.ObjectPageMap);
Print(builder, executable.ResourceTable);
Print(builder, executable.ResidentNamesTable);
Print(builder, executable.EntryTable);
Print(builder, executable.ModuleFormatDirectivesTable);
Print(builder, executable.VerifyRecordDirectiveTable);
Print(builder, executable.FixupPageTable);
Print(builder, executable.FixupRecordTable);
Print(builder, executable.ImportModuleNameTable);
Print(builder, executable.ImportModuleProcedureNameTable);
Print(builder, executable.PerPageChecksumTable);
Print(builder, executable.NonResidentNamesTable);
// Debug
Print(builder, executable.DebugInformation);
}
private static void Print(StringBuilder builder, Models.MSDOS.ExecutableHeader? header)
{
builder.AppendLine(" MS-DOS Stub Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No MS-DOS stub header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Magic, " Magic number");
builder.AppendLine(header.LastPageBytes, " Last page bytes");
builder.AppendLine(header.Pages, " Pages");
builder.AppendLine(header.RelocationItems, " Relocation items");
builder.AppendLine(header.HeaderParagraphSize, " Header paragraph size");
builder.AppendLine(header.MinimumExtraParagraphs, " Minimum extra paragraphs");
builder.AppendLine(header.MaximumExtraParagraphs, " Maximum extra paragraphs");
builder.AppendLine(header.InitialSSValue, " Initial SS value");
builder.AppendLine(header.InitialSPValue, " Initial SP value");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine(header.InitialIPValue, " Initial IP value");
builder.AppendLine(header.InitialCSValue, " Initial CS value");
builder.AppendLine(header.RelocationTableAddr, " Relocation table address");
builder.AppendLine(header.OverlayNumber, " Overlay number");
builder.AppendLine();
builder.AppendLine(" MS-DOS Stub Extended Header Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(header.Reserved1, " Reserved words");
builder.AppendLine(header.OEMIdentifier, " OEM identifier");
builder.AppendLine(header.OEMInformation, " OEM information");
builder.AppendLine(header.Reserved2, " Reserved words");
builder.AppendLine(header.NewExeHeaderAddr, " New EXE header address");
builder.AppendLine();
}
private static void Print(StringBuilder builder, InformationBlock? block)
{
builder.AppendLine(" Information Block Information:");
builder.AppendLine(" -------------------------");
if (block == null)
{
builder.AppendLine(" No information block");
builder.AppendLine();
return;
}
builder.AppendLine(block.Signature, " Signature");
builder.AppendLine($" Byte order: {block.ByteOrder} (0x{block.ByteOrder:X})");
builder.AppendLine($" Word order: {block.WordOrder} (0x{block.WordOrder:X})");
builder.AppendLine(block.ExecutableFormatLevel, " Executable format level");
builder.AppendLine($" CPU type: {block.CPUType} (0x{block.CPUType:X})");
builder.AppendLine($" Module OS: {block.ModuleOS} (0x{block.ModuleOS:X})");
builder.AppendLine(block.ModuleVersion, " Module version");
builder.AppendLine($" Module type flags: {block.ModuleTypeFlags} (0x{block.ModuleTypeFlags:X})");
builder.AppendLine(block.ModuleNumberPages, " Module number pages");
builder.AppendLine(block.InitialObjectCS, " Initial object CS");
builder.AppendLine(block.InitialEIP, " Initial EIP");
builder.AppendLine(block.InitialObjectSS, " Initial object SS");
builder.AppendLine(block.InitialESP, " Initial ESP");
builder.AppendLine(block.MemoryPageSize, " Memory page size");
builder.AppendLine(block.BytesOnLastPage, " Bytes on last page");
builder.AppendLine(block.FixupSectionSize, " Fix-up section size");
builder.AppendLine(block.FixupSectionChecksum, " Fix-up section checksum");
builder.AppendLine(block.LoaderSectionSize, " Loader section size");
builder.AppendLine(block.LoaderSectionChecksum, " Loader section checksum");
builder.AppendLine(block.ObjectTableOffset, " Object table offset");
builder.AppendLine(block.ObjectTableCount, " Object table count");
builder.AppendLine(block.ObjectPageMapOffset, " Object page map offset");
builder.AppendLine(block.ObjectIterateDataMapOffset, " Object iterate data map offset");
builder.AppendLine(block.ResourceTableOffset, " Resource table offset");
builder.AppendLine(block.ResourceTableCount, " Resource table count");
builder.AppendLine(block.ResidentNamesTableOffset, " Resident names table offset");
builder.AppendLine(block.EntryTableOffset, " Entry table offset");
builder.AppendLine(block.ModuleDirectivesTableOffset, " Module directives table offset");
builder.AppendLine(block.ModuleDirectivesCount, " Module directives table count");
builder.AppendLine(block.FixupPageTableOffset, " Fix-up page table offset");
builder.AppendLine(block.FixupRecordTableOffset, " Fix-up record table offset");
builder.AppendLine(block.ImportedModulesNameTableOffset, " Imported modules name table offset");
builder.AppendLine(block.ImportedModulesCount, " Imported modules count");
builder.AppendLine(block.ImportProcedureNameTableOffset, " Imported procedure name table count");
builder.AppendLine(block.PerPageChecksumTableOffset, " Per-page checksum table offset");
builder.AppendLine(block.DataPagesOffset, " Data pages offset");
builder.AppendLine(block.PreloadPageCount, " Preload page count");
builder.AppendLine(block.NonResidentNamesTableOffset, " Non-resident names table offset");
builder.AppendLine(block.NonResidentNamesTableLength, " Non-resident names table length");
builder.AppendLine(block.NonResidentNamesTableChecksum, " Non-resident names table checksum");
builder.AppendLine(block.AutomaticDataObject, " Automatic data object");
builder.AppendLine(block.DebugInformationOffset, " Debug information offset");
builder.AppendLine(block.DebugInformationLength, " Debug information length");
builder.AppendLine(block.PreloadInstancePagesNumber, " Preload instance pages number");
builder.AppendLine(block.DemandInstancePagesNumber, " Demand instance pages number");
builder.AppendLine(block.ExtraHeapAllocation, " Extra heap allocation");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ObjectTableEntry?[]? entries)
{
builder.AppendLine(" Object Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No object table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Object Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.VirtualSegmentSize, " Virtual segment size");
builder.AppendLine(entry.RelocationBaseAddress, " Relocation base address");
builder.AppendLine($" Object flags: {entry.ObjectFlags} (0x{entry.ObjectFlags:X})");
builder.AppendLine(entry.PageTableIndex, " Page table index");
builder.AppendLine(entry.PageTableEntries, " Page table entries");
builder.AppendLine(entry.Reserved, " Reserved");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ObjectPageMapEntry?[]? entries)
{
builder.AppendLine(" Object Page Map Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No object page map entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Object Page Map Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.PageDataOffset, " Page data offset");
builder.AppendLine(entry.DataSize, " Data size");
builder.AppendLine($" Flags: {entry.Flags} (0x{entry.Flags:X})");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ResourceTableEntry?[]? entries)
{
builder.AppendLine(" Resource Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No resource table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Resource Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine($" Type ID: {entry.TypeID} (0x{entry.TypeID:X})");
builder.AppendLine(entry.NameID, " Name ID");
builder.AppendLine(entry.ResourceSize, " Resource size");
builder.AppendLine(entry.ObjectNumber, " Object number");
builder.AppendLine(entry.Offset, " Offset");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ResidentNamesTableEntry?[]? entries)
{
builder.AppendLine(" Resident Names Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No resident names table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Resident Names Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Length, " Length");
builder.AppendLine(entry.Name, " Name");
builder.AppendLine(entry.OrdinalNumber, " Ordinal number");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, EntryTableBundle?[]? bundles)
{
builder.AppendLine(" Entry Table Information:");
builder.AppendLine(" -------------------------");
if (bundles == null || bundles.Length == 0)
{
builder.AppendLine(" No entry table bundles");
builder.AppendLine();
return;
}
for (int i = 0; i < bundles.Length; i++)
{
var bundle = bundles[i];
builder.AppendLine($" Entry Table Bundle {i}");
if (bundle == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(bundle.Entries, " Entries");
builder.AppendLine($" Bundle type: {bundle.BundleType} (0x{bundle.BundleType:X})");
builder.AppendLine();
builder.AppendLine(" Entry Table Entries:");
builder.AppendLine(" -------------------------");
if (bundle.TableEntries == null || bundle.TableEntries.Length == 0)
{
builder.AppendLine(" No entry table entries");
builder.AppendLine();
continue;
}
for (int j = 0; j < bundle.TableEntries.Length; j++)
{
var entry = bundle.TableEntries[j];
builder.AppendLine($" Entry Table Entry {j}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
switch (bundle.BundleType & ~BundleType.ParameterTypingInformationPresent)
{
case BundleType.UnusedEntry:
builder.AppendLine(" Unused, empty entry");
break;
case BundleType.SixteenBitEntry:
builder.AppendLine(entry.SixteenBitObjectNumber, " Object number");
builder.AppendLine($" Entry flags: {entry.SixteenBitEntryFlags} (0x{entry.SixteenBitEntryFlags:X})");
builder.AppendLine(entry.SixteenBitOffset, " Offset");
break;
case BundleType.TwoEightySixCallGateEntry:
builder.AppendLine(entry.TwoEightySixObjectNumber, " Object number");
builder.AppendLine($" Entry flags: {entry.TwoEightySixEntryFlags} (0x{entry.TwoEightySixEntryFlags:X})");
builder.AppendLine(entry.TwoEightySixOffset, " Offset");
builder.AppendLine(entry.TwoEightySixCallgate, " Callgate");
break;
case BundleType.ThirtyTwoBitEntry:
builder.AppendLine(entry.ThirtyTwoBitObjectNumber, " Object number");
builder.AppendLine($" Entry flags: {entry.ThirtyTwoBitEntryFlags} (0x{entry.ThirtyTwoBitEntryFlags:X})");
builder.AppendLine(entry.ThirtyTwoBitOffset, " Offset");
break;
case BundleType.ForwarderEntry:
builder.AppendLine(entry.ForwarderReserved, " Reserved");
builder.AppendLine($" Forwarder flags: {entry.ForwarderFlags} (0x{entry.ForwarderFlags:X})");
builder.AppendLine(entry.ForwarderModuleOrdinalNumber, " Module ordinal number");
builder.AppendLine(entry.ProcedureNameOffset, " Procedure name offset");
builder.AppendLine(entry.ImportOrdinalNumber, " Import ordinal number");
break;
default:
builder.AppendLine($" Unknown entry type {bundle.BundleType}");
break;
}
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ModuleFormatDirectivesTableEntry?[]? entries)
{
builder.AppendLine(" Module Format Directives Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No module format directives table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Moduile Format Directives Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine($" Directive number: {entry.DirectiveNumber} (0x{entry.DirectiveNumber:X})");
builder.AppendLine(entry.DirectiveDataLength, " Directive data length");
builder.AppendLine(entry.DirectiveDataOffset, " Directive data offset");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, VerifyRecordDirectiveTableEntry?[]? entries)
{
builder.AppendLine(" Verify Record Directive Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No verify record directive table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Verify Record Directive Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.EntryCount, " Entry count");
builder.AppendLine(entry.OrdinalIndex, " Ordinal index");
builder.AppendLine(entry.Version, " Version");
builder.AppendLine(entry.ObjectEntriesCount, " Object entries count");
builder.AppendLine(entry.ObjectNumberInModule, " Object number in module");
builder.AppendLine(entry.ObjectLoadBaseAddress, " Object load base address");
builder.AppendLine(entry.ObjectVirtualAddressSize, " Object virtual address size");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, FixupPageTableEntry?[]? entries)
{
builder.AppendLine(" Fix-up Page Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No fix-up page table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Fix-up Page Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Offset, " Offset");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, FixupRecordTableEntry?[]? entries)
{
builder.AppendLine(" Fix-up Record Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No fix-up record table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Fix-up Record Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine($" Source type: {entry.SourceType} (0x{entry.SourceType:X})");
builder.AppendLine($" Target flags: {entry.TargetFlags} (0x{entry.TargetFlags:X})");
// Source list flag
#if NET20 || NET35
if ((entry.SourceType & FixupRecordSourceType.SourceListFlag) != 0)
#else
if (entry.SourceType.HasFlag(FixupRecordSourceType.SourceListFlag))
#endif
builder.AppendLine(entry.SourceOffsetListCount, " Source offset list count");
else
builder.AppendLine(entry.SourceOffset, " Source offset");
// OBJECT / TRGOFF
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.InternalReference) != 0)
#else
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.InternalReference))
#endif
{
// 16-bit Object Number/Module Ordinal Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag) != 0)
#else
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
#endif
builder.AppendLine(entry.TargetObjectNumberWORD, " Target object number");
else
builder.AppendLine(entry.TargetObjectNumberByte, " Target object number");
// 16-bit Selector fixup
#if NET20 || NET35
if ((entry.SourceType & FixupRecordSourceType.SixteenBitSelectorFixup) != 0)
#else
if (!entry.SourceType.HasFlag(FixupRecordSourceType.SixteenBitSelectorFixup))
#endif
{
// 32-bit Target Offset Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag) != 0)
#else
if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag))
#endif
builder.AppendLine(entry.TargetOffsetDWORD, " Target offset");
else
builder.AppendLine(entry.TargetOffsetWORD, " Target offset");
}
}
// MOD ORD# / IMPORT ORD / ADDITIVE
#if NET20 || NET35
else if ((entry.TargetFlags & FixupRecordTargetFlags.ImportedReferenceByOrdinal) != 0)
#else
else if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ImportedReferenceByOrdinal))
#endif
{
// 16-bit Object Number/Module Ordinal Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
#endif
builder.AppendLine(entry.OrdinalIndexImportModuleNameTableWORD, " Ordinal index import module name table");
else
builder.AppendLine(entry.OrdinalIndexImportModuleNameTableByte, " Ordinal index import module name table");
// 8-bit Ordinal Flag & 32-bit Target Offset Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.EightBitOrdinalFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.EightBitOrdinalFlag))
#endif
builder.AppendLine(entry.ImportedOrdinalNumberByte, " Imported ordinal number");
#if NET20 || NET35
else if ((entry.TargetFlags & FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag) != 0)
#else
else if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag))
#endif
builder.AppendLine(entry.ImportedOrdinalNumberDWORD, " Imported ordinal number");
else
builder.AppendLine(entry.ImportedOrdinalNumberWORD, " Imported ordinal number");
// Additive Fixup Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.AdditiveFixupFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.AdditiveFixupFlag))
#endif
{
// 32-bit Additive Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag))
#endif
builder.AppendLine(entry.AdditiveFixupValueDWORD, " Additive fixup value");
else
builder.AppendLine(entry.AdditiveFixupValueWORD, " Additive fixup value");
}
}
// MOD ORD# / PROCEDURE NAME OFFSET / ADDITIVE
#if NET20 || NET35
else if ((entry.TargetFlags & FixupRecordTargetFlags.ImportedReferenceByName) != 0)
#else
else if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ImportedReferenceByName))
#endif
{
// 16-bit Object Number/Module Ordinal Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
#endif
builder.AppendLine(entry.OrdinalIndexImportModuleNameTableWORD, " Ordinal index import module name table");
else
builder.AppendLine(entry.OrdinalIndexImportModuleNameTableByte, " Ordinal index import module name table");
// 32-bit Target Offset Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitTargetOffsetFlag))
#endif
builder.AppendLine(entry.OffsetImportProcedureNameTableDWORD, " Offset import procedure name table");
else
builder.AppendLine(entry.OffsetImportProcedureNameTableWORD, " Offset import procedure name table");
// Additive Fixup Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.AdditiveFixupFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.AdditiveFixupFlag))
#endif
{
// 32-bit Additive Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag))
#endif
builder.AppendLine(entry.AdditiveFixupValueDWORD, " Additive fixup value");
else
builder.AppendLine(entry.AdditiveFixupValueWORD, " Additive fixup value");
}
}
// ORD # / ADDITIVE
#if NET20 || NET35
else if ((entry.TargetFlags & FixupRecordTargetFlags.InternalReferenceViaEntryTable) != 0)
#else
else if (entry.TargetFlags.HasFlag(FixupRecordTargetFlags.InternalReferenceViaEntryTable))
#endif
{
// 16-bit Object Number/Module Ordinal Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.SixteenBitObjectNumberModuleOrdinalFlag))
#endif
builder.AppendLine(entry.TargetObjectNumberWORD, " Target object number");
else
builder.AppendLine(entry.TargetObjectNumberByte, " Target object number");
// Additive Fixup Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.AdditiveFixupFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.AdditiveFixupFlag))
#endif
{
// 32-bit Additive Flag
#if NET20 || NET35
if ((entry.TargetFlags & FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag) != 0)
#else
if (!entry.TargetFlags.HasFlag(FixupRecordTargetFlags.ThirtyTwoBitAdditiveFixupFlag))
#endif
builder.AppendLine(entry.AdditiveFixupValueDWORD, " Additive fixup value");
else
builder.AppendLine(entry.AdditiveFixupValueWORD, " Additive fixup value");
}
}
// No other top-level flags recognized
else
{
builder.AppendLine(" Unknown entry format");
}
builder.AppendLine();
builder.AppendLine(" Source Offset List:");
builder.AppendLine(" -------------------------");
if (entry.SourceOffsetList == null || entry.SourceOffsetList.Length == 0)
{
builder.AppendLine(" No source offset list entries");
}
else
{
for (int j = 0; j < entry.SourceOffsetList.Length; j++)
{
builder.AppendLine(entry.SourceOffsetList[j], $" Source Offset List Entry {j}");
}
}
builder.AppendLine();
}
}
private static void Print(StringBuilder builder, ImportModuleNameTableEntry?[]? entries)
{
builder.AppendLine(" Import Module Name Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No import module name table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Import Module Name Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Length, " Length");
builder.AppendLine(entry.Name, " Name");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ImportModuleProcedureNameTableEntry?[]? entries)
{
builder.AppendLine(" Import Module Procedure Name Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No import module procedure name table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Import Module Procedure Name Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Length, " Length");
builder.AppendLine(entry.Name, " Name");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, PerPageChecksumTableEntry?[]? entries)
{
builder.AppendLine(" Per-Page Checksum Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No per-page checksum table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Per-Page Checksum Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Checksum, " Checksum");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, NonResidentNamesTableEntry?[]? entries)
{
builder.AppendLine(" Non-Resident Names Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No non-resident names table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Non-Resident Names Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Length, " Length");
builder.AppendLine(entry.Name, " Name");
builder.AppendLine(entry.OrdinalNumber, " Ordinal number");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DebugInformation? di)
{
builder.AppendLine(" Debug Information:");
builder.AppendLine(" -------------------------");
if (di == null)
{
builder.AppendLine(" No debug information");
builder.AppendLine();
return;
}
builder.AppendLine(di.Signature, " Signature");
builder.AppendLine($" Format type: {di.FormatType} (0x{di.FormatType:X})");
// Debugger data
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,78 @@
using System.Text;
using SabreTools.Models.MSDOS;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class MSDOS : IPrinter<Executable>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Executable model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Executable executable)
{
builder.AppendLine("MS-DOS Executable Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, executable.Header);
Print(builder, executable.RelocationTable);
}
private static void Print(StringBuilder builder, ExecutableHeader? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Magic, " Magic number");
builder.AppendLine(header.LastPageBytes, " Last page bytes");
builder.AppendLine(header.Pages, " Pages");
builder.AppendLine(header.RelocationItems, " Relocation items");
builder.AppendLine(header.HeaderParagraphSize, " Header paragraph size");
builder.AppendLine(header.MinimumExtraParagraphs, " Minimum extra paragraphs");
builder.AppendLine(header.MaximumExtraParagraphs, " Maximum extra paragraphs");
builder.AppendLine(header.InitialSSValue, " Initial SS value");
builder.AppendLine(header.InitialSPValue, " Initial SP value");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine(header.InitialIPValue, " Initial IP value");
builder.AppendLine(header.InitialCSValue, " Initial CS value");
builder.AppendLine(header.RelocationTableAddr, " Relocation table address");
builder.AppendLine(header.OverlayNumber, " Overlay number");
builder.AppendLine();
}
private static void Print(StringBuilder builder, RelocationEntry?[]? entries)
{
builder.AppendLine(" Relocation Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No relocation table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Relocation Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Offset, " Offset");
builder.AppendLine(entry.Segment, " Segment");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,172 @@
using System.Text;
using SabreTools.Models.MicrosoftCabinet;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class MicrosoftCabinet : IPrinter<Cabinet>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Cabinet model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Cabinet cabinet)
{
builder.AppendLine("Microsoft Cabinet Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, cabinet.Header);
Print(builder, cabinet.Folders);
Print(builder, cabinet.Files);
}
private static void Print(StringBuilder builder, CFHEADER? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.Reserved1, " Reserved 1");
builder.AppendLine(header.CabinetSize, " Cabinet size");
builder.AppendLine(header.Reserved2, " Reserved 2");
builder.AppendLine(header.FilesOffset, " Files offset");
builder.AppendLine(header.Reserved3, " Reserved 3");
builder.AppendLine(header.VersionMinor, " Minor version");
builder.AppendLine(header.VersionMajor, " Major version");
builder.AppendLine(header.FolderCount, " Folder count");
builder.AppendLine(header.FileCount, " File count");
builder.AppendLine($" Flags: {header.Flags} (0x{header.Flags:X})");
builder.AppendLine(header.SetID, " Set ID");
builder.AppendLine(header.CabinetIndex, " Cabinet index");
#if NET20 || NET35
if ((header.Flags & HeaderFlags.RESERVE_PRESENT) != 0)
#else
if (header.Flags.HasFlag(HeaderFlags.RESERVE_PRESENT))
#endif
{
builder.AppendLine(header.HeaderReservedSize, " Header reserved size");
builder.AppendLine(header.FolderReservedSize, " Folder reserved size");
builder.AppendLine(header.DataReservedSize, " Data reserved size");
builder.AppendLine(header.ReservedData, " Reserved data");
}
#if NET20 || NET35
if ((header.Flags & HeaderFlags.PREV_CABINET) != 0)
#else
if (header.Flags.HasFlag(HeaderFlags.PREV_CABINET))
#endif
{
builder.AppendLine(header.CabinetPrev, " Previous cabinet");
builder.AppendLine(header.DiskPrev, " Previous disk");
}
#if NET20 || NET35
if ((header.Flags & HeaderFlags.NEXT_CABINET) != 0)
#else
if (header.Flags.HasFlag(HeaderFlags.NEXT_CABINET))
#endif
{
builder.AppendLine(header.CabinetNext, " Next cabinet");
builder.AppendLine(header.DiskNext, " Next disk");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, CFFOLDER?[]? entries)
{
builder.AppendLine(" Folders:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No folders");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Folder {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.CabStartOffset, " Cab start offset");
builder.AppendLine(entry.DataCount, " Data count");
builder.AppendLine($" Compression type: {entry.CompressionType} (0x{entry.CompressionType:X})");
builder.AppendLine($" Masked compression type: {entry.CompressionType & CompressionType.MASK_TYPE}");
builder.AppendLine(entry.ReservedData, " Reserved data");
builder.AppendLine();
builder.AppendLine(" Data Blocks");
builder.AppendLine(" -------------------------");
if (entry.DataBlocks == null || entry.DataBlocks.Length == 0)
{
builder.AppendLine(" No data blocks");
continue;
}
for (int j = 0; j < entry.DataBlocks.Length; j++)
{
var dataBlock = entry.DataBlocks[j];
builder.AppendLine($" Data Block {j}");
if (dataBlock == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(dataBlock.Checksum, " Checksum");
builder.AppendLine(dataBlock.CompressedSize, " Compressed size");
builder.AppendLine(dataBlock.UncompressedSize, " Uncompressed size");
builder.AppendLine(dataBlock.ReservedData, " Reserved data");
//builder.AppendLine(dataBlock.CompressedData, " Compressed data");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, CFFILE?[]? entries)
{
builder.AppendLine(" Files:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No files");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" File {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.FileSize, " File size");
builder.AppendLine(entry.FolderStartOffset, " Folder start offset");
builder.AppendLine($" Folder index: {entry.FolderIndex} (0x{entry.FolderIndex:X})");
builder.AppendLine(entry.Date, " Date");
builder.AppendLine(entry.Time, " Time");
builder.AppendLine($" Attributes: {entry.Attributes} (0x{entry.Attributes:X})");
builder.AppendLine(entry.Name, " Name");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,243 @@
using System.Text;
using SabreTools.Models.MoPaQ;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class MoPaQ : IPrinter<Archive>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Archive model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Archive archive)
{
builder.AppendLine("MoPaQ Archive Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, archive.UserData);
Print(builder, archive.ArchiveHeader);
Print(builder, archive.HetTable);
Print(builder, archive.BetTable);
Print(builder, archive.HashTable);
Print(builder, archive.BlockTable);
Print(builder, archive.HiBlockTable);
}
private static void Print(StringBuilder builder, UserData? userData)
{
builder.AppendLine(" User Data Information:");
builder.AppendLine(" -------------------------");
if (userData == null)
{
builder.AppendLine(" No user data");
builder.AppendLine();
return;
}
builder.AppendLine(userData.Signature, " Signature");
builder.AppendLine(userData.UserDataSize, " User data size");
builder.AppendLine(userData.HeaderOffset, " Header offset");
builder.AppendLine(userData.UserDataHeaderSize, " User data header size");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ArchiveHeader? header)
{
builder.AppendLine(" Archive Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No archive header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.HeaderSize, " Header size");
builder.AppendLine(header.ArchiveSize, " Archive size");
builder.AppendLine($" Format version: {header.FormatVersion} (0x{header.FormatVersion:X})");
builder.AppendLine(header.BlockSize, " Block size");
builder.AppendLine(header.HashTablePosition, " Hash table position");
builder.AppendLine(header.BlockTablePosition, " Block table position");
builder.AppendLine(header.HashTableSize, " Hash table size");
builder.AppendLine(header.BlockTableSize, " Block table size");
builder.AppendLine(header.HiBlockTablePosition, " Hi-block table position");
builder.AppendLine(header.HashTablePositionHi, " Hash table position hi");
builder.AppendLine(header.BlockTablePositionHi, " Block table position hi");
builder.AppendLine(header.ArchiveSizeLong, " Archive size long");
builder.AppendLine(header.BetTablePosition, " BET table position");
builder.AppendLine(header.HetTablePosition, " HET table position");
builder.AppendLine(header.HashTableSizeLong, " Hash table size long");
builder.AppendLine(header.BlockTableSizeLong, " Block table size long");
builder.AppendLine(header.HiBlockTableSize, " Hi-block table size");
builder.AppendLine(header.HetTableSize, " HET table size");
builder.AppendLine(header.BetTablesize, " BET table size"); // TODO: Fix casing
builder.AppendLine(header.RawChunkSize, " Raw chunk size");
builder.AppendLine(header.BlockTableMD5, " Block table MD5");
builder.AppendLine(header.HashTableMD5, " Hash table MD5");
builder.AppendLine(header.HiBlockTableMD5, " Hi-block table MD5");
builder.AppendLine(header.BetTableMD5, " BET table MD5");
builder.AppendLine(header.HetTableMD5, " HET table MD5");
builder.AppendLine(header.MpqHeaderMD5, " MPQ header MD5");
builder.AppendLine();
}
private static void Print(StringBuilder builder, HetTable? table)
{
builder.AppendLine(" HET Table Information:");
builder.AppendLine(" -------------------------");
if (table == null)
{
builder.AppendLine(" No HET table");
builder.AppendLine();
return;
}
builder.AppendLine(table.Signature, " Signature");
builder.AppendLine(table.Version, " Version");
builder.AppendLine(table.DataSize, " Data size");
builder.AppendLine(table.TableSize, " Table size");
builder.AppendLine(table.MaxFileCount, " Max file count");
builder.AppendLine(table.HashTableSize, " Hash table size");
builder.AppendLine(table.HashEntrySize, " Hash entry size");
builder.AppendLine(table.TotalIndexSize, " Total index size");
builder.AppendLine(table.IndexSizeExtra, " Index size extra");
builder.AppendLine(table.IndexSize, " Index size");
builder.AppendLine(table.BlockTableSize, " Block table size");
builder.AppendLine(table.HashTable, " Hash table");
builder.AppendLine(" File indexes:");
builder.AppendLine(" -------------------------");
if (table.FileIndexes == null)
{
builder.AppendLine(" No file indexes ");
}
else
{
for (int i = 0; i < table.FileIndexes.Length; i++)
{
builder.AppendLine(table.FileIndexes[i], $" File index {i}");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, BetTable? table)
{
builder.AppendLine(" BET Table Information:");
builder.AppendLine(" -------------------------");
if (table == null)
{
builder.AppendLine(" No BET table");
builder.AppendLine();
return;
}
builder.AppendLine(table.Signature, " Signature");
builder.AppendLine(table.Version, " Version");
builder.AppendLine(table.DataSize, " Data size");
builder.AppendLine(table.TableSize, " Table size");
builder.AppendLine(table.FileCount, " File count");
builder.AppendLine(table.Unknown, " Unknown");
builder.AppendLine(table.TableEntrySize, " Table entry size");
builder.AppendLine(table.FilePositionBitIndex, " File position bit index");
builder.AppendLine(table.FileSizeBitIndex, " File size bit index");
builder.AppendLine(table.CompressedSizeBitIndex, " Compressed size bit index");
builder.AppendLine(table.FlagIndexBitIndex, " Flag index bit index");
builder.AppendLine(table.UnknownBitIndex, " Unknown bit index");
builder.AppendLine(table.FilePositionBitCount, " File position bit count");
builder.AppendLine(table.FileSizeBitCount, " File size bit count");
builder.AppendLine(table.CompressedSizeBitCount, " Compressed size bit count");
builder.AppendLine(table.FlagIndexBitCount, " Flag index bit count");
builder.AppendLine(table.UnknownBitCount, " Unknown bit count");
builder.AppendLine(table.TotalBetHashSize, " Total BET hash size");
builder.AppendLine(table.BetHashSizeExtra, " BET hash size extra");
builder.AppendLine(table.BetHashSize, " BET hash size");
builder.AppendLine(table.BetHashArraySize, " BET hash array size");
builder.AppendLine(table.FlagCount, " Flag count");
builder.AppendLine(table.FlagsArray, " Flags array");
builder.AppendLine();
}
private static void Print(StringBuilder builder, HashEntry?[]? entries)
{
builder.AppendLine(" Hash Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No hash table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Hash Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.NameHashPartA, " Name hash, part A");
builder.AppendLine(entry.NameHashPartB, " Name hash, part B");
builder.AppendLine($" Locale: {entry.Locale} (0x{entry.Locale:X})");
builder.AppendLine(entry.Platform, " Platform");
builder.AppendLine(entry.BlockIndex, " BlockIndex");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, BlockEntry?[]? entries)
{
builder.AppendLine(" Block Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No block table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Block Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.FilePosition, " File position");
builder.AppendLine(entry.CompressedSize, " Compressed size");
builder.AppendLine(entry.UncompressedSize, " Uncompressed size");
builder.AppendLine($" Flags: {entry.Flags} (0x{entry.Flags:X})");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, short[]? entries)
{
builder.AppendLine(" Hi-block Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No hi-block table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Hi-block Table Entry {i}: {entry}");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,646 @@
using System.Text;
using SabreTools.Models.N3DS;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class N3DS : IPrinter<Cart>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Cart model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Cart cart)
{
builder.AppendLine("3DS Cart Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, cart.Header);
Print(builder, cart.CardInfoHeader);
Print(builder, cart.DevelopmentCardInfoHeader);
Print(builder, cart.Partitions);
Print(builder, cart.ExtendedHeaders);
Print(builder, cart.ExeFSHeaders);
Print(builder, cart.RomFSHeaders);
}
private static void Print(StringBuilder builder, NCSDHeader? header)
{
builder.AppendLine(" NCSD Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No NCSD header");
builder.AppendLine();
return;
}
builder.AppendLine(header.RSA2048Signature, " RSA-2048 SHA-256 signature");
builder.AppendLine(header.MagicNumber, " Magic number");
builder.AppendLine(header.ImageSizeInMediaUnits, " Image size in media units");
builder.AppendLine(header.MediaId, " Media ID");
builder.AppendLine($" Partitions filesystem type: {header.PartitionsFSType} (0x{header.PartitionsFSType:X})");
builder.AppendLine(header.PartitionsCryptType, " Partitions crypt type");
builder.AppendLine();
builder.AppendLine(" Partition table:");
builder.AppendLine(" -------------------------");
if (header.PartitionsTable == null || header.PartitionsTable.Length == 0)
{
builder.AppendLine(" No partition table entries");
}
else
{
for (int i = 0; i < header.PartitionsTable.Length; i++)
{
var partitionTableEntry = header.PartitionsTable[i];
builder.AppendLine($" Partition table entry {i}");
if (partitionTableEntry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(partitionTableEntry.Offset, " Offset");
builder.AppendLine(partitionTableEntry.Length, " Length");
}
}
builder.AppendLine();
// If we have a cart image
if (header.PartitionsFSType == FilesystemType.Normal || header.PartitionsFSType == FilesystemType.None)
{
builder.AppendLine(header.ExheaderHash, " Exheader SHA-256 hash");
builder.AppendLine(header.AdditionalHeaderSize, " Additional header size");
builder.AppendLine(header.SectorZeroOffset, " Sector zero offset");
builder.AppendLine(header.PartitionFlags, " Partition flags");
builder.AppendLine();
builder.AppendLine(" Partition ID table:");
builder.AppendLine(" -------------------------");
if (header.PartitionIdTable == null || header.PartitionIdTable.Length == 0)
{
builder.AppendLine(" No partition ID table entries");
}
else
{
for (int i = 0; i < header.PartitionIdTable.Length; i++)
{
builder.AppendLine(header.PartitionIdTable[i], $" Partition {i} ID");
}
}
builder.AppendLine();
builder.AppendLine(header.Reserved1, " Reserved 1");
builder.AppendLine(header.Reserved2, " Reserved 2");
builder.AppendLine(header.FirmUpdateByte1, " Firmware update byte 1");
builder.AppendLine(header.FirmUpdateByte2, " Firmware update byte 2");
}
// If we have a firmware image
else if (header.PartitionsFSType == FilesystemType.FIRM)
{
builder.AppendLine(header.Unknown, " Unknown");
builder.AppendLine(header.EncryptedMBR, " Encrypted MBR");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, CardInfoHeader? header)
{
builder.AppendLine(" Card Info Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No card info header");
builder.AppendLine();
return;
}
builder.AppendLine(header.WritableAddressMediaUnits, " Writable address in media units");
builder.AppendLine(header.CardInfoBitmask, " Card info bitmask");
builder.AppendLine(header.Reserved1, " Reserved 1");
builder.AppendLine(header.FilledSize, " Filled size of cartridge");
builder.AppendLine(header.Reserved2, " Reserved 2");
builder.AppendLine(header.TitleVersion, " Title version");
builder.AppendLine(header.CardRevision, " Card revision");
builder.AppendLine(header.Reserved3, " Reserved 3");
builder.AppendLine(header.CVerTitleID, " Title ID of CVer in included update partition");
builder.AppendLine(header.CVerVersionNumber, " Version number of CVer in included update partition");
builder.AppendLine(header.Reserved4, " Reserved 4");
builder.AppendLine();
}
private static void Print(StringBuilder builder, DevelopmentCardInfoHeader? header)
{
builder.AppendLine(" Development Card Info Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No development card info header");
builder.AppendLine();
return;
}
builder.AppendLine();
builder.AppendLine(" Initial Data:");
builder.AppendLine(" -------------------------");
if (header.InitialData == null)
{
builder.AppendLine(" No initial data");
}
else
{
builder.AppendLine(header.InitialData.CardSeedKeyY, " Card seed keyY");
builder.AppendLine(header.InitialData.EncryptedCardSeed, " Encrypted card seed");
builder.AppendLine(header.InitialData.CardSeedAESMAC, " Card seed AES-MAC");
builder.AppendLine(header.InitialData.CardSeedNonce, " Card seed nonce");
builder.AppendLine(header.InitialData.Reserved, " Reserved");
builder.AppendLine();
builder.AppendLine(" Backup Header:");
builder.AppendLine(" -------------------------");
if (header.InitialData.BackupHeader == null)
{
builder.AppendLine(" No backup header");
}
else
{
builder.AppendLine(header.InitialData.BackupHeader.MagicID, " Magic ID");
builder.AppendLine(header.InitialData.BackupHeader.ContentSizeInMediaUnits, " Content size in media units");
builder.AppendLine(header.InitialData.BackupHeader.PartitionId, " Partition ID");
builder.AppendLine(header.InitialData.BackupHeader.MakerCode, " Maker code");
builder.AppendLine(header.InitialData.BackupHeader.Version, " Version");
builder.AppendLine(header.InitialData.BackupHeader.VerificationHash, " Verification hash");
builder.AppendLine(header.InitialData.BackupHeader.ProgramId, " Program ID");
builder.AppendLine(header.InitialData.BackupHeader.Reserved1, " Reserved 1");
builder.AppendLine(header.InitialData.BackupHeader.LogoRegionHash, " Logo region SHA-256 hash");
builder.AppendLine(header.InitialData.BackupHeader.ProductCode, " Product code");
builder.AppendLine(header.InitialData.BackupHeader.ExtendedHeaderHash, " Extended header SHA-256 hash");
builder.AppendLine(header.InitialData.BackupHeader.ExtendedHeaderSizeInBytes, " Extended header size in bytes");
builder.AppendLine(header.InitialData.BackupHeader.Reserved2, " Reserved 2");
builder.AppendLine($" Flags: {header.InitialData.BackupHeader.Flags} (0x{header.InitialData.BackupHeader.Flags:X})");
builder.AppendLine(header.InitialData.BackupHeader.PlainRegionOffsetInMediaUnits, " Plain region offset, in media units");
builder.AppendLine(header.InitialData.BackupHeader.PlainRegionSizeInMediaUnits, " Plain region size, in media units");
builder.AppendLine(header.InitialData.BackupHeader.LogoRegionOffsetInMediaUnits, " Logo region offset, in media units");
builder.AppendLine(header.InitialData.BackupHeader.LogoRegionSizeInMediaUnits, " Logo region size, in media units");
builder.AppendLine(header.InitialData.BackupHeader.ExeFSOffsetInMediaUnits, " ExeFS offset, in media units");
builder.AppendLine(header.InitialData.BackupHeader.ExeFSSizeInMediaUnits, " ExeFS size, in media units");
builder.AppendLine(header.InitialData.BackupHeader.ExeFSHashRegionSizeInMediaUnits, " ExeFS hash region size, in media units");
builder.AppendLine(header.InitialData.BackupHeader.Reserved3, " Reserved 3");
builder.AppendLine(header.InitialData.BackupHeader.RomFSOffsetInMediaUnits, " RomFS offset, in media units");
builder.AppendLine(header.InitialData.BackupHeader.RomFSSizeInMediaUnits, " RomFS size, in media units");
builder.AppendLine(header.InitialData.BackupHeader.RomFSHashRegionSizeInMediaUnits, " RomFS hash region size, in media units");
builder.AppendLine(header.InitialData.BackupHeader.Reserved4, " Reserved 4");
builder.AppendLine(header.InitialData.BackupHeader.ExeFSSuperblockHash, " ExeFS superblock SHA-256 hash");
builder.AppendLine(header.InitialData.BackupHeader.RomFSSuperblockHash, " RomFS superblock SHA-256 hash");
}
}
builder.AppendLine();
builder.AppendLine(header.CardDeviceReserved1, " Card device reserved 1");
builder.AppendLine(header.TitleKey, " Title key");
builder.AppendLine(header.CardDeviceReserved2, " Card device reserved 2");
builder.AppendLine();
builder.AppendLine(" Test Data:");
builder.AppendLine(" -------------------------");
if (header.TestData == null)
{
builder.AppendLine(" No test data");
}
else
{
builder.AppendLine(header.TestData.Signature, " Signature");
builder.AppendLine(header.TestData.AscendingByteSequence, " Ascending byte sequence");
builder.AppendLine(header.TestData.DescendingByteSequence, " Descending byte sequence");
builder.AppendLine(header.TestData.Filled00, " Filled with 00");
builder.AppendLine(header.TestData.FilledFF, " Filled with FF");
builder.AppendLine(header.TestData.Filled0F, " Filled with 0F");
builder.AppendLine(header.TestData.FilledF0, " Filled with F0");
builder.AppendLine(header.TestData.Filled55, " Filled with 55");
builder.AppendLine(header.TestData.FilledAA, " Filled with AA");
builder.AppendLine(header.TestData.FinalByte, " Final byte");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, NCCHHeader?[]? entries)
{
builder.AppendLine(" NCCH Partition Header Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No NCCH partition headers");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" NCCH Partition Header {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
if (entry.MagicID == string.Empty)
{
builder.AppendLine(" Empty partition, no data can be parsed");
}
else if (entry.MagicID != Constants.NCCHMagicNumber)
{
builder.AppendLine(" Unrecognized partition data, no data can be parsed");
}
else
{
builder.AppendLine(entry.RSA2048Signature, " RSA-2048 SHA-256 signature");
builder.AppendLine(entry.MagicID, " Magic ID");
builder.AppendLine(entry.ContentSizeInMediaUnits, " Content size in media units");
builder.AppendLine(entry.PartitionId, " Partition ID");
builder.AppendLine(entry.MakerCode, " Maker code");
builder.AppendLine(entry.Version, " Version");
builder.AppendLine(entry.VerificationHash, " Verification hash");
builder.AppendLine(entry.ProgramId, " Program ID");
builder.AppendLine(entry.Reserved1, " Reserved 1");
builder.AppendLine(entry.LogoRegionHash, " Logo region SHA-256 hash");
builder.AppendLine(entry.ProductCode, " Product code");
builder.AppendLine(entry.ExtendedHeaderHash, " Extended header SHA-256 hash");
builder.AppendLine(entry.ExtendedHeaderSizeInBytes, " Extended header size in bytes");
builder.AppendLine(entry.Reserved2, " Reserved 2");
builder.AppendLine(" Flags:");
if (entry.Flags == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.Flags.Reserved0, " Reserved 0");
builder.AppendLine(entry.Flags.Reserved1, " Reserved 1");
builder.AppendLine(entry.Flags.Reserved2, " Reserved 2");
builder.AppendLine($" Crypto method: {entry.Flags.CryptoMethod} (0x{entry.Flags.CryptoMethod:X})");
builder.AppendLine($" Content platform: {entry.Flags.ContentPlatform} (0x{entry.Flags.ContentPlatform:X})");
builder.AppendLine($" Content type: {entry.Flags.MediaPlatformIndex} (0x{entry.Flags.MediaPlatformIndex:X})");
builder.AppendLine(entry.Flags.ContentUnitSize, " Content unit size");
builder.AppendLine($" Bitmasks: {entry.Flags.BitMasks} (0x{entry.Flags.BitMasks:X})");
}
builder.AppendLine(entry.PlainRegionOffsetInMediaUnits, " Plain region offset, in media units");
builder.AppendLine(entry.PlainRegionSizeInMediaUnits, " Plain region size, in media units");
builder.AppendLine(entry.LogoRegionOffsetInMediaUnits, " Logo region offset, in media units");
builder.AppendLine(entry.LogoRegionSizeInMediaUnits, " Logo region size, in media units");
builder.AppendLine(entry.ExeFSOffsetInMediaUnits, " ExeFS offset, in media units");
builder.AppendLine(entry.ExeFSSizeInMediaUnits, " ExeFS size, in media units");
builder.AppendLine(entry.ExeFSHashRegionSizeInMediaUnits, " ExeFS hash region size, in media units");
builder.AppendLine(entry.Reserved3, " Reserved 3");
builder.AppendLine(entry.RomFSOffsetInMediaUnits, " RomFS offset, in media units");
builder.AppendLine(entry.RomFSSizeInMediaUnits, " RomFS size, in media units");
builder.AppendLine(entry.RomFSHashRegionSizeInMediaUnits, " RomFS hash region size, in media units");
builder.AppendLine(entry.Reserved4, " Reserved 4");
builder.AppendLine(entry.ExeFSSuperblockHash, " ExeFS superblock SHA-256 hash");
builder.AppendLine(entry.RomFSSuperblockHash, " RomFS superblock SHA-256 hash");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, NCCHExtendedHeader?[]? entries)
{
builder.AppendLine(" NCCH Extended Header Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No NCCH extended headers");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" NCCH Extended Header {i}");
if (entry == null)
{
builder.AppendLine(" Unrecognized partition data, no data can be parsed");
continue;
}
builder.AppendLine(" System control info:");
if (entry.SCI == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.SCI.ApplicationTitle, " Application title");
builder.AppendLine(entry.SCI.Reserved1, " Reserved 1");
builder.AppendLine(entry.SCI.Flag, " Flag");
builder.AppendLine(entry.SCI.RemasterVersion, " Remaster version");
builder.AppendLine(" Text code set info:");
if (entry.SCI.TextCodeSetInfo == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.SCI.TextCodeSetInfo.Address, " Address");
builder.AppendLine(entry.SCI.TextCodeSetInfo.PhysicalRegionSizeInPages, " Physical region size (in page-multiples)");
builder.AppendLine(entry.SCI.TextCodeSetInfo.SizeInBytes, " Size (in bytes)");
}
builder.AppendLine(entry.SCI.StackSize, " Stack size");
builder.AppendLine(" Read-only code set info:");
if (entry.SCI.ReadOnlyCodeSetInfo == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.SCI.ReadOnlyCodeSetInfo.Address, " Address");
builder.AppendLine(entry.SCI.ReadOnlyCodeSetInfo.PhysicalRegionSizeInPages, " Physical region size (in page-multiples)");
builder.AppendLine(entry.SCI.ReadOnlyCodeSetInfo.SizeInBytes, " Size (in bytes)");
}
builder.AppendLine(entry.SCI.Reserved2, " Reserved 2");
builder.AppendLine(" Data code set info:");
if (entry.SCI.DataCodeSetInfo == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.SCI.DataCodeSetInfo.Address, " Address");
builder.AppendLine(entry.SCI.DataCodeSetInfo.PhysicalRegionSizeInPages, " Physical region size (in page-multiples)");
builder.AppendLine(entry.SCI.DataCodeSetInfo.SizeInBytes, " Size (in bytes)");
}
builder.AppendLine(entry.SCI.BSSSize, " BSS size");
builder.AppendLine(entry.SCI.DependencyModuleList, " Dependency module list");
builder.AppendLine(" System info:");
if (entry.SCI.SystemInfo == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.SCI.SystemInfo.SaveDataSize, " SaveData size");
builder.AppendLine(entry.SCI.SystemInfo.JumpID, " Jump ID");
builder.AppendLine(entry.SCI.SystemInfo.Reserved, " Reserved");
}
}
builder.AppendLine(" Access control info:");
if (entry.ACI == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(" ARM11 local system capabilities:");
if (entry.ACI.ARM11LocalSystemCapabilities == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ProgramID, " Program ID");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.CoreVersion, " Core version");
builder.AppendLine($" Flag 1: {entry.ACI.ARM11LocalSystemCapabilities.Flag1} (0x{entry.ACI.ARM11LocalSystemCapabilities.Flag1:X})");
builder.AppendLine($" Flag 2: {entry.ACI.ARM11LocalSystemCapabilities.Flag2} (0x{entry.ACI.ARM11LocalSystemCapabilities.Flag2:X})");
builder.AppendLine($" Flag 0: {entry.ACI.ARM11LocalSystemCapabilities.Flag0} (0x{entry.ACI.ARM11LocalSystemCapabilities.Flag0:X})");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.Priority, " Priority");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ResourceLimitDescriptors, " Resource limit descriptors");
builder.AppendLine(" Storage info:");
if (entry.ACI.ARM11LocalSystemCapabilities.StorageInfo == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID, " Extdata ID");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs, " System savedata IDs");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs, " Storage accessible unique IDs");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo, " File system access info");
builder.AppendLine($" Other attributes: {entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{entry.ACI.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})");
}
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ServiceAccessControl, " Service access control");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl, " Extended service access control");
builder.AppendLine(entry.ACI.ARM11LocalSystemCapabilities.Reserved, " Reserved");
builder.AppendLine($" Resource limit cateogry: {entry.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{entry.ACI.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})");
}
builder.AppendLine(" ARM11 kernel capabilities:");
if (entry.ACI.ARM11KernelCapabilities == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACI.ARM11KernelCapabilities.Descriptors, " Descriptors");
builder.AppendLine(entry.ACI.ARM11KernelCapabilities.Reserved, " Reserved");
}
builder.AppendLine(" ARM9 access control:");
if (entry.ACI.ARM9AccessControl == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACI.ARM9AccessControl.Descriptors, " Descriptors");
builder.AppendLine(entry.ACI.ARM9AccessControl.DescriptorVersion, " Descriptor version");
}
builder.AppendLine(entry.AccessDescSignature, " AccessDec signature (RSA-2048-SHA256)");
builder.AppendLine(entry.NCCHHDRPublicKey, " NCCH HDR RSA-2048 public key");
}
builder.AppendLine(" Access control info (for limitations of first ACI):");
if (entry.ACIForLimitations == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(" ARM11 local system capabilities:");
if (entry.ACIForLimitations.ARM11LocalSystemCapabilities == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ProgramID, " Program ID");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.CoreVersion, " Core version");
builder.AppendLine($" Flag 1: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag1} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag1:X})");
builder.AppendLine($" Flag 2: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag2:X})");
builder.AppendLine($" Flag 0: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.Flag0:X})");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.Priority, " Priority");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitDescriptors, " Resource limit descriptors");
builder.AppendLine(" Storage info:");
if (entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.ExtdataID, " Extdata ID");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.SystemSavedataIDs, " System savedata IDs");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.StorageAccessibleUniqueIDs, " Storage accessible unique IDs");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.FileSystemAccessInfo, " File system access info");
builder.AppendLine($" Other attributes: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.StorageInfo.OtherAttributes:X})");
}
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ServiceAccessControl, " Service access control");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.ExtendedServiceAccessControl, " Extended service access control");
builder.AppendLine(entry.ACIForLimitations.ARM11LocalSystemCapabilities.Reserved, " Reserved");
builder.AppendLine($" Resource limit cateogry: {entry.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory} (0x{entry.ACIForLimitations.ARM11LocalSystemCapabilities.ResourceLimitCategory:X})");
}
builder.AppendLine(" ARM11 kernel capabilities:");
if (entry.ACIForLimitations.ARM11KernelCapabilities == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACIForLimitations.ARM11KernelCapabilities.Descriptors, " Descriptors");
builder.AppendLine(entry.ACIForLimitations.ARM11KernelCapabilities.Reserved, " Reserved");
}
builder.AppendLine(" ARM9 access control:");
if (entry.ACIForLimitations.ARM9AccessControl == null)
{
builder.AppendLine(" [NULL]");
}
else
{
builder.AppendLine(entry.ACIForLimitations.ARM9AccessControl.Descriptors, " Descriptors");
builder.AppendLine(entry.ACIForLimitations.ARM9AccessControl.DescriptorVersion, " Descriptor version");
}
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ExeFSHeader?[]? entries)
{
builder.AppendLine(" ExeFS Header Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No ExeFS headers");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" ExeFS Header {i}");
if (entry == null)
{
builder.AppendLine(" Unrecognized partition data, no data can be parsed");
continue;
}
builder.AppendLine(" File headers:");
if (entry.FileHeaders == null || entry.FileHeaders.Length == 0)
{
builder.AppendLine(" No file headers");
}
else
{
for (int j = 0; j < entry.FileHeaders.Length; j++)
{
var fileHeader = entry.FileHeaders[j];
builder.AppendLine($" File Header {j}");
if (fileHeader == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(fileHeader.FileName, " File name");
builder.AppendLine(fileHeader.FileOffset, " File offset");
builder.AppendLine(fileHeader.FileSize, " File size");
}
}
builder.AppendLine(entry.Reserved, " Reserved");
builder.AppendLine(" File hashes:");
if (entry.FileHashes == null || entry.FileHashes.Length == 0)
{
builder.AppendLine(" No file hashes");
}
else
{
for (int j = 0; j < entry.FileHashes.Length; j++)
{
var fileHash = entry.FileHashes[j];
builder.AppendLine($" File Hash {j}");
if (fileHash == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(fileHash, " SHA-256");
}
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, RomFSHeader?[]? entries)
{
builder.AppendLine(" RomFS Header Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No RomFS headers");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var romFSHeader = entries[i];
builder.AppendLine($" RomFS Header {i}");
if (romFSHeader == null)
{
builder.AppendLine(" Unrecognized RomFS data, no data can be parsed");
continue;
}
builder.AppendLine(romFSHeader.MagicString, " Magic string");
builder.AppendLine(romFSHeader.MagicNumber, " Magic number");
builder.AppendLine(romFSHeader.MasterHashSize, " Master hash size");
builder.AppendLine(romFSHeader.Level1LogicalOffset, " Level 1 logical offset");
builder.AppendLine(romFSHeader.Level1HashdataSize, " Level 1 hashdata size");
builder.AppendLine(romFSHeader.Level1BlockSizeLog2, " Level 1 block size");
builder.AppendLine(romFSHeader.Reserved1, " Reserved 1");
builder.AppendLine(romFSHeader.Level2LogicalOffset, " Level 2 logical offset");
builder.AppendLine(romFSHeader.Level2HashdataSize, " Level 2 hashdata size");
builder.AppendLine(romFSHeader.Level2BlockSizeLog2, " Level 2 block size");
builder.AppendLine(romFSHeader.Reserved2, " Reserved 2");
builder.AppendLine(romFSHeader.Level3LogicalOffset, " Level 3 logical offset");
builder.AppendLine(romFSHeader.Level3HashdataSize, " Level 3 hashdata size");
builder.AppendLine(romFSHeader.Level3BlockSizeLog2, " Level 3 block size");
builder.AppendLine(romFSHeader.Reserved3, " Reserved 3");
builder.AppendLine(romFSHeader.Reserved4, " Reserved 4");
builder.AppendLine(romFSHeader.OptionalInfoSize, " Optional info size");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,360 @@
using System.Collections.Generic;
using System.Text;
using SabreTools.Models.NCF;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class NCF : IPrinter<File>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, File model)
=> Print(builder, model);
public static void Print(StringBuilder builder, File file)
{
builder.AppendLine("NCF Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
// Header
Print(builder, file.Header);
// Directory and Directory Maps
Print(builder, file.DirectoryHeader);
Print(builder, file.DirectoryEntries, file.DirectoryNames);
// TODO: Should we print out the entire string table?
Print(builder, file.DirectoryInfo1Entries);
Print(builder, file.DirectoryInfo2Entries);
Print(builder, file.DirectoryCopyEntries);
Print(builder, file.DirectoryLocalEntries);
Print(builder, file.UnknownHeader);
Print(builder, file.UnknownEntries);
// Checksums and Checksum Maps
Print(builder, file.ChecksumHeader);
Print(builder, file.ChecksumMapHeader);
Print(builder, file.ChecksumMapEntries);
Print(builder, file.ChecksumEntries);
}
private static void Print(StringBuilder builder, Header? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.MajorVersion, " Major version");
builder.AppendLine(header.MinorVersion, " Minor version");
builder.AppendLine(header.CacheID, " Cache ID");
builder.AppendLine(header.LastVersionPlayed, " Last version played");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine(header.Dummy2, " Dummy 2");
builder.AppendLine(header.FileSize, " File size");
builder.AppendLine(header.BlockSize, " Block size");
builder.AppendLine(header.BlockCount, " Block count");
builder.AppendLine(header.Dummy3, " Dummy 3");
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryHeader? header)
{
builder.AppendLine(" Directory Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No directory header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.CacheID, " Cache ID");
builder.AppendLine(header.LastVersionPlayed, " Last version played");
builder.AppendLine(header.ItemCount, " Item count");
builder.AppendLine(header.FileCount, " File count");
builder.AppendLine(header.ChecksumDataLength, " Checksum data length");
builder.AppendLine(header.DirectorySize, " Directory size");
builder.AppendLine(header.NameSize, " Name size");
builder.AppendLine(header.Info1Count, " Info 1 count");
builder.AppendLine(header.CopyCount, " Copy count");
builder.AppendLine(header.LocalCount, " Local count");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine(header.Dummy2, " Dummy 2");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryEntry?[]? entries, Dictionary<long, string?>? entryNames)
{
builder.AppendLine(" Directory Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.NameOffset, " Name offset");
builder.AppendLine(entryNames![entry.NameOffset], " Name");
builder.AppendLine(entry.ItemSize, " Item size");
builder.AppendLine(entry.ChecksumIndex, " Checksum index");
builder.AppendLine($" Directory flags: {entry.DirectoryFlags} (0x{entry.DirectoryFlags:X})");
builder.AppendLine(entry.ParentIndex, " Parent index");
builder.AppendLine(entry.NextIndex, " Next index");
builder.AppendLine(entry.FirstIndex, " First index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryInfo1Entry?[]? entries)
{
builder.AppendLine(" Directory Info 1 Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory info 1 entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Info 1 Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Dummy0, " Dummy 0");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryInfo2Entry?[]? entries)
{
builder.AppendLine(" Directory Info 2 Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory info 2 entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Info 2 Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Dummy0, " Dummy 0");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryCopyEntry?[]? entries)
{
builder.AppendLine(" Directory Copy Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory copy entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Copy Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.DirectoryIndex, " Directory index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryLocalEntry?[]? entries)
{
builder.AppendLine(" Directory Local Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory local entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Local Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.DirectoryIndex, " Directory index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, UnknownHeader? header)
{
builder.AppendLine(" Unknown Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No unknown header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine();
}
private static void Print(StringBuilder builder, UnknownEntry?[]? entries)
{
builder.AppendLine(" Unknown Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No unknown entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Unknown Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Dummy0, " Dummy 0");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumHeader? header)
{
builder.AppendLine(" Checksum Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No checksum header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.ChecksumSize, " Checksum size");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumMapHeader? header)
{
builder.AppendLine(" Checksum Map Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No checksum map header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Dummy0, " Dummy 0");
builder.AppendLine(header.Dummy1, " Dummy 1");
builder.AppendLine(header.ItemCount, " Item count");
builder.AppendLine(header.ChecksumCount, " Checksum count");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumMapEntry?[]? entries)
{
builder.AppendLine(" Checksum Map Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No checksum map entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Checksum Map Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.ChecksumCount, " Checksum count");
builder.AppendLine(entry.FirstChecksumIndex, " First checksum index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ChecksumEntry?[]? entries)
{
builder.AppendLine(" Checksum Entries Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No checksum entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Checksum Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Checksum, " Checksum");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,379 @@
using System.Collections.Generic;
using System.Text;
using SabreTools.Models.NewExecutable;
using SabreTools.Serialization.Interfaces;
using static SabreTools.Serialization.Extensions;
namespace SabreTools.Serialization.Printers
{
public class NewExecutable : IPrinter<Executable>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Executable model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Executable executable)
{
builder.AppendLine("New Executable Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
// Stub
Print(builder, executable.Stub?.Header);
// Header
Print(builder, executable.Header);
// Tables
Print(builder, executable.SegmentTable);
Print(builder, executable.ResourceTable);
Print(builder, executable.ResidentNameTable);
Print(builder, executable.ModuleReferenceTable, executable.Stub?.Header, executable.Header);
Print(builder, executable.ImportedNameTable);
Print(builder, executable.EntryTable);
Print(builder, executable.NonResidentNameTable);
}
private static void Print(StringBuilder builder, Models.MSDOS.ExecutableHeader? header)
{
builder.AppendLine(" MS-DOS Stub Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No MS-DOS stub header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Magic, " Magic number");
builder.AppendLine(header.LastPageBytes, " Last page bytes");
builder.AppendLine(header.Pages, " Pages");
builder.AppendLine(header.RelocationItems, " Relocation items");
builder.AppendLine(header.HeaderParagraphSize, " Header paragraph size");
builder.AppendLine(header.MinimumExtraParagraphs, " Minimum extra paragraphs");
builder.AppendLine(header.MaximumExtraParagraphs, " Maximum extra paragraphs");
builder.AppendLine(header.InitialSSValue, " Initial SS value");
builder.AppendLine(header.InitialSPValue, " Initial SP value");
builder.AppendLine(header.Checksum, " Checksum");
builder.AppendLine(header.InitialIPValue, " Initial IP value");
builder.AppendLine(header.InitialCSValue, " Initial CS value");
builder.AppendLine(header.RelocationTableAddr, " Relocation table address");
builder.AppendLine(header.OverlayNumber, " Overlay number");
builder.AppendLine();
builder.AppendLine(" MS-DOS Stub Extended Header Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(header.Reserved1, " Reserved words");
builder.AppendLine(header.OEMIdentifier, " OEM identifier");
builder.AppendLine(header.OEMInformation, " OEM information");
builder.AppendLine(header.Reserved2, " Reserved words");
builder.AppendLine(header.NewExeHeaderAddr, " New EXE header address");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ExecutableHeader? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Magic, " Magic number");
builder.AppendLine(header.LinkerVersion, " Linker version");
builder.AppendLine(header.LinkerRevision, " Linker revision");
builder.AppendLine(header.EntryTableOffset, " Entry table offset");
builder.AppendLine(header.EntryTableSize, " Entry table size");
builder.AppendLine(header.CrcChecksum, " CRC checksum");
builder.AppendLine($" Flag word: {header.FlagWord} (0x{header.FlagWord:X})");
builder.AppendLine(header.AutomaticDataSegmentNumber, " Automatic data segment number");
builder.AppendLine(header.InitialHeapAlloc, " Initial heap allocation");
builder.AppendLine(header.InitialStackAlloc, " Initial stack allocation");
builder.AppendLine(header.InitialCSIPSetting, " Initial CS:IP setting");
builder.AppendLine(header.InitialSSSPSetting, " Initial SS:SP setting");
builder.AppendLine(header.FileSegmentCount, " File segment count");
builder.AppendLine(header.ModuleReferenceTableSize, " Module reference table size");
builder.AppendLine(header.NonResidentNameTableSize, " Non-resident name table size");
builder.AppendLine(header.SegmentTableOffset, " Segment table offset");
builder.AppendLine(header.ResourceTableOffset, " Resource table offset");
builder.AppendLine(header.ResidentNameTableOffset, " Resident name table offset");
builder.AppendLine(header.ModuleReferenceTableOffset, " Module reference table offset");
builder.AppendLine(header.ImportedNamesTableOffset, " Imported names table offset");
builder.AppendLine(header.NonResidentNamesTableOffset, " Non-resident name table offset");
builder.AppendLine(header.MovableEntriesCount, " Moveable entries count");
builder.AppendLine(header.SegmentAlignmentShiftCount, " Segment alignment shift count");
builder.AppendLine(header.ResourceEntriesCount, " Resource entries count");
builder.AppendLine($" Target operating system: {header.TargetOperatingSystem} (0x{header.TargetOperatingSystem:X})");
builder.AppendLine($" Additional flags: {header.AdditionalFlags} (0x{header.AdditionalFlags:X})");
builder.AppendLine(header.ReturnThunkOffset, " Return thunk offset");
builder.AppendLine(header.SegmentReferenceThunkOffset, " Segment reference thunk offset");
builder.AppendLine(header.MinCodeSwapAreaSize, " Minimum code swap area size");
builder.AppendLine(header.WindowsSDKRevision, " Windows SDK revision");
builder.AppendLine(header.WindowsSDKVersion, " Windows SDK version");
builder.AppendLine();
}
private static void Print(StringBuilder builder, SegmentTableEntry?[]? entries)
{
builder.AppendLine(" Segment Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No segment table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Segment Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Offset, " Offset");
builder.AppendLine(entry.Length, " Length");
builder.AppendLine($" Flag word: {entry.FlagWord} (0x{entry.FlagWord:X})");
builder.AppendLine(entry.MinimumAllocationSize, " Minimum allocation size");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ResourceTable? table)
{
builder.AppendLine(" Resource Table Information:");
builder.AppendLine(" -------------------------");
if (table == null)
{
builder.AppendLine(" No resource table");
builder.AppendLine();
return;
}
builder.AppendLine(table.AlignmentShiftCount, " Alignment shift count");
if (table.ResourceTypes == null || table.ResourceTypes.Length == 0)
{
builder.AppendLine(" No resource table items");
}
else
{
for (int i = 0; i < table.ResourceTypes.Length; i++)
{
// TODO: If not integer type, print out name
var entry = table.ResourceTypes[i];
builder.AppendLine($" Resource Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.TypeID, " Type ID");
builder.AppendLine(entry.ResourceCount, " Resource count");
builder.AppendLine(entry.Reserved, " Reserved");
builder.AppendLine(" Resources = ");
if (entry.ResourceCount == 0 || entry.Resources == null || entry.Resources.Length == 0)
{
builder.AppendLine(" No resource items");
}
else
{
for (int j = 0; j < entry.Resources.Length; j++)
{
// TODO: If not integer type, print out name
var resource = entry.Resources[j];
builder.AppendLine($" Resource Entry {j}");
if (resource == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(resource.Offset, " Offset");
builder.AppendLine(resource.Length, " Length");
builder.AppendLine($" Flag word: {resource.FlagWord} (0x{resource.FlagWord:X})");
builder.AppendLine(resource.ResourceID, " Resource ID");
builder.AppendLine(resource.Reserved, " Reserved");
}
}
}
}
if (table.TypeAndNameStrings == null || table.TypeAndNameStrings.Count == 0)
{
builder.AppendLine(" No resource table type/name strings");
}
else
{
foreach (var typeAndNameString in table.TypeAndNameStrings)
{
builder.AppendLine($" Resource Type/Name Offset {typeAndNameString.Key}");
if (typeAndNameString.Value == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(typeAndNameString.Value.Length, " Length");
builder.AppendLine(typeAndNameString.Value.Text, " Text", Encoding.ASCII);
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ResidentNameTableEntry?[]? entries)
{
builder.AppendLine(" Resident-Name Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No resident-name table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Resident-Name Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Length, " Length");
builder.AppendLine(entry.NameString, " Name string", Encoding.ASCII);
builder.AppendLine(entry.OrdinalNumber, " Ordinal number");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, ModuleReferenceTableEntry?[]? entries, Models.MSDOS.ExecutableHeader? stub, ExecutableHeader? header)
{
builder.AppendLine(" Module-Reference Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No module-reference table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
// TODO: Read the imported names table and print value here
var entry = entries[i];
builder.AppendLine($" Module-Reference Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine($" Offset: {entry.Offset} (adjusted to be {entry.Offset + (stub?.NewExeHeaderAddr ?? 0) + (header?.ImportedNamesTableOffset ?? 0)})");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Dictionary<ushort, ImportedNameTableEntry>? entries)
{
builder.AppendLine(" Imported-Name Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Count == 0)
{
builder.AppendLine(" No imported-name table items");
builder.AppendLine();
return;
}
foreach (var entry in entries)
{
builder.AppendLine($" Imported-Name Table at Offset {entry.Key}");
if (entry.Value == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Value.Length, " Length");
builder.AppendLine(entry.Value.NameString, " Name string", Encoding.ASCII);
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, EntryTableBundle?[]? entries)
{
builder.AppendLine(" Entry Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No entry table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Entry Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.EntryCount, " Entry count");
builder.AppendLine(entry.SegmentIndicator, " Segment indicator");
switch (entry.GetEntryType())
{
case SegmentEntryType.FixedSegment:
builder.AppendLine($" Flag word: {entry.FixedFlagWord} (0x{entry.FixedFlagWord:X})");
builder.AppendLine(entry.FixedOffset, " Offset");
break;
case SegmentEntryType.MoveableSegment:
builder.AppendLine($" Flag word: {entry.MoveableFlagWord} (0x{entry.MoveableFlagWord:X})");
builder.AppendLine(entry.MoveableReserved, " Reserved");
builder.AppendLine(entry.MoveableSegmentNumber, " Segment number");
builder.AppendLine(entry.MoveableOffset, " Offset");
break;
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, NonResidentNameTableEntry?[]? entries)
{
builder.AppendLine(" Nonresident-Name Table Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No nonresident-name table items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Nonresident-Name Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Length, " Length");
builder.AppendLine(entry.NameString, " Name string", Encoding.ASCII);
builder.AppendLine(entry.OrdinalNumber, " Ordinal number");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,259 @@
using System.Text;
using SabreTools.Models.Nitro;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class Nitro : IPrinter<Cart>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Cart model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Cart cart)
{
builder.AppendLine("NDS Cart Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, cart.CommonHeader);
Print(builder, cart.ExtendedDSiHeader);
Print(builder, cart.SecureArea);
Print(builder, cart.NameTable);
Print(builder, cart.FileAllocationTable);
}
private static void Print(StringBuilder builder, CommonHeader? header)
{
builder.AppendLine(" Common Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No common header");
builder.AppendLine();
return;
}
builder.AppendLine(header.GameTitle, " Game title");
builder.AppendLine(header.GameCode, " Game code");
builder.AppendLine(header.MakerCode, " Maker code");
builder.AppendLine($" Unit code: {header.UnitCode} (0x{header.UnitCode:X})");
builder.AppendLine(header.EncryptionSeedSelect, " Encryption seed select");
builder.AppendLine(header.DeviceCapacity, " Device capacity");
builder.AppendLine(header.Reserved1, " Reserved 1");
builder.AppendLine(header.GameRevision, " Game revision");
builder.AppendLine(header.RomVersion, " Rom version");
builder.AppendLine(header.ARM9RomOffset, " ARM9 rom offset");
builder.AppendLine(header.ARM9EntryAddress, " ARM9 entry address");
builder.AppendLine(header.ARM9LoadAddress, " ARM9 load address");
builder.AppendLine(header.ARM9Size, " ARM9 size");
builder.AppendLine(header.ARM7RomOffset, " ARM7 rom offset");
builder.AppendLine(header.ARM7EntryAddress, " ARM7 entry address");
builder.AppendLine(header.ARM7LoadAddress, " ARM7 load address");
builder.AppendLine(header.ARM7Size, " ARM7 size");
builder.AppendLine(header.FileNameTableOffset, " File name table offset");
builder.AppendLine(header.FileNameTableLength, " File name table length");
builder.AppendLine(header.FileAllocationTableOffset, " File allocation table offset");
builder.AppendLine(header.FileAllocationTableLength, " File allocation table length");
builder.AppendLine(header.ARM9OverlayOffset, " ARM9 overlay offset");
builder.AppendLine(header.ARM9OverlayLength, " ARM9 overlay length");
builder.AppendLine(header.ARM7OverlayOffset, " ARM7 overlay offset");
builder.AppendLine(header.ARM7OverlayLength, " ARM7 overlay length");
builder.AppendLine(header.NormalCardControlRegisterSettings, " Normal card control register settings");
builder.AppendLine(header.SecureCardControlRegisterSettings, " Secure card control register settings");
builder.AppendLine(header.IconBannerOffset, " Icon banner offset");
builder.AppendLine(header.SecureAreaCRC, " Secure area CRC");
builder.AppendLine(header.SecureTransferTimeout, " Secure transfer timeout");
builder.AppendLine(header.ARM9Autoload, " ARM9 autoload");
builder.AppendLine(header.ARM7Autoload, " ARM7 autoload");
builder.AppendLine(header.SecureDisable, " Secure disable");
builder.AppendLine(header.NTRRegionRomSize, " NTR region rom size");
builder.AppendLine(header.HeaderSize, " Header size");
builder.AppendLine(header.Reserved2, " Reserved 2");
builder.AppendLine(header.NintendoLogo, " Nintendo logo");
builder.AppendLine(header.NintendoLogoCRC, " Nintendo logo CRC");
builder.AppendLine(header.HeaderCRC, " Header CRC");
builder.AppendLine(header.DebuggerReserved, " Debugger reserved");
builder.AppendLine();
}
private static void Print(StringBuilder builder, ExtendedDSiHeader? header)
{
builder.AppendLine(" Extended DSi Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No extended DSi header");
builder.AppendLine();
return;
}
builder.AppendLine(header.GlobalMBK15Settings, " Global MBK1..MBK5 settings");
builder.AppendLine(header.LocalMBK68SettingsARM9, " Local MBK6..MBK8 settings for ARM9");
builder.AppendLine(header.LocalMBK68SettingsARM7, " Local MBK6..MBK8 settings for ARM7");
builder.AppendLine(header.GlobalMBK9Setting, " Global MBK9 setting");
builder.AppendLine(header.RegionFlags, " Region flags");
builder.AppendLine(header.AccessControl, " Access control");
builder.AppendLine(header.ARM7SCFGEXTMask, " ARM7 SCFG EXT mask");
builder.AppendLine(header.ReservedFlags, " Reserved/flags?");
builder.AppendLine(header.ARM9iRomOffset, " ARM9i rom offset");
builder.AppendLine(header.Reserved3, " Reserved 3");
builder.AppendLine(header.ARM9iLoadAddress, " ARM9i load address");
builder.AppendLine(header.ARM9iSize, " ARM9i size");
builder.AppendLine(header.ARM7iRomOffset, " ARM7i rom offset");
builder.AppendLine(header.Reserved4, " Reserved 4");
builder.AppendLine(header.ARM7iLoadAddress, " ARM7i load address");
builder.AppendLine(header.ARM7iSize, " ARM7i size");
builder.AppendLine(header.DigestNTRRegionOffset, " Digest NTR region offset");
builder.AppendLine(header.DigestNTRRegionLength, " Digest NTR region length");
builder.AppendLine(header.DigestTWLRegionOffset, " Digest TWL region offset");
builder.AppendLine(header.DigestTWLRegionLength, " Digest TWL region length");
builder.AppendLine(header.DigestSectorHashtableRegionOffset, " Digest sector hashtable region offset");
builder.AppendLine(header.DigestSectorHashtableRegionLength, " Digest sector hashtable region length");
builder.AppendLine(header.DigestBlockHashtableRegionOffset, " Digest block hashtable region offset");
builder.AppendLine(header.DigestBlockHashtableRegionLength, " Digest block hashtable region length");
builder.AppendLine(header.DigestSectorSize, " Digest sector size");
builder.AppendLine(header.DigestBlockSectorCount, " Digest block sector count");
builder.AppendLine(header.IconBannerSize, " Icon banner size");
builder.AppendLine(header.Unknown1, " Unknown 1");
builder.AppendLine(header.ModcryptArea1Offset, " Modcrypt area 1 offset");
builder.AppendLine(header.ModcryptArea1Size, " Modcrypt area 1 size");
builder.AppendLine(header.ModcryptArea2Offset, " Modcrypt area 2 offset");
builder.AppendLine(header.ModcryptArea2Size, " Modcrypt area 2 size");
builder.AppendLine(header.TitleID, " Title ID");
builder.AppendLine(header.DSiWarePublicSavSize, " DSiWare 'public.sav' size");
builder.AppendLine(header.DSiWarePrivateSavSize, " DSiWare 'private.sav' size");
builder.AppendLine(header.ReservedZero, " Reserved (zero)");
builder.AppendLine(header.Unknown2, " Unknown 2");
builder.AppendLine(header.ARM9WithSecureAreaSHA1HMACHash, " ARM9 (with encrypted secure area) SHA1 HMAC hash");
builder.AppendLine(header.ARM7SHA1HMACHash, " ARM7 SHA1 HMAC hash");
builder.AppendLine(header.DigestMasterSHA1HMACHash, " Digest master SHA1 HMAC hash");
builder.AppendLine(header.BannerSHA1HMACHash, " Banner SHA1 HMAC hash");
builder.AppendLine(header.ARM9iDecryptedSHA1HMACHash, " ARM9i (decrypted) SHA1 HMAC hash");
builder.AppendLine(header.ARM7iDecryptedSHA1HMACHash, " ARM7i (decrypted) SHA1 HMAC hash");
builder.AppendLine(header.Reserved5, " Reserved 5");
builder.AppendLine(header.ARM9NoSecureAreaSHA1HMACHash, " ARM9 (without secure area) SHA1 HMAC hash");
builder.AppendLine(header.Reserved6, " Reserved 6");
builder.AppendLine(header.ReservedAndUnchecked, " Reserved and unchecked region");
builder.AppendLine(header.RSASignature, " RSA signature");
builder.AppendLine();
}
private static void Print(StringBuilder builder, byte[]? secureArea)
{
builder.AppendLine(" Secure Area Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(secureArea, " Secure Area");
builder.AppendLine();
}
private static void Print(StringBuilder builder, NameTable? table)
{
builder.AppendLine(" Name Table Information:");
builder.AppendLine(" -------------------------");
if (table == null)
{
builder.AppendLine(" No name table");
builder.AppendLine();
return;
}
builder.AppendLine();
Print(builder, table.FolderAllocationTable);
Print(builder, table.NameList);
}
private static void Print(StringBuilder builder, FolderAllocationTableEntry?[]? entries)
{
builder.AppendLine(" Folder Allocation Table:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No folder allocation table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Folder Allocation Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.StartOffset, " Start offset");
builder.AppendLine(entry.FirstFileIndex, " First file index");
if (entry.Unknown == 0xF0)
{
builder.AppendLine(entry.ParentFolderIndex, " Parent folder index");
builder.AppendLine(entry.Unknown, " Unknown");
}
else
{
ushort totalEntries = (ushort)((entry.Unknown << 8) | entry.ParentFolderIndex);
builder.AppendLine(totalEntries, " Total entries");
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, NameListEntry?[]? entries)
{
builder.AppendLine(" Name List:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No name list entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Name List Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.Folder, " Folder");
builder.AppendLine(entry.Name, " Name");
if (entry.Folder)
builder.AppendLine(entry.Index, " Index");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, FileAllocationTableEntry?[]? entries)
{
builder.AppendLine(" File Allocation Table:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No file allocation table entries");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" File Allocation Table Entry {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.StartOffset, " Start offset");
builder.AppendLine(entry.EndOffset, " End offset");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,68 @@
using System.Text;
using SabreTools.Models.PAK;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class PAK : IPrinter<File>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, File model)
=> Print(builder, model);
public static void Print(StringBuilder builder, File file)
{
builder.AppendLine("PAK Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, file.Header);
Print(builder, file.DirectoryItems);
}
private static void Print(StringBuilder builder, Header? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.DirectoryOffset, " Directory offset");
builder.AppendLine(header.DirectoryLength, " Directory length");
builder.AppendLine();
}
private static void Print(StringBuilder builder, DirectoryItem?[]? entries)
{
builder.AppendLine(" Directory Items Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No directory items");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Directory Item {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.ItemName, " Item name");
builder.AppendLine(entry.ItemOffset, " Item offset");
builder.AppendLine(entry.ItemLength, " Item length");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,92 @@
using System.Text;
using SabreTools.Models.PFF;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class PFF : IPrinter<Archive>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Archive model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Archive archive)
{
builder.AppendLine("PFF Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, archive.Header);
Print(builder, archive.Segments);
Print(builder, archive.Footer);
}
private static void Print(StringBuilder builder, Header? header)
{
builder.AppendLine(" Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No header");
builder.AppendLine();
return;
}
builder.AppendLine(header.HeaderSize, " Header size");
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.NumberOfFiles, " Number of files");
builder.AppendLine(header.FileSegmentSize, " File segment size");
builder.AppendLine(header.FileListOffset, " File list offset");
builder.AppendLine();
}
private static void Print(StringBuilder builder, Segment?[]? segments)
{
builder.AppendLine(" Segments Information:");
builder.AppendLine(" -------------------------");
if (segments == null || segments.Length == 0)
{
builder.AppendLine(" No segments");
builder.AppendLine();
return;
}
for (int i = 0; i < segments.Length; i++)
{
var segment = segments[i];
builder.AppendLine($" Segment {i}");
if (segment == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(segment.Deleted, " Deleted");
builder.AppendLine(segment.FileLocation, " File location");
builder.AppendLine(segment.FileSize, " File size");
builder.AppendLine(segment.PackedDate, " Packed date");
builder.AppendLine(segment.FileName, " File name");
builder.AppendLine(segment.ModifiedDate, " Modified date");
builder.AppendLine(segment.CompressionLevel, " Compression level");
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, Footer? footer)
{
builder.AppendLine(" Footer Information:");
builder.AppendLine(" -------------------------");
if (footer == null)
{
builder.AppendLine(" No footer");
builder.AppendLine();
return;
}
builder.AppendLine(footer.SystemIP, " System IP");
builder.AppendLine(footer.Reserved, " Reserved");
builder.AppendLine(footer.KingTag, " King tag");
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,87 @@
using System.Text;
using SabreTools.Models.PIC;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class PIC : IPrinter<DiscInformation>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, DiscInformation model)
=> Print(builder, model);
public static void Print(StringBuilder builder, DiscInformation di)
{
builder.AppendLine("PIC Information:");
builder.AppendLine("-------------------------");
builder.AppendLine(di.DataStructureLength, "Data structure length");
builder.AppendLine(di.Reserved0, "Reserved");
builder.AppendLine(di.Reserved1, "Reserved");
builder.AppendLine();
Print(builder, di.Units);
}
private static void Print(StringBuilder builder, DiscInformationUnit?[]? entries)
{
builder.AppendLine(" Disc Information Units:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No disc information units");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Disc Information Unit {i}");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
if (entry.Header == null)
{
builder.AppendLine(" No header");
}
else
{
var header = entry.Header;
builder.AppendLine(header.DiscInformationIdentifier, " Disc information identifier");
builder.AppendLine(header.DiscInformationFormat, " Disc information format");
builder.AppendLine(header.Reserved0, " Reserved");
builder.AppendLine(header.SequenceNumber, " Sequence number");
builder.AppendLine(header.BytesInUse, " Bytes in use");
builder.AppendLine(header.Reserved1, " Reserved");
}
if (entry.Body == null)
{
builder.AppendLine(" No body");
}
else
{
DiscInformationUnitBody body = entry.Body;
builder.AppendLine(body.DiscTypeIdentifier, " Disc type identifer");
builder.AppendLine(body.DiscSizeClassVersion, " Disc size class version");
builder.AppendLine(body.FormatDependentContents, " Format-dependent contents");
}
if (entry.Trailer == null)
{
builder.AppendLine(" No trailer");
}
else
{
DiscInformationUnitTrailer trailer = entry.Trailer;
builder.AppendLine(trailer.DiscManufacturerID, " Disc manufacturer ID");
builder.AppendLine(trailer.MediaTypeID, " Media type ID");
builder.AppendLine(trailer.TimeStamp, " Timestamp");
builder.AppendLine(trailer.ProductRevisionNumber, " Product revision number");
}
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,279 @@
using System.Text;
using SabreTools.Models.PKZIP;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class PKZIP : IPrinter<Archive>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Archive model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Archive archive)
{
builder.AppendLine("PKZIP Archive (or Derived Format) Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, archive.EndOfCentralDirectoryRecord);
Print(builder, archive.ZIP64EndOfCentralDirectoryLocator);
Print(builder, archive.ZIP64EndOfCentralDirectoryRecord);
Print(builder, archive.CentralDirectoryHeaders);
Print(builder, archive.ArchiveExtraDataRecord);
Print(builder,
archive.LocalFileHeaders,
archive.EncryptionHeaders,
archive.FileData,
archive.DataDescriptors,
archive.ZIP64DataDescriptors);
}
private static void Print(StringBuilder builder, EndOfCentralDirectoryRecord? record)
{
builder.AppendLine(" End of Central Directory Record Information:");
builder.AppendLine(" -------------------------");
if (record == null)
{
builder.AppendLine(" No end of central directory record");
builder.AppendLine();
return;
}
builder.AppendLine(record.Signature, " Signature");
builder.AppendLine(record.DiskNumber, " Disk number");
builder.AppendLine(record.StartDiskNumber, " Start disk number");
builder.AppendLine(record.TotalEntriesOnDisk, " Total entries on disk");
builder.AppendLine(record.TotalEntries, " Total entries");
builder.AppendLine(record.CentralDirectorySize, " Central directory size");
builder.AppendLine(record.CentralDirectoryOffset, " Central directory offset");
builder.AppendLine(record.FileCommentLength, " File comment length");
builder.AppendLine(record.FileComment, " File comment");
builder.AppendLine();
}
private static void Print(StringBuilder builder, EndOfCentralDirectoryLocator64? locator)
{
builder.AppendLine(" ZIP64 End of Central Directory Locator Information:");
builder.AppendLine(" -------------------------");
if (locator == null)
{
builder.AppendLine(" No ZIP64 end of central directory locator");
builder.AppendLine();
return;
}
builder.AppendLine(locator.Signature, " Signature");
builder.AppendLine(locator.StartDiskNumber, " Start disk number");
builder.AppendLine(locator.CentralDirectoryOffset, " Central directory offset");
builder.AppendLine(locator.TotalDisks, " Total disks");
builder.AppendLine();
}
private static void Print(StringBuilder builder, EndOfCentralDirectoryRecord64? record)
{
builder.AppendLine(" ZIP64 End of Central Directory Record Information:");
builder.AppendLine(" -------------------------");
if (record == null)
{
builder.AppendLine(" No ZIP64 end of central directory record");
builder.AppendLine();
return;
}
builder.AppendLine(record.Signature, " Signature");
builder.AppendLine(record.DirectoryRecordSize, " Directory record size");
builder.AppendLine($" Host system: {record.HostSystem} (0x{record.HostSystem:X})");
builder.AppendLine(record.VersionMadeBy, " Version made by");
builder.AppendLine(record.VersionNeededToExtract, " Version needed to extract");
builder.AppendLine(record.DiskNumber, " Disk number");
builder.AppendLine(record.StartDiskNumber, " Start disk number");
builder.AppendLine(record.TotalEntriesOnDisk, " Total entries on disk");
builder.AppendLine(record.TotalEntries, " Total entries");
builder.AppendLine(record.CentralDirectorySize, " Central directory size");
builder.AppendLine(record.CentralDirectoryOffset, " Central directory offset");
//builder.AppendLine(record.ExtensibleDataSector, " Extensible data sector");
builder.AppendLine();
}
private static void Print(StringBuilder builder, CentralDirectoryFileHeader?[]? headers)
{
builder.AppendLine(" Central Directory File Headers Information:");
builder.AppendLine(" -------------------------");
if (headers == null || headers.Length == 0)
{
builder.AppendLine(" No central directory file headers");
builder.AppendLine();
return;
}
for (int i = 0; i < headers.Length; i++)
{
var record = headers[i];
Print(builder, record, i);
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, CentralDirectoryFileHeader? header, int index)
{
builder.AppendLine($" Central Directory File Header Entry {index}");
if (header == null)
{
builder.AppendLine(" [NULL]");
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine($" Host system: {header.HostSystem} (0x{header.HostSystem:X})");
builder.AppendLine(header.VersionMadeBy, " Version made by");
builder.AppendLine(header.VersionNeededToExtract, " Version needed to extract");
builder.AppendLine($" Flags: {header.Flags} (0x{header.Flags:X})");
builder.AppendLine($" Compression method: {header.CompressionMethod} (0x{header.CompressionMethod:X})");
builder.AppendLine(header.LastModifedFileTime, " Last modified file time"); // TODO: Parse from MS-DOS
builder.AppendLine(header.LastModifiedFileDate, " Last modified file date"); // TODO: Parse from MS-DOS
builder.AppendLine(header.CRC32, " CRC-32");
builder.AppendLine(header.CompressedSize, " Compressed size");
builder.AppendLine(header.UncompressedSize, " Uncompressed size");
builder.AppendLine(header.FileNameLength, " File name length");
builder.AppendLine(header.ExtraFieldLength, " Extra field length");
builder.AppendLine(header.FileCommentLength, " File comment length");
builder.AppendLine(header.DiskNumberStart, " Disk number start");
builder.AppendLine($" Internal file attributes: {header.InternalFileAttributes} (0x{header.InternalFileAttributes:X})");
builder.AppendLine(header.ExternalFileAttributes, " External file attributes");
builder.AppendLine(header.RelativeOffsetOfLocalHeader, " Relative offset of local header");
builder.AppendLine(header.FileName, " File name");
builder.AppendLine(header.ExtraField, " Extra field");
builder.AppendLine(header.FileComment, " File comment");
}
private static void Print(StringBuilder builder, ArchiveExtraDataRecord? record)
{
builder.AppendLine(" Archive Extra Data Record Information:");
builder.AppendLine(" -------------------------");
if (record == null)
{
builder.AppendLine(" No archive extra data record");
builder.AppendLine();
return;
}
builder.AppendLine(record.Signature, " Signature");
builder.AppendLine(record.ExtraFieldLength, " Extra field length");
builder.AppendLine(record.ExtraFieldData, " Extra field data");
builder.AppendLine();
}
private static void Print(StringBuilder builder,
LocalFileHeader[]? localFileHeaders,
byte[]?[]? encryptionHeaders,
byte[][]? fileData,
DataDescriptor?[]? dataDescriptors,
DataDescriptor64?[]? zip64DataDescriptors)
{
builder.AppendLine(" Local File Information:");
builder.AppendLine(" -------------------------");
if (localFileHeaders == null || localFileHeaders.Length == 0)
{
builder.AppendLine(" No local files");
builder.AppendLine();
return;
}
if (encryptionHeaders == null || localFileHeaders.Length > encryptionHeaders.Length
|| fileData == null || localFileHeaders.Length > fileData.Length
|| dataDescriptors == null || localFileHeaders.Length > dataDescriptors.Length
|| zip64DataDescriptors == null || localFileHeaders.Length > zip64DataDescriptors.Length)
{
builder.AppendLine(" Mismatch in local file array values");
builder.AppendLine();
}
for (int i = 0; i < localFileHeaders.Length; i++)
{
var localFileHeader = localFileHeaders[i];
var encryptionHeader = encryptionHeaders != null && i < encryptionHeaders.Length ? encryptionHeaders[i] : null;
var fileDatum = fileData != null && i < fileData.Length ? fileData[i] : null;
var dataDescriptor = dataDescriptors != null && i < dataDescriptors.Length ? dataDescriptors[i] : null;
var zip64DataDescriptor = zip64DataDescriptors != null && i < zip64DataDescriptors.Length ? zip64DataDescriptors[i] : null;
Print(builder, localFileHeader, encryptionHeader, fileDatum, dataDescriptor, zip64DataDescriptor, i);
}
builder.AppendLine();
}
private static void Print(StringBuilder builder,
LocalFileHeader localFileHeader,
byte[]? encryptionHeader,
byte[]? fileData,
DataDescriptor? dataDescriptor,
DataDescriptor64? zip64DataDescriptor,
int index)
{
builder.AppendLine($" Local File Entry {index}");
if (localFileHeader == null)
{
builder.AppendLine(" [NULL]");
return;
}
builder.AppendLine(localFileHeader.Signature, " [Local File Header] Signature");
builder.AppendLine(localFileHeader.Version, " [Local File Header] Version");
builder.AppendLine($" [Local File Header] Flags: {localFileHeader.Flags} (0x{localFileHeader.Flags:X})");
builder.AppendLine($" [Local File Header] Compression method: {localFileHeader.CompressionMethod} (0x{localFileHeader.CompressionMethod:X})");
builder.AppendLine(localFileHeader.LastModifedFileTime, " [Local File Header] Last modified file time"); // TODO: Parse from MS-DOS
builder.AppendLine(localFileHeader.LastModifiedFileDate, " [Local File Header] Last modified file date"); // TODO: Parse from MS-DOS
builder.AppendLine(localFileHeader.CRC32, " [Local File Header] CRC-32");
builder.AppendLine(localFileHeader.CompressedSize, " [Local File Header] Compressed size");
builder.AppendLine(localFileHeader.UncompressedSize, " [Local File Header] Uncompressed size");
builder.AppendLine(localFileHeader.FileNameLength, " [Local File Header] File name length");
builder.AppendLine(localFileHeader.ExtraFieldLength, " [Local File Header] Extra field length");
builder.AppendLine(localFileHeader.FileName, " [Local File Header] File name");
builder.AppendLine(localFileHeader.ExtraField, " [Local File Header] Extra field");
if (encryptionHeader == null)
{
builder.AppendLine(" [Encryption Header]: [NULL]");
}
else
{
builder.AppendLine(encryptionHeader.Length, " [Encryption Header] Length");
builder.AppendLine(encryptionHeader, " [Encryption Header] Data");
}
if (fileData == null)
{
builder.AppendLine(" [File Data]: [NULL]");
}
else
{
builder.AppendLine(fileData.Length, " [File Data] Length");
//builder.AppendLine(fileData, " [File Data] Data");
}
if (dataDescriptor == null)
{
builder.AppendLine(" [Data Descriptor]: [NULL]");
}
else
{
builder.AppendLine(dataDescriptor.Signature, " [Data Descriptor] Signature");
builder.AppendLine(dataDescriptor.CRC32, " [Data Descriptor] CRC-32");
builder.AppendLine(dataDescriptor.CompressedSize, " [Data Descriptor] Compressed size");
builder.AppendLine(dataDescriptor.UncompressedSize, " [Data Descriptor] Uncompressed size");
}
if (zip64DataDescriptor == null)
{
builder.AppendLine(" [ZIP64 Data Descriptor]: [NULL]");
}
else
{
builder.AppendLine(zip64DataDescriptor.Signature, " [ZIP64 Data Descriptor] Signature");
builder.AppendLine(zip64DataDescriptor.CRC32, " [ZIP64 Data Descriptor] CRC-32");
builder.AppendLine(zip64DataDescriptor.CompressedSize, " [ZIP64 Data Descriptor] Compressed size");
builder.AppendLine(zip64DataDescriptor.UncompressedSize, " [ZIP64 Data Descriptor] Uncompressed size");
}
}
}
}

View File

@@ -0,0 +1,183 @@
using System.Text;
using SabreTools.Models.PlayJ;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class PlayJAudioFile : IPrinter<AudioFile>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, AudioFile model)
=> Print(builder, model);
public static void Print(StringBuilder builder, AudioFile audio)
{
builder.AppendLine("PlayJ Audio File Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, audio.Header);
Print(builder, audio.UnknownBlock1);
if (audio.Header?.Version == 0x00000000)
{
Print(builder, audio.UnknownValue2);
Print(builder, audio.UnknownBlock3);
}
else if (audio.Header?.Version == 0x0000000A)
{
Print(builder, audio.DataFilesCount, audio.DataFiles);
}
}
private static void Print(StringBuilder builder, AudioHeader? header)
{
builder.AppendLine(" Audio Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No audio header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.Version, " Version");
if (header.Version == 0x00000000 && header is AudioHeaderV1 headerV1)
{
builder.AppendLine(headerV1.TrackID, " Track ID");
builder.AppendLine(headerV1.UnknownOffset1, " Unknown offset 1");
builder.AppendLine(headerV1.UnknownOffset2, " Unknown offset 2");
builder.AppendLine(headerV1.UnknownOffset3, " Unknown offset 3");
builder.AppendLine(headerV1.Unknown1, " Unknown 1");
builder.AppendLine(headerV1.Unknown2, " Unknown 2");
builder.AppendLine(headerV1.Year, " Year");
builder.AppendLine(headerV1.TrackNumber, " Track number");
builder.AppendLine($" Subgenre: {headerV1.Subgenre} (0x{headerV1.Subgenre:X})");
builder.AppendLine(headerV1.Duration, " Duration in seconds");
}
else if (header.Version == 0x0000000A && header is AudioHeaderV2 headerV2)
{
builder.AppendLine(headerV2.Unknown1, " Unknown 1");
builder.AppendLine(headerV2.Unknown2, " Unknown 2");
builder.AppendLine(headerV2.Unknown3, " Unknown 3");
builder.AppendLine(headerV2.Unknown4, " Unknown 4");
builder.AppendLine(headerV2.Unknown5, " Unknown 5");
builder.AppendLine(headerV2.Unknown6, " Unknown 6");
builder.AppendLine(headerV2.UnknownOffset1, " Unknown Offset 1");
builder.AppendLine(headerV2.Unknown7, " Unknown 7");
builder.AppendLine(headerV2.Unknown8, " Unknown 8");
builder.AppendLine(headerV2.Unknown9, " Unknown 9");
builder.AppendLine(headerV2.UnknownOffset2, " Unknown Offset 2");
builder.AppendLine(headerV2.Unknown10, " Unknown 10");
builder.AppendLine(headerV2.Unknown11, " Unknown 11");
builder.AppendLine(headerV2.Unknown12, " Unknown 12");
builder.AppendLine(headerV2.Unknown13, " Unknown 13");
builder.AppendLine(headerV2.Unknown14, " Unknown 14");
builder.AppendLine(headerV2.Unknown15, " Unknown 15");
builder.AppendLine(headerV2.Unknown16, " Unknown 16");
builder.AppendLine(headerV2.Unknown17, " Unknown 17");
builder.AppendLine(headerV2.TrackID, " Track ID");
builder.AppendLine(headerV2.Year, " Year");
builder.AppendLine(headerV2.TrackNumber, " Track number");
builder.AppendLine(headerV2.Unknown18, " Unknown 18");
}
else
{
builder.AppendLine(" Unrecognized version, not parsed...");
}
builder.AppendLine(header.TrackLength, " Track length");
builder.AppendLine(header.Track, " Track");
builder.AppendLine(header.ArtistLength, " Artist length");
builder.AppendLine(header.Artist, " Artist");
builder.AppendLine(header.AlbumLength, " Album length");
builder.AppendLine(header.Album, " Album");
builder.AppendLine(header.WriterLength, " Writer length");
builder.AppendLine(header.Writer, " Writer");
builder.AppendLine(header.PublisherLength, " Publisher length");
builder.AppendLine(header.Publisher, " Publisher");
builder.AppendLine(header.LabelLength, " Label length");
builder.AppendLine(header.Label, " Label");
builder.AppendLine(header.CommentsLength, " Comments length");
builder.AppendLine(header.Comments, " Comments");
builder.AppendLine();
}
private static void Print(StringBuilder builder, UnknownBlock1? block)
{
builder.AppendLine(" Unknown Block 1 Information:");
builder.AppendLine(" -------------------------");
if (block == null)
{
builder.AppendLine(" No unknown block 1r");
builder.AppendLine();
return;
}
builder.AppendLine(block.Length, " Length");
builder.AppendLine(block.Data, " Data");
builder.AppendLine();
}
private static void Print(StringBuilder builder, uint? value)
{
builder.AppendLine(" Unknown Value 2 Information:");
builder.AppendLine(" -------------------------");
if (value == null)
{
builder.AppendLine(" No unknown block 1r");
builder.AppendLine();
return;
}
builder.AppendLine(value, " Value");
builder.AppendLine();
}
private static void Print(StringBuilder builder, UnknownBlock3? block)
{
builder.AppendLine(" Unknown Block 3 Information:");
builder.AppendLine(" -------------------------");
if (block == null)
{
builder.AppendLine(" No unknown block 1r");
builder.AppendLine();
return;
}
builder.AppendLine(block.Data, " Data");
builder.AppendLine();
}
private static void Print(StringBuilder builder, uint count, DataFile?[]? entries)
{
builder.AppendLine(" Data Files Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(count, " Data files count");
if (count == 0 || entries == null || entries.Length == 0)
{
builder.AppendLine(" No data files");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Data File {i}:");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.FileNameLength, " File name length");
builder.AppendLine(entry.FileName, " File name");
builder.AppendLine(entry.DataLength, " Data length");
builder.AppendLine(entry.Data, " Data");
}
builder.AppendLine();
}
}
}

View File

@@ -0,0 +1,226 @@
using System.Text;
using SabreTools.Models.PlayJ;
using SabreTools.Serialization.Interfaces;
namespace SabreTools.Serialization.Printers
{
public class PlayJPlaylist : IPrinter<Playlist>
{
/// <inheritdoc/>
public void PrintInformation(StringBuilder builder, Playlist model)
=> Print(builder, model);
public static void Print(StringBuilder builder, Playlist playlist)
{
builder.AppendLine("PlayJ Playlist Information:");
builder.AppendLine("-------------------------");
builder.AppendLine();
Print(builder, playlist.Header);
Print(builder, playlist.AudioFiles);
}
private static void Print(StringBuilder builder, PlaylistHeader? header)
{
builder.AppendLine(" Playlist Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No playlist header");
builder.AppendLine();
return;
}
builder.AppendLine(header.TrackCount, " Track count");
builder.AppendLine(header.Data, " Data");
builder.AppendLine();
}
private static void Print(StringBuilder builder, AudioFile?[]? entries)
{
builder.AppendLine(" Audio Files Information:");
builder.AppendLine(" -------------------------");
if (entries == null || entries.Length == 0)
{
builder.AppendLine(" No audio files");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Audio File {i}:");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
Print(builder, entry.Header);
Print(builder, entry.UnknownBlock1);
if (entry.Header?.Version == 0x00000000)
{
Print(builder, entry.UnknownValue2);
Print(builder, entry.UnknownBlock3);
}
else if (entry.Header?.Version == 0x0000000A)
{
Print(builder, entry.DataFilesCount, entry.DataFiles);
}
}
builder.AppendLine();
}
private static void Print(StringBuilder builder, AudioHeader? header)
{
builder.AppendLine(" Audio Header Information:");
builder.AppendLine(" -------------------------");
if (header == null)
{
builder.AppendLine(" No audio header");
builder.AppendLine();
return;
}
builder.AppendLine(header.Signature, " Signature");
builder.AppendLine(header.Version, " Version");
if (header.Version == 0x00000000 && header is AudioHeaderV1 headerV1)
{
builder.AppendLine(headerV1.TrackID, " Track ID");
builder.AppendLine(headerV1.UnknownOffset1, " Unknown offset 1");
builder.AppendLine(headerV1.UnknownOffset2, " Unknown offset 2");
builder.AppendLine(headerV1.UnknownOffset3, " Unknown offset 3");
builder.AppendLine(headerV1.Unknown1, " Unknown 1");
builder.AppendLine(headerV1.Unknown2, " Unknown 2");
builder.AppendLine(headerV1.Year, " Year");
builder.AppendLine(headerV1.TrackNumber, " Track number");
builder.AppendLine($" Subgenre: {headerV1.Subgenre} (0x{headerV1.Subgenre:X})");
builder.AppendLine(headerV1.Duration, " Duration in seconds");
}
else if (header.Version == 0x0000000A && header is AudioHeaderV2 headerV2)
{
builder.AppendLine(headerV2.Unknown1, " Unknown 1");
builder.AppendLine(headerV2.Unknown2, " Unknown 2");
builder.AppendLine(headerV2.Unknown3, " Unknown 3");
builder.AppendLine(headerV2.Unknown4, " Unknown 4");
builder.AppendLine(headerV2.Unknown5, " Unknown 5");
builder.AppendLine(headerV2.Unknown6, " Unknown 6");
builder.AppendLine(headerV2.UnknownOffset1, " Unknown Offset 1");
builder.AppendLine(headerV2.Unknown7, " Unknown 7");
builder.AppendLine(headerV2.Unknown8, " Unknown 8");
builder.AppendLine(headerV2.Unknown9, " Unknown 9");
builder.AppendLine(headerV2.UnknownOffset2, " Unknown Offset 2");
builder.AppendLine(headerV2.Unknown10, " Unknown 10");
builder.AppendLine(headerV2.Unknown11, " Unknown 11");
builder.AppendLine(headerV2.Unknown12, " Unknown 12");
builder.AppendLine(headerV2.Unknown13, " Unknown 13");
builder.AppendLine(headerV2.Unknown14, " Unknown 14");
builder.AppendLine(headerV2.Unknown15, " Unknown 15");
builder.AppendLine(headerV2.Unknown16, " Unknown 16");
builder.AppendLine(headerV2.Unknown17, " Unknown 17");
builder.AppendLine(headerV2.TrackID, " Track ID");
builder.AppendLine(headerV2.Year, " Year");
builder.AppendLine(headerV2.TrackNumber, " Track number");
builder.AppendLine(headerV2.Unknown18, " Unknown 18");
}
else
{
builder.AppendLine(" Unrecognized version, not parsed...");
}
builder.AppendLine(header.TrackLength, " Track length");
builder.AppendLine(header.Track, " Track");
builder.AppendLine(header.ArtistLength, " Artist length");
builder.AppendLine(header.Artist, " Artist");
builder.AppendLine(header.AlbumLength, " Album length");
builder.AppendLine(header.Album, " Album");
builder.AppendLine(header.WriterLength, " Writer length");
builder.AppendLine(header.Writer, " Writer");
builder.AppendLine(header.PublisherLength, " Publisher length");
builder.AppendLine(header.Publisher, " Publisher");
builder.AppendLine(header.LabelLength, " Label length");
builder.AppendLine(header.Label, " Label");
builder.AppendLine(header.CommentsLength, " Comments length");
builder.AppendLine(header.Comments, " Comments");
builder.AppendLine();
}
private static void Print(StringBuilder builder, UnknownBlock1? block)
{
builder.AppendLine(" Unknown Block 1 Information:");
builder.AppendLine(" -------------------------");
if (block == null)
{
builder.AppendLine(" No unknown block 1r");
builder.AppendLine();
return;
}
builder.AppendLine(block.Length, " Length");
builder.AppendLine(block.Data, " Data");
builder.AppendLine();
}
private static void Print(StringBuilder builder, uint? value)
{
builder.AppendLine(" Unknown Value 2 Information:");
builder.AppendLine(" -------------------------");
if (value == null)
{
builder.AppendLine(" No unknown block 1r");
builder.AppendLine();
return;
}
builder.AppendLine(value, " Value");
builder.AppendLine();
}
private static void Print(StringBuilder builder, UnknownBlock3? block)
{
builder.AppendLine(" Unknown Block 3 Information:");
builder.AppendLine(" -------------------------");
if (block == null)
{
builder.AppendLine(" No unknown block 1r");
builder.AppendLine();
return;
}
builder.AppendLine(block.Data, " Data");
builder.AppendLine();
}
private static void Print(StringBuilder builder, uint count, DataFile?[]? entries)
{
builder.AppendLine(" Data Files Information:");
builder.AppendLine(" -------------------------");
builder.AppendLine(count, " Data files count");
if (count == 0 || entries == null || entries.Length == 0)
{
builder.AppendLine(" No data files");
builder.AppendLine();
return;
}
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
builder.AppendLine($" Data File {i}:");
if (entry == null)
{
builder.AppendLine(" [NULL]");
continue;
}
builder.AppendLine(entry.FileNameLength, " File name length");
builder.AppendLine(entry.FileName, " File name");
builder.AppendLine(entry.DataLength, " Data length");
builder.AppendLine(entry.Data, " Data");
}
builder.AppendLine();
}
}
}

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More