mirror of
https://github.com/SabreTools/SabreTools.Serialization.git
synced 2026-02-06 13:47:36 +00:00
Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2776928946 | ||
|
|
8cc87c6540 | ||
|
|
3c212022aa | ||
|
|
511c4d09e5 | ||
|
|
d7eba27dc5 | ||
|
|
09370618ca | ||
|
|
2197167088 | ||
|
|
b527635fe7 | ||
|
|
695309bc32 | ||
|
|
97b2f68ec7 | ||
|
|
593044dbf3 | ||
|
|
1fcf44fb8d | ||
|
|
a2a472baf9 | ||
|
|
b5b4a50d94 | ||
|
|
f1b5464052 | ||
|
|
2c0224db22 | ||
|
|
1e78eecb40 | ||
|
|
3626faea60 | ||
|
|
a0177f1174 | ||
|
|
db5fe4a2cd | ||
|
|
5716143168 | ||
|
|
2a59b23149 | ||
|
|
bdbec4ed02 | ||
|
|
25193f1805 | ||
|
|
4840c816a2 | ||
|
|
d0a8e3770b | ||
|
|
1cf3d50864 | ||
|
|
d1b98f7d6d | ||
|
|
4bc87ff812 | ||
|
|
e1df11b360 | ||
|
|
34606a4f04 | ||
|
|
c4c5fc4bf6 | ||
|
|
cd87ce5373 | ||
|
|
90fc16b888 | ||
|
|
c2d0b71d22 | ||
|
|
e54473682c | ||
|
|
1c8d64d98c | ||
|
|
a19437f42f | ||
|
|
855e2f2c77 | ||
|
|
bd3cf88123 | ||
|
|
e4578ad3fc | ||
|
|
39e56ef864 | ||
|
|
51b77da760 | ||
|
|
4b83219a9b | ||
|
|
3ed07dd299 | ||
|
|
bb7daed7f6 | ||
|
|
0c84c47752 | ||
|
|
c18a185474 | ||
|
|
8ff66b04d8 | ||
|
|
94d6556e04 | ||
|
|
6d960265e4 | ||
|
|
cf4ca76e10 | ||
|
|
c7760e9903 | ||
|
|
d51bedceb6 | ||
|
|
125dc021d5 | ||
|
|
5bce481648 | ||
|
|
20153f62cf | ||
|
|
e302dfccf1 | ||
|
|
594b841490 | ||
|
|
40c354f79f | ||
|
|
b77959f300 | ||
|
|
59d6026a2b | ||
|
|
14226d1270 | ||
|
|
955f4da708 | ||
|
|
700b0359ea | ||
|
|
fe95b894d7 | ||
|
|
38a2712a8f | ||
|
|
d1ea091574 | ||
|
|
6bc812fc2f | ||
|
|
61b89fbd72 | ||
|
|
a2c065bdf2 | ||
|
|
88479f674b | ||
|
|
5edbacde74 | ||
|
|
67fc51224b | ||
|
|
101f3294b4 | ||
|
|
6c5622f732 | ||
|
|
f2a6fe1445 | ||
|
|
b0b593443f | ||
|
|
9b05185add | ||
|
|
17316da536 | ||
|
|
f3ca4dd989 | ||
|
|
e2b7bdac8c | ||
|
|
f86f6dc438 | ||
|
|
2bac0ed505 | ||
|
|
ae4078bb7f | ||
|
|
afaffbd9a2 | ||
|
|
b878e59e2e | ||
|
|
4bb3f625dd | ||
|
|
b7978cafa5 | ||
|
|
17f376c76f | ||
|
|
2774fdf158 | ||
|
|
11081efcb0 | ||
|
|
1b412c3027 | ||
|
|
73ec66e627 | ||
|
|
4ae4cd80b1 | ||
|
|
6eb27c66fc | ||
|
|
f96fd17fd3 | ||
|
|
c255a2494d | ||
|
|
86a9846300 | ||
|
|
db877d253c | ||
|
|
0acf1e3b08 | ||
|
|
362ed3a9b6 | ||
|
|
758878a229 | ||
|
|
ffb6dfc333 | ||
|
|
66da74e00a | ||
|
|
d41a0045cb | ||
|
|
b65629ba0e | ||
|
|
9518e6d1a0 | ||
|
|
4f374ee885 | ||
|
|
afa239056e | ||
|
|
886825af11 | ||
|
|
198de925aa | ||
|
|
3f7b71e9a5 | ||
|
|
95baaf8603 | ||
|
|
3673264bab | ||
|
|
64fb5a6b63 | ||
|
|
e9c959ccdb | ||
|
|
4b7487e92e | ||
|
|
52dbcffd8e | ||
|
|
24ae354bc2 | ||
|
|
b30b91fd91 | ||
|
|
efb63afc74 | ||
|
|
16706f7169 | ||
|
|
d7c32676b5 | ||
|
|
c8c45446bc | ||
|
|
f4de2e27d7 | ||
|
|
970fcbd93b | ||
|
|
57d1cd7f1e | ||
|
|
522fc372fa | ||
|
|
7141690fcb | ||
|
|
c7d9177e68 | ||
|
|
00b3ea40d9 | ||
|
|
c9afe939dc | ||
|
|
4171ae6516 | ||
|
|
35a42c49d5 | ||
|
|
e4dbf56b49 | ||
|
|
76eeb10c47 | ||
|
|
9fa73ad54f | ||
|
|
6034a4fd06 |
8
.github/workflows/build_nupkg.yml
vendored
8
.github/workflows/build_nupkg.yml
vendored
@@ -16,10 +16,16 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
|
||||
- name: Build library
|
||||
run: dotnet build
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
|
||||
- name: Pack
|
||||
run: dotnet pack
|
||||
|
||||
55
.github/workflows/build_test.yml
vendored
Normal file
55
.github/workflows/build_test.yml
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
name: Build InfoPrint
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "main" ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
project: [InfoPrint]
|
||||
runtime: [win-x86, win-x64, win-arm64, linux-x64, linux-arm64, osx-x64]
|
||||
framework: [net9.0] #[net20, net35, net40, net452, net472, net48, netcoreapp3.1, net5.0, net6.0, net7.0, net8.0, net9.0]
|
||||
conf: [Debug] #[Release, Debug]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 9.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') || startsWith(matrix.framework, 'net9')) && '-p:PublishSingleFile=true' || ''}}
|
||||
|
||||
- name: Archive build
|
||||
run: |
|
||||
cd ${{ matrix.project }}/bin/Debug/${{ matrix.framework }}/${{ matrix.runtime }}/publish/
|
||||
zip -r ${{ github.workspace }}/${{ matrix.project }}_${{ matrix.framework }}_${{ matrix.runtime }}_${{ matrix.conf }}.zip ./
|
||||
|
||||
- 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
|
||||
7
.github/workflows/check_pr.yml
vendored
7
.github/workflows/check_pr.yml
vendored
@@ -11,7 +11,10 @@ jobs:
|
||||
- name: Setup .NET
|
||||
uses: actions/setup-dotnet@v4
|
||||
with:
|
||||
dotnet-version: 8.0.x
|
||||
dotnet-version: 9.0.x
|
||||
|
||||
- name: Build
|
||||
run: dotnet build
|
||||
run: dotnet build
|
||||
|
||||
- name: Run tests
|
||||
run: dotnet test
|
||||
328
.gitignore
vendored
328
.gitignore
vendored
@@ -1,15 +1,7 @@
|
||||
*.swp
|
||||
*.*~
|
||||
project.lock.json
|
||||
.DS_Store
|
||||
*.pyc
|
||||
nupkg/
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode
|
||||
|
||||
# Rider
|
||||
.idea
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
##
|
||||
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
@@ -17,6 +9,9 @@ nupkg/
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
@@ -24,15 +19,312 @@ nupkg/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Oo]ut/
|
||||
msbuild.log
|
||||
msbuild.err
|
||||
msbuild.wrn
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015
|
||||
# Visual Studio 2015/2017 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# Visual Studio 2017 auto generated files
|
||||
Generated\ Files/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# Benchmark Results
|
||||
BenchmarkDotNet.Artifacts/
|
||||
|
||||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
# StyleCop
|
||||
StyleCopReport.xml
|
||||
|
||||
# Files built by Visual Studio
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.iobj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.ipdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# Visual Studio Trace Files
|
||||
*.e2e
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# AxoCover is a Code Coverage Tool
|
||||
.axoCover/*
|
||||
!.axoCover/settings.json
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# Note: Comment the next line if you want to checkin your web deploy settings,
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/[Pp]ackages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/[Pp]ackages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/[Pp]ackages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignorable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
*.appx
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
orleans.codegen.cs
|
||||
|
||||
# Including strong name files can present a security risk
|
||||
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
|
||||
#*.snk
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
ServiceFabricBackup/
|
||||
*.rptproj.bak
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
*.ndf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
*.rptproj.rsuser
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
node_modules/
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
|
||||
*.vbw
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/**
|
||||
# !tools/packages.config
|
||||
|
||||
# Tabs Studio
|
||||
*.tss
|
||||
|
||||
# Telerik's JustMock configuration file
|
||||
*.jmconfig
|
||||
|
||||
# BizTalk build output
|
||||
*.btp.cs
|
||||
*.btm.cs
|
||||
*.odx.cs
|
||||
*.xsd.cs
|
||||
|
||||
# OpenCover UI analysis results
|
||||
OpenCover/
|
||||
|
||||
# Azure Stream Analytics local run output
|
||||
ASALocalRun/
|
||||
|
||||
# MSBuild Binary and Structured Log
|
||||
*.binlog
|
||||
|
||||
# NVidia Nsight GPU debugger configuration file
|
||||
*.nvuser
|
||||
|
||||
# MFractors (Xamarin productivity tool) working folder
|
||||
.mfractor/
|
||||
|
||||
28
.vscode/launch.json
vendored
Normal file
28
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
// Use IntelliSense to find out which attributes exist for C# debugging
|
||||
// Use hover for the description of the existing attributes
|
||||
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": ".NET Core Launch (InfoPrint)",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build",
|
||||
// If you have changed target frameworks, make sure to update the program path.
|
||||
"program": "${workspaceFolder}/InfoPrint/bin/Debug/net9.0/InfoPrint.dll",
|
||||
"args": [],
|
||||
"cwd": "${workspaceFolder}",
|
||||
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false,
|
||||
"justMyCode": false
|
||||
},
|
||||
{
|
||||
"name": ".NET Core Attach",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickProcess}"
|
||||
}
|
||||
]
|
||||
}
|
||||
24
.vscode/tasks.json
vendored
Normal file
24
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=733558
|
||||
// for the documentation about the tasks.json format
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "build",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"build",
|
||||
// Ask dotnet build to generate full paths for file names.
|
||||
"/property:GenerateFullPaths=true",
|
||||
// Do not generate summary otherwise it leads to duplicate errors in Problems panel
|
||||
"/consoleloggerparameters:NoSummary"
|
||||
],
|
||||
"group": "build",
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"problemMatcher": "$msCompile"
|
||||
}
|
||||
]
|
||||
}
|
||||
33
InfoPrint/InfoPrint.csproj
Normal file
33
InfoPrint/InfoPrint.csproj
Normal file
@@ -0,0 +1,33 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net20;net35;net40;net452;net462;net472;net48;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
<OutputType>Exe</OutputType>
|
||||
<CheckEolTargetFramework>false</CheckEolTargetFramework>
|
||||
<IncludeSourceRevisionInInformationalVersion>false</IncludeSourceRevisionInInformationalVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<Version>1.7.4</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<!-- Support All Frameworks -->
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net2`)) OR $(TargetFramework.StartsWith(`net3`)) OR $(TargetFramework.StartsWith(`net4`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`netcoreapp`)) OR $(TargetFramework.StartsWith(`net5`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(TargetFramework.StartsWith(`net6`)) OR $(TargetFramework.StartsWith(`net7`)) OR $(TargetFramework.StartsWith(`net8`)) OR $(TargetFramework.StartsWith(`net9`))">
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64;linux-x64;linux-arm64;osx-x64;osx-arm64</RuntimeIdentifiers>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="$(RuntimeIdentifier.StartsWith(`osx-arm`))">
|
||||
<TargetFrameworks>net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.Serialization\SabreTools.Serialization.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
119
InfoPrint/Options.cs
Normal file
119
InfoPrint/Options.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace InfoPrint
|
||||
{
|
||||
/// <summary>
|
||||
/// Set of options for the test executable
|
||||
/// </summary>
|
||||
internal sealed class Options
|
||||
{
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Enable debug output for relevant operations
|
||||
/// </summary>
|
||||
public bool Debug { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Set of input paths to use for operations
|
||||
/// </summary>
|
||||
public List<string> InputPaths { get; private set; } = [];
|
||||
|
||||
#if NETCOREAPP3_1_OR_GREATER
|
||||
/// <summary>
|
||||
/// Enable JSON output
|
||||
/// </summary>
|
||||
public bool Json { get; private set; } = false;
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Parse commandline arguments into an Options object
|
||||
/// </summary>
|
||||
public static Options? ParseOptions(string[] args)
|
||||
{
|
||||
// If we have invalid arguments
|
||||
if (args == null || args.Length == 0)
|
||||
return null;
|
||||
|
||||
// Create an Options object
|
||||
var options = new Options();
|
||||
|
||||
// Parse the features
|
||||
int index = 0;
|
||||
for (; index < args.Length; index++)
|
||||
{
|
||||
string arg = args[index];
|
||||
bool featureFound = false;
|
||||
switch (arg)
|
||||
{
|
||||
case "-?":
|
||||
case "-h":
|
||||
case "--help":
|
||||
return null;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// If the flag wasn't a feature
|
||||
if (!featureFound)
|
||||
break;
|
||||
}
|
||||
|
||||
// Parse the options and paths
|
||||
for (; index < args.Length; index++)
|
||||
{
|
||||
string arg = args[index];
|
||||
switch (arg)
|
||||
{
|
||||
case "-d":
|
||||
case "--debug":
|
||||
options.Debug = true;
|
||||
break;
|
||||
|
||||
case "-j":
|
||||
case "--json":
|
||||
#if NET6_0_OR_GREATER
|
||||
options.Json = true;
|
||||
#else
|
||||
Console.WriteLine("JSON output not available in .NET Framework");
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
options.InputPaths.Add(arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Validate we have any input paths to work on
|
||||
if (options.InputPaths.Count == 0)
|
||||
{
|
||||
Console.WriteLine("At least one path is required!");
|
||||
return null;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Display help text
|
||||
/// </summary>
|
||||
public static void DisplayHelp()
|
||||
{
|
||||
Console.WriteLine("Information Printing Program");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("infoprint.exe <options> file|directory ...");
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Options:");
|
||||
Console.WriteLine("-?, -h, --help Display this help text and quit");
|
||||
Console.WriteLine("-d, --debug Enable debug mode");
|
||||
#if NET6_0_OR_GREATER
|
||||
Console.WriteLine("-j, --json Print info as JSON");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
132
InfoPrint/Program.cs
Normal file
132
InfoPrint/Program.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Serialization;
|
||||
using SabreTools.Serialization.Wrappers;
|
||||
|
||||
namespace InfoPrint
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
// Get the options from the arguments
|
||||
var options = Options.ParseOptions(args);
|
||||
|
||||
// If we have an invalid state
|
||||
if (options == null)
|
||||
{
|
||||
Options.DisplayHelp();
|
||||
return;
|
||||
}
|
||||
|
||||
// Loop through the input paths
|
||||
foreach (string inputPath in options.InputPaths)
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
PrintPathInfo(inputPath, false, options.Debug);
|
||||
#else
|
||||
PrintPathInfo(inputPath, options.Json, options.Debug);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Wrapper to print information for a single path
|
||||
/// </summary>
|
||||
/// <param name="path">File or directory path</param>
|
||||
/// <param name="json">Enable JSON output, if supported</param>
|
||||
/// <param name="debug">Enable debug output</param>
|
||||
private static void PrintPathInfo(string path, bool json, bool debug)
|
||||
{
|
||||
Console.WriteLine($"Checking possible path: {path}");
|
||||
|
||||
// Check if the file or directory exists
|
||||
if (File.Exists(path))
|
||||
{
|
||||
PrintFileInfo(path, json, debug);
|
||||
}
|
||||
else if (Directory.Exists(path))
|
||||
{
|
||||
foreach (string file in IOExtensions.SafeEnumerateFiles(path, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
PrintFileInfo(file, json, debug);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"{path} does not exist, skipping...");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Print information for a single file, if possible
|
||||
/// </summary>
|
||||
private static void PrintFileInfo(string file, bool json, bool debug)
|
||||
{
|
||||
Console.WriteLine($"Attempting to print info for {file}");
|
||||
|
||||
try
|
||||
{
|
||||
using Stream stream = File.Open(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
|
||||
// Read the first 8 bytes
|
||||
byte[]? magic = stream.ReadBytes(8);
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
// Get the file type
|
||||
string extension = Path.GetExtension(file).TrimStart('.');
|
||||
WrapperType ft = WrapperFactory.GetFileType(magic ?? [], extension);
|
||||
|
||||
// Print out the file format
|
||||
Console.WriteLine($"File format found: {ft}");
|
||||
|
||||
// Setup the wrapper to print
|
||||
var wrapper = WrapperFactory.CreateWrapper(ft, stream);
|
||||
|
||||
// If we don't have a wrapper
|
||||
if (wrapper == null)
|
||||
{
|
||||
Console.WriteLine($"Either {ft} is not supported or something went wrong during parsing!");
|
||||
Console.WriteLine();
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the base info output name
|
||||
string filenameBase = $"info-{DateTime.Now:yyyy-MM-dd_HHmmss.ffff}";
|
||||
|
||||
#if NET6_0_OR_GREATER
|
||||
// If we have the JSON flag
|
||||
if (json)
|
||||
{
|
||||
// Create the output data
|
||||
string serializedData = wrapper.ExportJSON();
|
||||
Console.WriteLine(serializedData);
|
||||
|
||||
// Write the output data
|
||||
using var jsw = new StreamWriter(File.OpenWrite($"{filenameBase}.json"));
|
||||
jsw.WriteLine(serializedData);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create the output data
|
||||
var builder = wrapper.ExportStringBuilder();
|
||||
if (builder == null)
|
||||
{
|
||||
Console.WriteLine("No item information could be generated");
|
||||
return;
|
||||
}
|
||||
|
||||
// Write the output data
|
||||
Console.WriteLine(builder);
|
||||
using var sw = new StreamWriter(File.OpenWrite($"{filenameBase}.txt"));
|
||||
sw.WriteLine(builder.ToString());
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine(debug ? ex : "[Exception opening file, please try again]");
|
||||
Console.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
17
README.MD
17
README.MD
@@ -4,9 +4,15 @@ This library comprises of serializers that both read and write from files and st
|
||||
|
||||
Find the link to the Nuget package [here](https://www.nuget.org/packages/SabreTools.Serialization).
|
||||
|
||||
## Releases
|
||||
|
||||
For the most recent stable build, download the latest release here: [Releases Page](https://github.com/SabreTools/SabreTools.Serialization/releases)
|
||||
|
||||
For the latest WIP build here: [Rolling Release](https://github.com/SabreTools/SabreTools.Serialization/releases/tag/rolling)
|
||||
|
||||
## 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 +25,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 +41,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 |
|
||||
|
||||
@@ -31,13 +31,9 @@ namespace SabreTools.Serialization.Test
|
||||
Assert.Equal(count, dat.File.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.Null(dat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dat.ADDITIONAL_ELEMENTS);
|
||||
foreach (var file in dat.File)
|
||||
{
|
||||
Assert.NotNull(file);
|
||||
Assert.Null(file.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(file.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,7 +55,6 @@ namespace SabreTools.Serialization.Test
|
||||
foreach (var file in dat.Row)
|
||||
{
|
||||
Assert.NotNull(file);
|
||||
Assert.Null(file.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,103 +71,12 @@ namespace SabreTools.Serialization.Test
|
||||
|
||||
// Validate the values
|
||||
if (expectHeader)
|
||||
{
|
||||
Assert.NotNull(dat?.ClrMamePro);
|
||||
Assert.Null(dat.ClrMamePro.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(dat?.ClrMamePro);
|
||||
}
|
||||
|
||||
Assert.NotNull(dat?.Game);
|
||||
Assert.Equal(count, dat.Game.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.NotNull(dat?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.ADDITIONAL_ELEMENTS);
|
||||
foreach (var game in dat.Game)
|
||||
{
|
||||
Assert.NotNull(game?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(game.ADDITIONAL_ELEMENTS);
|
||||
foreach (var release in game.Release ?? Array.Empty<Models.ClrMamePro.Release>())
|
||||
{
|
||||
Assert.NotNull(release?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(release.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var biosset in game.BiosSet ?? Array.Empty<Models.ClrMamePro.BiosSet>())
|
||||
{
|
||||
Assert.NotNull(biosset?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(biosset.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var rom in game.Rom ?? Array.Empty<Models.ClrMamePro.Rom>())
|
||||
{
|
||||
Assert.NotNull(rom?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(rom.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var disk in game.Disk ?? Array.Empty<Models.ClrMamePro.Disk>())
|
||||
{
|
||||
Assert.NotNull(disk?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(disk.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var media in game.Media ?? Array.Empty<Models.ClrMamePro.Media>())
|
||||
{
|
||||
Assert.NotNull(media?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(media.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var sample in game.Sample ?? Array.Empty<Models.ClrMamePro.Sample>())
|
||||
{
|
||||
Assert.NotNull(sample?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(sample.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var archive in game.Archive ?? Array.Empty<Models.ClrMamePro.Archive>())
|
||||
{
|
||||
Assert.NotNull(archive?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(archive.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var chip in game.Chip ?? Array.Empty<Models.ClrMamePro.Chip>())
|
||||
{
|
||||
Assert.NotNull(chip?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(chip.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var video in game.Video ?? Array.Empty<Models.ClrMamePro.Video>())
|
||||
{
|
||||
Assert.NotNull(video?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(video.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Sound != null)
|
||||
{
|
||||
Assert.NotNull(game.Sound?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(game.Sound.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Input != null)
|
||||
{
|
||||
Assert.NotNull(game.Input?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(game.Input.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var dipswitch in game.DipSwitch ?? Array.Empty<Models.ClrMamePro.DipSwitch>())
|
||||
{
|
||||
Assert.NotNull(dipswitch?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dipswitch.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Driver != null)
|
||||
{
|
||||
Assert.NotNull(game.Driver?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(game.Driver.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -192,23 +96,9 @@ namespace SabreTools.Serialization.Test
|
||||
Assert.NotNull(dat?.Game);
|
||||
Assert.Equal(count, dat.Game.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.NotNull(dat?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.ADDITIONAL_ELEMENTS);
|
||||
|
||||
Assert.NotNull(dat.DosCenter?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.DosCenter.ADDITIONAL_ELEMENTS);
|
||||
foreach (var game in dat.Game)
|
||||
{
|
||||
Assert.NotNull(game?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(game.ADDITIONAL_ELEMENTS);
|
||||
|
||||
Assert.NotNull(game.File);
|
||||
foreach (var file in game.File)
|
||||
{
|
||||
Assert.NotNull(file?.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(file.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,20 +115,10 @@ namespace SabreTools.Serialization.Test
|
||||
// Validate the values
|
||||
Assert.NotNull(dat?.Row);
|
||||
Assert.Equal(count, dat.Row.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
foreach (var file in dat.Row)
|
||||
{
|
||||
Assert.Null(file.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("test-sfv-files.sfv", HashType.CRC32, 100)]
|
||||
[InlineData("test-sfv-files.sfv", HashType.CRC32_ISO, 100)]
|
||||
[InlineData("test-sfv-files.sfv", HashType.CRC32_Naive, 100)]
|
||||
[InlineData("test-sfv-files.sfv", HashType.CRC32_Optimized, 100)]
|
||||
[InlineData("test-sfv-files.sfv", HashType.CRC32_Parallel, 100)]
|
||||
[InlineData("test-md5-files.md5", HashType.MD5, 100)]
|
||||
[InlineData("test-sha1-files.sha1", HashType.SHA1, 100)]
|
||||
[InlineData("test-sha256.sha256", HashType.SHA256, 1)]
|
||||
@@ -259,10 +139,6 @@ namespace SabreTools.Serialization.Test
|
||||
switch (hash)
|
||||
{
|
||||
case HashType.CRC32:
|
||||
case HashType.CRC32_ISO:
|
||||
case HashType.CRC32_Naive:
|
||||
case HashType.CRC32_Optimized:
|
||||
case HashType.CRC32_Parallel:
|
||||
Assert.NotNull(dat.SFV);
|
||||
Assert.Equal(count, dat.SFV.Length);
|
||||
break;
|
||||
@@ -308,10 +184,6 @@ namespace SabreTools.Serialization.Test
|
||||
// Validate the values
|
||||
Assert.NotNull(dat?.Set);
|
||||
Assert.Equal(count, dat.Set.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.NotNull(dat.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -328,219 +200,6 @@ namespace SabreTools.Serialization.Test
|
||||
// Validate the values
|
||||
Assert.NotNull(dat?.Game);
|
||||
Assert.Equal(count, dat.Game.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.Null(dat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dat.ADDITIONAL_ELEMENTS);
|
||||
foreach (var game in dat.Game)
|
||||
{
|
||||
Assert.Null(game.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var biosset in game.BiosSet ?? Array.Empty<Models.Listxml.BiosSet>())
|
||||
{
|
||||
Assert.Null(biosset.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(biosset.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var rom in game.Rom ?? Array.Empty<Models.Listxml.Rom>())
|
||||
{
|
||||
Assert.Null(rom.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(rom.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var disk in game.Disk ?? Array.Empty<Models.Listxml.Disk>())
|
||||
{
|
||||
Assert.Null(disk.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(disk.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var deviceRef in game.DeviceRef ?? Array.Empty<Models.Listxml.DeviceRef>())
|
||||
{
|
||||
Assert.Null(deviceRef.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(deviceRef.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var sample in game.Sample ?? Array.Empty<Models.Listxml.Sample>())
|
||||
{
|
||||
Assert.Null(sample.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(sample.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var chip in game.Chip ?? Array.Empty<Models.Listxml.Chip>())
|
||||
{
|
||||
Assert.Null(chip.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(chip.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var display in game.Display ?? Array.Empty<Models.Listxml.Display>())
|
||||
{
|
||||
Assert.Null(display.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(display.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var video in game.Video ?? Array.Empty<Models.Listxml.Video>())
|
||||
{
|
||||
Assert.Null(video.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(video.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Sound != null)
|
||||
{
|
||||
Assert.Null(game.Sound.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.Sound.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Input != null)
|
||||
{
|
||||
Assert.Null(game.Input.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.Input.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var control in game.Input.Control ?? Array.Empty<Models.Listxml.Control>())
|
||||
{
|
||||
Assert.Null(control.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(control.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var dipswitch in game.DipSwitch ?? Array.Empty<Models.Listxml.DipSwitch>())
|
||||
{
|
||||
Assert.Null(dipswitch.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dipswitch.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (dipswitch.Condition != null)
|
||||
{
|
||||
Assert.Null(dipswitch.Condition.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dipswitch.Condition.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var diplocation in dipswitch.DipLocation ?? Array.Empty<Models.Listxml.DipLocation>())
|
||||
{
|
||||
Assert.Null(diplocation.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(diplocation.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var dipvalue in dipswitch.DipValue ?? Array.Empty<Models.Listxml.DipValue>())
|
||||
{
|
||||
Assert.Null(dipvalue.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dipvalue.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (dipvalue.Condition != null)
|
||||
{
|
||||
Assert.Null(dipvalue.Condition.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dipvalue.Condition.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var configuration in game.Configuration ?? Array.Empty<Models.Listxml.Configuration>())
|
||||
{
|
||||
Assert.Null(configuration.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(configuration.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (configuration.Condition != null)
|
||||
{
|
||||
Assert.Null(configuration.Condition.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(configuration.Condition.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var conflocation in configuration.ConfLocation ?? Array.Empty<Models.Listxml.ConfLocation>())
|
||||
{
|
||||
Assert.Null(conflocation.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(conflocation.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var confsetting in configuration.ConfSetting ?? Array.Empty<Models.Listxml.ConfSetting>())
|
||||
{
|
||||
Assert.Null(confsetting.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(confsetting.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (confsetting.Condition != null)
|
||||
{
|
||||
Assert.Null(confsetting.Condition.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(confsetting.Condition.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var port in game.Port ?? Array.Empty<Models.Listxml.Port>())
|
||||
{
|
||||
Assert.Null(port.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(port.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var analog in port.Analog ?? Array.Empty<Models.Listxml.Analog>())
|
||||
{
|
||||
Assert.Null(analog.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(analog.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var adjuster in game.Adjuster ?? Array.Empty<Models.Listxml.Adjuster>())
|
||||
{
|
||||
Assert.Null(adjuster.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(adjuster.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (adjuster.Condition != null)
|
||||
{
|
||||
Assert.Null(adjuster.Condition.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(adjuster.Condition.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
if (game.Driver != null)
|
||||
{
|
||||
Assert.Null(game.Driver.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.Driver.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var feature in game.Feature ?? Array.Empty<Models.Listxml.Feature>())
|
||||
{
|
||||
Assert.Null(feature.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(feature.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var device in game.Device ?? Array.Empty<Models.Listxml.Device>())
|
||||
{
|
||||
Assert.Null(device.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(device.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (device.Instance != null)
|
||||
{
|
||||
Assert.Null(device.Instance.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(device.Instance.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var extension in device.Extension ?? Array.Empty<Models.Listxml.Extension>())
|
||||
{
|
||||
Assert.Null(extension.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(extension.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var slot in game.Slot ?? Array.Empty<Models.Listxml.Slot>())
|
||||
{
|
||||
Assert.Null(slot.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(slot.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var slotoption in slot.SlotOption ?? Array.Empty<Models.Listxml.SlotOption>())
|
||||
{
|
||||
Assert.Null(slotoption.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(slotoption.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var softwarelist in game.SoftwareList ?? Array.Empty<Models.Listxml.SoftwareList>())
|
||||
{
|
||||
Assert.Null(softwarelist.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(softwarelist.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var ramoption in game.RamOption ?? Array.Empty<Models.Listxml.RamOption>())
|
||||
{
|
||||
Assert.Null(ramoption.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(ramoption.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -557,180 +216,6 @@ namespace SabreTools.Serialization.Test
|
||||
// Validate the values
|
||||
Assert.NotNull(dat?.Game);
|
||||
Assert.Equal(count, dat.Game.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.Null(dat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dat.ADDITIONAL_ELEMENTS);
|
||||
if (dat.Header != null)
|
||||
{
|
||||
var header = dat.Header;
|
||||
Assert.Null(header.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(header.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (header.ClrMamePro != null)
|
||||
{
|
||||
var cmp = header.ClrMamePro;
|
||||
Assert.Null(cmp.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(cmp.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (header.RomCenter != null)
|
||||
{
|
||||
var rc = header.RomCenter;
|
||||
Assert.Null(rc.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(rc.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var game in dat.Game)
|
||||
{
|
||||
Assert.Null(game.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var item in game.Release ?? Array.Empty<Models.Logiqx.Release>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.BiosSet ?? Array.Empty<Models.Logiqx.BiosSet>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Rom ?? Array.Empty<Models.Logiqx.Rom>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Disk ?? Array.Empty<Models.Logiqx.Disk>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Media ?? Array.Empty<Models.Logiqx.Media>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.DeviceRef ?? Array.Empty<Models.Logiqx.DeviceRef>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Sample ?? Array.Empty<Models.Logiqx.Sample>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Archive ?? Array.Empty<Models.Logiqx.Archive>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Driver != null)
|
||||
{
|
||||
Assert.Null(game.Driver.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.Driver.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.SoftwareList ?? Array.Empty<Models.Logiqx.SoftwareList>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Trurip != null)
|
||||
{
|
||||
var trurip = game.Trurip;
|
||||
Assert.Null(trurip.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(trurip.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var dir in dat.Dir ?? Array.Empty<Models.Logiqx.Dir>())
|
||||
{
|
||||
Assert.NotNull(dir.Game);
|
||||
foreach (var game in dir.Game)
|
||||
{
|
||||
Assert.Null(game.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var item in game.Release ?? Array.Empty<Models.Logiqx.Release>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.BiosSet ?? Array.Empty<Models.Logiqx.BiosSet>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Rom ?? Array.Empty<Models.Logiqx.Rom>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Disk ?? Array.Empty<Models.Logiqx.Disk>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Media ?? Array.Empty<Models.Logiqx.Media>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.DeviceRef ?? Array.Empty<Models.Logiqx.DeviceRef>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Sample ?? Array.Empty<Models.Logiqx.Sample>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.Archive ?? Array.Empty<Models.Logiqx.Archive>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Driver != null)
|
||||
{
|
||||
Assert.Null(game.Driver.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(game.Driver.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var item in game.SoftwareList ?? Array.Empty<Models.Logiqx.SoftwareList>())
|
||||
{
|
||||
Assert.Null(item.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(item.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (game.Trurip != null)
|
||||
{
|
||||
var trurip = game.Trurip;
|
||||
Assert.Null(trurip.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(trurip.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -746,196 +231,6 @@ namespace SabreTools.Serialization.Test
|
||||
// Validate the values
|
||||
Assert.NotNull(dat?.Games?.Game);
|
||||
Assert.Equal(count, dat.Games.Game.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.Null(dat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dat.ADDITIONAL_ELEMENTS);
|
||||
if (dat.Configuration != null)
|
||||
{
|
||||
var configuration = dat.Configuration;
|
||||
Assert.Null(configuration.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(configuration.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (configuration.Infos != null)
|
||||
{
|
||||
var infos = configuration.Infos;
|
||||
Assert.Null(infos.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(infos.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (infos.Title != null)
|
||||
{
|
||||
var title = infos.Title;
|
||||
Assert.Null(title.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(title.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.Location != null)
|
||||
{
|
||||
var location = infos.Location;
|
||||
Assert.Null(location.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(location.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.Publisher != null)
|
||||
{
|
||||
var publisher = infos.Publisher;
|
||||
Assert.Null(publisher.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(publisher.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.SourceRom != null)
|
||||
{
|
||||
var sourceRom = infos.SourceRom;
|
||||
Assert.Null(sourceRom.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(sourceRom.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.SaveType != null)
|
||||
{
|
||||
var saveType = infos.SaveType;
|
||||
Assert.Null(saveType.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(saveType.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.RomSize != null)
|
||||
{
|
||||
var romSize = infos.RomSize;
|
||||
Assert.Null(romSize.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(romSize.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.ReleaseNumber != null)
|
||||
{
|
||||
var releaseNumber = infos.ReleaseNumber;
|
||||
Assert.Null(releaseNumber.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(releaseNumber.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.LanguageNumber != null)
|
||||
{
|
||||
var languageNumber = infos.LanguageNumber;
|
||||
Assert.Null(languageNumber.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(languageNumber.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.Comment != null)
|
||||
{
|
||||
var comment = infos.Comment;
|
||||
Assert.Null(comment.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(comment.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.RomCRC != null)
|
||||
{
|
||||
var romCRC = infos.RomCRC;
|
||||
Assert.Null(romCRC.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(romCRC.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.Im1CRC != null)
|
||||
{
|
||||
var im1CRC = infos.Im1CRC;
|
||||
Assert.Null(im1CRC.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(im1CRC.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.Im2CRC != null)
|
||||
{
|
||||
var im2CRC = infos.Im2CRC;
|
||||
Assert.Null(im2CRC.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(im2CRC.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (infos.Languages != null)
|
||||
{
|
||||
var languages = infos.Languages;
|
||||
Assert.Null(languages.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(languages.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
if (configuration.CanOpen != null)
|
||||
{
|
||||
var canOpen = configuration.CanOpen;
|
||||
Assert.Null(canOpen.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(canOpen.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (configuration.NewDat != null)
|
||||
{
|
||||
var newDat = configuration.NewDat;
|
||||
Assert.Null(newDat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(newDat.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (newDat.DatUrl != null)
|
||||
{
|
||||
var datURL = newDat.DatUrl;
|
||||
Assert.Null(datURL.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(datURL.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
if (configuration.Search != null)
|
||||
{
|
||||
var search = configuration.Search;
|
||||
Assert.Null(search.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(search.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var to in search.To ?? Array.Empty<Models.OfflineList.To>())
|
||||
{
|
||||
Assert.Null(to.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(to.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var find in to.Find ?? Array.Empty<Models.OfflineList.Find>())
|
||||
{
|
||||
Assert.Null(find.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(find.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Assert.Null(dat.Games.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dat.Games.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var game in dat.Games.Game)
|
||||
{
|
||||
Assert.Null(game.ADDITIONAL_ATTRIBUTES);
|
||||
//Assert.Null(game.ADDITIONAL_ELEMENTS); // TODO: Re-enable line when Models is fixed again
|
||||
|
||||
if (game.Files != null)
|
||||
{
|
||||
var files = game.Files;
|
||||
Assert.Null(files.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(files.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var romCRC in files.RomCRC ?? Array.Empty<Models.OfflineList.FileRomCRC>())
|
||||
{
|
||||
Assert.Null(romCRC.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(romCRC.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dat.GUI != null)
|
||||
{
|
||||
var gui = dat.GUI;
|
||||
Assert.Null(gui.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(gui.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (gui.Images != null)
|
||||
{
|
||||
var images = gui.Images;
|
||||
Assert.Null(images.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(images.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var image in images.Image ?? Array.Empty<Models.OfflineList.Image>())
|
||||
{
|
||||
Assert.Null(image.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(image.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -952,33 +247,6 @@ namespace SabreTools.Serialization.Test
|
||||
Assert.NotNull(dat);
|
||||
Assert.NotNull(dat.Software);
|
||||
Assert.Equal(count, dat.Software.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.Null(dat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dat.ADDITIONAL_ELEMENTS);
|
||||
foreach (var software in dat.Software)
|
||||
{
|
||||
Assert.Null(software.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(software.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var dump in software.Dump ?? Array.Empty<Models.OpenMSX.Dump>())
|
||||
{
|
||||
Assert.Null(dump.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dump.ADDITIONAL_ELEMENTS);
|
||||
|
||||
if (dump.Original != null)
|
||||
{
|
||||
Assert.Null(dump.Original.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dump.Original.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (dump.Rom != null)
|
||||
{
|
||||
Assert.Null(dump.Rom.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dump.Rom.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -994,37 +262,6 @@ namespace SabreTools.Serialization.Test
|
||||
// Validate the values
|
||||
Assert.NotNull(dat?.Games?.Rom);
|
||||
Assert.Equal(count, dat.Games.Rom.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.NotNull(dat.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.ADDITIONAL_ELEMENTS);
|
||||
if (dat.Credits != null)
|
||||
{
|
||||
Assert.NotNull(dat.Credits.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.Credits.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (dat.Dat != null)
|
||||
{
|
||||
Assert.NotNull(dat.Dat.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.Dat.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (dat.Emulator != null)
|
||||
{
|
||||
Assert.NotNull(dat.Emulator.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.Emulator.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
if (dat.Games != null)
|
||||
{
|
||||
Assert.NotNull(dat.Games.ADDITIONAL_ELEMENTS);
|
||||
Assert.Empty(dat.Games.ADDITIONAL_ELEMENTS);
|
||||
foreach (var rom in dat.Games.Rom ?? Array.Empty<Models.RomCenter.Rom>())
|
||||
{
|
||||
Assert.Null(rom.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -1045,12 +282,6 @@ namespace SabreTools.Serialization.Test
|
||||
// Validate the values
|
||||
Assert.NotNull(dat?.Row);
|
||||
Assert.Equal(count, dat.Row.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
foreach (var rom in dat.Row ?? Array.Empty<Models.SeparatedValue.Row>())
|
||||
{
|
||||
Assert.Null(rom.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@@ -1069,77 +300,8 @@ namespace SabreTools.Serialization.Test
|
||||
Assert.NotNull(dat);
|
||||
Assert.NotNull(dat.Software);
|
||||
Assert.Equal(count, dat.Software.Length);
|
||||
|
||||
// Validate we're not missing any attributes or elements
|
||||
Assert.Null(dat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dat.ADDITIONAL_ELEMENTS);
|
||||
foreach (var software in dat.Software)
|
||||
{
|
||||
Assert.Null(software.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(software.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var info in software.Info ?? Array.Empty<Models.SoftwareList.Info>())
|
||||
{
|
||||
Assert.Null(info.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(info.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var sharedfeat in software.SharedFeat ?? Array.Empty<Models.SoftwareList.SharedFeat>())
|
||||
{
|
||||
Assert.Null(sharedfeat.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(sharedfeat.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var part in software.Part ?? Array.Empty<Models.SoftwareList.Part>())
|
||||
{
|
||||
Assert.Null(part.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(part.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var feature in part.Feature ?? Array.Empty<Models.SoftwareList.Feature>())
|
||||
{
|
||||
Assert.Null(feature.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(feature.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
|
||||
foreach (var dataarea in part.DataArea ?? Array.Empty<Models.SoftwareList.DataArea>())
|
||||
{
|
||||
Assert.Null(dataarea.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dataarea.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var rom in dataarea.Rom ?? Array.Empty<Models.SoftwareList.Rom>())
|
||||
{
|
||||
Assert.Null(rom.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(rom.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var diskarea in part.DiskArea ?? Array.Empty<Models.SoftwareList.DiskArea>())
|
||||
{
|
||||
Assert.Null(diskarea.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(diskarea.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var disk in diskarea.Disk ?? Array.Empty<Models.SoftwareList.Disk>())
|
||||
{
|
||||
Assert.Null(disk.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(disk.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var dipswitch in part.DipSwitch ?? Array.Empty<Models.SoftwareList.DipSwitch>())
|
||||
{
|
||||
Assert.Null(dipswitch.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dipswitch.ADDITIONAL_ELEMENTS);
|
||||
|
||||
foreach (var dipvalue in dipswitch.DipValue ?? Array.Empty<Models.SoftwareList.DipValue>())
|
||||
{
|
||||
Assert.Null(dipvalue.ADDITIONAL_ATTRIBUTES);
|
||||
Assert.Null(dipvalue.ADDITIONAL_ELEMENTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Get the path to the test file
|
||||
/// </summary>
|
||||
|
||||
@@ -63,9 +63,9 @@ namespace SabreTools.Serialization.Test
|
||||
|
||||
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 },
|
||||
new() { Original = original, Rom = rom },
|
||||
new() { Rom = megaRom },
|
||||
new() { Rom = sccPlusCart },
|
||||
};
|
||||
|
||||
var software = new Models.OpenMSX.Software
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0;net8.0;net9.0</TargetFrameworks>
|
||||
<IsPackable>false</IsPackable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.Serialization\SabreTools.Serialization.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\SabreTools.Serialization\SabreTools.Serialization.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="TestData\*" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="TestData\*" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="TestData\*">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</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.5" />
|
||||
<PackageReference Include="xunit" Version="2.7.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.8">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</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.11.1" />
|
||||
<PackageReference Include="SabreTools.Models" Version="1.5.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -5,7 +5,7 @@ VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SabreTools.Serialization", "SabreTools.Serialization\SabreTools.Serialization.csproj", "{5B688801-5F36-483E-B2E8-F219BA5923A2}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{F3DEE31A-4726-464C-A90C-C19D78F51898}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InfoPrint", "InfoPrint\InfoPrint.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
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.ArchiveDotOrg;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
@@ -16,14 +15,13 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var files = new Models.ArchiveDotOrg.Files();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
var items = new List<Models.ArchiveDotOrg.File>();
|
||||
foreach (var machine in machines ?? [])
|
||||
{
|
||||
files.File = machines
|
||||
.Where(m => m != null)
|
||||
.SelectMany(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
items.AddRange(ConvertFromInternalModel(machine));
|
||||
}
|
||||
|
||||
files.File = [.. items];
|
||||
return files;
|
||||
}
|
||||
|
||||
@@ -36,9 +34,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (roms == null)
|
||||
return [];
|
||||
|
||||
return roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel).ToArray();
|
||||
return Array.ConvertAll(roms, ConvertFromInternalModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
@@ -16,13 +16,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item),
|
||||
};
|
||||
|
||||
if (item?.File != null && item.File.Any())
|
||||
if (item?.File != null && item.File.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = item.File
|
||||
.Where(f => f != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.Where(m => m != null)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(item.File, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,14 +17,13 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var metadataFile = header != null ? ConvertHeaderFromInternalModel(header) : new MetadataFile();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
var items = new List<Row>();
|
||||
foreach (var machine in machines ?? [])
|
||||
{
|
||||
metadataFile.Row = machines
|
||||
.Where(m => m != null)
|
||||
.SelectMany(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
items.AddRange(ConvertMachineFromInternalModel(machine));
|
||||
}
|
||||
|
||||
metadataFile.Row = [.. items];
|
||||
return metadataFile;
|
||||
}
|
||||
|
||||
@@ -46,13 +45,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
private static Row[] ConvertMachineFromInternalModel(Models.Metadata.Machine item)
|
||||
{
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms == null || !roms.Any())
|
||||
if (roms == null || roms.Length == 0)
|
||||
return [];
|
||||
|
||||
return roms
|
||||
.Where(r => r != null)
|
||||
.Select(rom => ConvertFromInternalModel(rom, item))
|
||||
.ToArray();
|
||||
return Array.ConvertAll(roms, r => ConvertFromInternalModel(r, item));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.AttractMode;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,13 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(obj),
|
||||
};
|
||||
|
||||
if (obj?.Row != null && obj.Row.Any())
|
||||
if (obj?.Row != null && obj.Row.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = obj.Row
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.Where(m => m != null)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(obj.Row, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.ClrMamePro;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -22,12 +22,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
metadataFile.ClrMamePro = ConvertHeaderFromInternalModel(header);
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
if (machines != null && machines.Length > 0)
|
||||
{
|
||||
metadataFile.Game = machines
|
||||
.Where(m => m != null)
|
||||
.Select(machine => ConvertMachineFromInternalModel(machine, game))
|
||||
.ToArray();
|
||||
metadataFile.Game
|
||||
= Array.ConvertAll(machines, m => ConvertMachineFromInternalModel(m));
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -76,85 +74,40 @@ namespace SabreTools.Serialization.CrossModel
|
||||
gameBase.SampleOf = item.ReadString(Models.Metadata.Machine.SampleOfKey);
|
||||
|
||||
var releases = item.Read<Models.Metadata.Release[]>(Models.Metadata.Machine.ReleaseKey);
|
||||
if (releases != null && releases.Any())
|
||||
{
|
||||
gameBase.Release = releases
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (releases != null && releases.Length > 0)
|
||||
gameBase.Release = Array.ConvertAll(releases, ConvertFromInternalModel);
|
||||
|
||||
var biosSets = item.Read<Models.Metadata.BiosSet[]>(Models.Metadata.Machine.BiosSetKey);
|
||||
if (biosSets != null && biosSets.Any())
|
||||
{
|
||||
gameBase.BiosSet = biosSets
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (biosSets != null && biosSets.Length > 0)
|
||||
gameBase.BiosSet = Array.ConvertAll(biosSets, ConvertFromInternalModel);
|
||||
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms != null && roms.Any())
|
||||
{
|
||||
gameBase.Rom = roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (roms != null && roms.Length > 0)
|
||||
gameBase.Rom = Array.ConvertAll(roms, ConvertFromInternalModel);
|
||||
|
||||
var disks = item.Read<Models.Metadata.Disk[]>(Models.Metadata.Machine.DiskKey);
|
||||
if (disks != null && disks.Any())
|
||||
{
|
||||
gameBase.Disk = disks
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (disks != null && disks.Length > 0)
|
||||
gameBase.Disk = Array.ConvertAll(disks, ConvertFromInternalModel);
|
||||
|
||||
var medias = item.Read<Models.Metadata.Media[]>(Models.Metadata.Machine.MediaKey);
|
||||
if (medias != null && medias.Any())
|
||||
{
|
||||
gameBase.Media = medias
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (medias != null && medias.Length > 0)
|
||||
gameBase.Media = Array.ConvertAll(medias, ConvertFromInternalModel);
|
||||
|
||||
var samples = item.Read<Models.Metadata.Sample[]>(Models.Metadata.Machine.SampleKey);
|
||||
if (samples != null && samples.Any())
|
||||
{
|
||||
gameBase.Sample = samples
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (samples != null && samples.Length > 0)
|
||||
gameBase.Sample = Array.ConvertAll(samples, ConvertFromInternalModel);
|
||||
|
||||
var archives = item.Read<Models.Metadata.Archive[]>(Models.Metadata.Machine.ArchiveKey);
|
||||
if (archives != null && archives.Any())
|
||||
{
|
||||
gameBase.Archive = archives
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (archives != null && archives.Length > 0)
|
||||
gameBase.Archive = Array.ConvertAll(archives, ConvertFromInternalModel);
|
||||
|
||||
var chips = item.Read<Models.Metadata.Chip[]>(Models.Metadata.Machine.ChipKey);
|
||||
if (chips != null && chips.Any())
|
||||
{
|
||||
gameBase.Chip = chips
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (chips != null && chips.Length > 0)
|
||||
gameBase.Chip = Array.ConvertAll(chips, ConvertFromInternalModel);
|
||||
|
||||
var videos = item.Read<Models.Metadata.Video[]>(Models.Metadata.Machine.VideoKey);
|
||||
if (videos != null && videos.Any())
|
||||
{
|
||||
gameBase.Video = videos
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (videos != null && videos.Length > 0)
|
||||
gameBase.Video = Array.ConvertAll(videos, ConvertFromInternalModel);
|
||||
|
||||
var sound = item.Read<Models.Metadata.Sound>(Models.Metadata.Machine.SoundKey);
|
||||
if (sound != null)
|
||||
@@ -165,13 +118,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
gameBase.Input = ConvertFromInternalModel(input);
|
||||
|
||||
var dipSwitches = item.Read<Models.Metadata.DipSwitch[]>(Models.Metadata.Machine.DipSwitchKey);
|
||||
if (dipSwitches != null && dipSwitches.Any())
|
||||
{
|
||||
gameBase.DipSwitch = dipSwitches
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dipSwitches != null && dipSwitches.Length > 0)
|
||||
gameBase.DipSwitch = Array.ConvertAll(dipSwitches, ConvertFromInternalModel);
|
||||
|
||||
var driver = item.Read<Models.Metadata.Driver>(Models.Metadata.Machine.DriverKey);
|
||||
if (driver != null)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.ClrMamePro;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,13 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (obj?.ClrMamePro != null)
|
||||
metadataFile[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(obj.ClrMamePro);
|
||||
|
||||
if (obj?.Game != null && obj.Game.Any())
|
||||
if (obj?.Game != null && obj.Game.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = obj.Game
|
||||
.Where(g => g != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.Where(m => m != null)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(obj.Game, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -75,76 +72,58 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Machine.SampleOfKey] = item.SampleOf,
|
||||
};
|
||||
|
||||
if (item.Release != null && item.Release.Any())
|
||||
if (item.Release != null && item.Release.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.ReleaseKey] = item.Release
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.ReleaseKey]
|
||||
= Array.ConvertAll(item.Release, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.BiosSet != null && item.BiosSet.Any())
|
||||
if (item.BiosSet != null && item.BiosSet.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.BiosSetKey] = item.BiosSet
|
||||
.Where(b => b != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.BiosSetKey]
|
||||
= Array.ConvertAll(item.BiosSet, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Rom != null && item.Rom.Any())
|
||||
if (item.Rom != null && item.Rom.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.RomKey] = item.Rom
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.RomKey]
|
||||
= Array.ConvertAll(item.Rom, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Disk != null && item.Disk.Any())
|
||||
if (item.Disk != null && item.Disk.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DiskKey] = item.Disk
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DiskKey]
|
||||
= Array.ConvertAll(item.Disk, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Media != null && item.Media.Any())
|
||||
if (item.Media != null && item.Media.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.MediaKey] = item.Media
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.MediaKey]
|
||||
= Array.ConvertAll(item.Media, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Sample != null && item.Sample.Any())
|
||||
if (item.Sample != null && item.Sample.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.SampleKey] = item.Sample
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.SampleKey]
|
||||
= Array.ConvertAll(item.Sample, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Archive != null && item.Archive.Any())
|
||||
if (item.Archive != null && item.Archive.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.ArchiveKey] = item.Archive
|
||||
.Where(a => a != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.ArchiveKey]
|
||||
= Array.ConvertAll(item.Archive, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Chip != null && item.Chip.Any())
|
||||
if (item.Chip != null && item.Chip.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.ChipKey] = item.Chip
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.ChipKey]
|
||||
= Array.ConvertAll(item.Chip, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Video != null)
|
||||
{
|
||||
machine[Models.Metadata.Machine.VideoKey] = item.Video
|
||||
.Where(v => v != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.VideoKey]
|
||||
= Array.ConvertAll(item.Video, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Sound != null)
|
||||
@@ -153,12 +132,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (item.Input != null)
|
||||
machine[Models.Metadata.Machine.InputKey] = ConvertToInternalModel(item.Input);
|
||||
|
||||
if (item.DipSwitch != null && item.DipSwitch.Any())
|
||||
if (item.DipSwitch != null && item.DipSwitch.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DipSwitchKey] = item.DipSwitch
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DipSwitchKey]
|
||||
= Array.ConvertAll(item.DipSwitch, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Driver != null)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.DosCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -19,13 +19,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
metadataFile.DosCenter = ConvertHeaderFromInternalModel(header);
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
metadataFile.Game = machines
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
metadataFile.Game = Array.ConvertAll(machines, ConvertMachineFromInternalModel);
|
||||
|
||||
return metadataFile;
|
||||
}
|
||||
@@ -59,13 +54,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms != null && roms.Any())
|
||||
{
|
||||
game.File = roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (roms != null && roms.Length > 0)
|
||||
game.File = Array.ConvertAll(roms, ConvertFromInternalModel);
|
||||
|
||||
return game;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.DosCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,12 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (obj?.DosCenter != null)
|
||||
metadataFile[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(obj.DosCenter);
|
||||
|
||||
if (obj?.Game != null && obj.Game.Any())
|
||||
if (obj?.Game != null && obj.Game.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = obj.Game
|
||||
.Where(g => g != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(obj.Game, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -56,12 +54,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Machine.NameKey] = item.Name,
|
||||
};
|
||||
|
||||
if (item.File != null && item.File.Any())
|
||||
if (item.File != null && item.File.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.RomKey] = item.File
|
||||
.Where(f => f != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.RomKey]
|
||||
= Array.ConvertAll(item.File, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return machine;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.Models.EverdriveSMDB;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var metadataFile = new MetadataFile();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
metadataFile.Row = machines
|
||||
.Where(m => m != null)
|
||||
.SelectMany(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
var items = new List<Row>();
|
||||
foreach (var machine in machines ?? [])
|
||||
{
|
||||
items.AddRange(ConvertMachineFromInternalModel(machine));
|
||||
}
|
||||
|
||||
metadataFile.Row = [.. items];
|
||||
|
||||
return metadataFile;
|
||||
}
|
||||
@@ -33,13 +33,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
private static Row[] ConvertMachineFromInternalModel(Models.Metadata.Machine item)
|
||||
{
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms == null || !roms.Any())
|
||||
if (roms == null || roms.Length == 0)
|
||||
return [];
|
||||
|
||||
return roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
return Array.ConvertAll(roms, ConvertFromInternalModel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.EverdriveSMDB;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,12 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(),
|
||||
};
|
||||
|
||||
if (obj?.Row != null && obj.Row.Any())
|
||||
if (obj?.Row != null && obj.Row.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = obj.Row
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(obj.Row, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.Models.Hashfile;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
@@ -18,12 +18,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
return null;
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines == null || !machines.Any())
|
||||
if (machines == null || machines.Length == 0)
|
||||
return null;
|
||||
|
||||
var hashfiles = machines
|
||||
.Where(m => m != null)
|
||||
.Select(machine => ConvertMachineFromInternalModel(machine, hash));
|
||||
var hashfiles = Array.ConvertAll(machines, m => ConvertMachineFromInternalModel(m, hash));
|
||||
|
||||
var sfvs = new List<SFV>();
|
||||
var md5s = new List<MD5>();
|
||||
@@ -35,38 +33,38 @@ namespace SabreTools.Serialization.CrossModel
|
||||
|
||||
foreach (var hashfile in hashfiles)
|
||||
{
|
||||
if (hashfile.SFV != null && hashfile.SFV.Any())
|
||||
if (hashfile.SFV != null && hashfile.SFV.Length > 0)
|
||||
sfvs.AddRange(hashfile.SFV);
|
||||
if (hashfile.MD5 != null && hashfile.MD5.Any())
|
||||
if (hashfile.MD5 != null && hashfile.MD5.Length > 0)
|
||||
md5s.AddRange(hashfile.MD5);
|
||||
if (hashfile.SHA1 != null && hashfile.SHA1.Any())
|
||||
if (hashfile.SHA1 != null && hashfile.SHA1.Length > 0)
|
||||
sha1s.AddRange(hashfile.SHA1);
|
||||
if (hashfile.SHA256 != null && hashfile.SHA256.Any())
|
||||
if (hashfile.SHA256 != null && hashfile.SHA256.Length > 0)
|
||||
sha256s.AddRange(hashfile.SHA256);
|
||||
if (hashfile.SHA384 != null && hashfile.SHA384.Any())
|
||||
if (hashfile.SHA384 != null && hashfile.SHA384.Length > 0)
|
||||
sha384s.AddRange(hashfile.SHA384);
|
||||
if (hashfile.SHA512 != null && hashfile.SHA512.Any())
|
||||
if (hashfile.SHA512 != null && hashfile.SHA512.Length > 0)
|
||||
sha512s.AddRange(hashfile.SHA512);
|
||||
if (hashfile.SpamSum != null && hashfile.SpamSum.Any())
|
||||
if (hashfile.SpamSum != null && hashfile.SpamSum.Length > 0)
|
||||
spamsums.AddRange(hashfile.SpamSum);
|
||||
}
|
||||
|
||||
var hashfileItem = new Models.Hashfile.Hashfile();
|
||||
|
||||
if (sfvs.Any())
|
||||
hashfileItem.SFV = sfvs.ToArray();
|
||||
if (md5s.Any())
|
||||
hashfileItem.MD5 = md5s.ToArray();
|
||||
if (sha1s.Any())
|
||||
hashfileItem.SHA1 = sha1s.ToArray();
|
||||
if (sha256s.Any())
|
||||
hashfileItem.SHA256 = sha256s.ToArray();
|
||||
if (sha384s.Any())
|
||||
hashfileItem.SHA384 = sha384s.ToArray();
|
||||
if (sha512s.Any())
|
||||
hashfileItem.SHA512 = sha512s.ToArray();
|
||||
if (spamsums.Any())
|
||||
hashfileItem.SpamSum = spamsums.ToArray();
|
||||
if (sfvs.Count > 0)
|
||||
hashfileItem.SFV = [.. sfvs];
|
||||
if (md5s.Count > 0)
|
||||
hashfileItem.MD5 = [.. md5s];
|
||||
if (sha1s.Count > 0)
|
||||
hashfileItem.SHA1 = [.. sha1s];
|
||||
if (sha256s.Count > 0)
|
||||
hashfileItem.SHA256 = [.. sha256s];
|
||||
if (sha384s.Count > 0)
|
||||
hashfileItem.SHA384 = [.. sha384s];
|
||||
if (sha512s.Count > 0)
|
||||
hashfileItem.SHA512 = [.. sha512s];
|
||||
if (spamsums.Count > 0)
|
||||
hashfileItem.SpamSum = [.. spamsums];
|
||||
|
||||
return hashfileItem;
|
||||
}
|
||||
@@ -80,13 +78,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
return null;
|
||||
|
||||
var machines = item.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
return machines
|
||||
.Where(m => m != null)
|
||||
.Select(machine => ConvertMachineFromInternalModel(machine, hash))
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
return Array.ConvertAll(machines, m => ConvertMachineFromInternalModel(m, hash));
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -102,47 +95,26 @@ namespace SabreTools.Serialization.CrossModel
|
||||
|
||||
return new Models.Hashfile.Hashfile
|
||||
{
|
||||
SFV = hash == HashType.CRC32 || hash == HashType.CRC32_ISO || hash == HashType.CRC32_Naive || hash == HashType.CRC32_Optimized || hash == HashType.CRC32_Parallel
|
||||
? roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToSFV)
|
||||
.ToArray()
|
||||
SFV = hash == HashType.CRC32
|
||||
? Array.ConvertAll(roms, ConvertToSFV)
|
||||
: null,
|
||||
MD5 = hash == HashType.MD5
|
||||
? roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToMD5)
|
||||
.ToArray()
|
||||
? Array.ConvertAll(roms, ConvertToMD5)
|
||||
: null,
|
||||
SHA1 = hash == HashType.SHA1
|
||||
? roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToSHA1)
|
||||
.ToArray()
|
||||
? Array.ConvertAll(roms, ConvertToSHA1)
|
||||
: null,
|
||||
SHA256 = hash == HashType.SHA256
|
||||
? roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToSHA256)
|
||||
.ToArray()
|
||||
? Array.ConvertAll(roms, ConvertToSHA256)
|
||||
: null,
|
||||
SHA384 = hash == HashType.SHA384
|
||||
? roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToSHA384)
|
||||
.ToArray()
|
||||
? Array.ConvertAll(roms, ConvertToSHA384)
|
||||
: null,
|
||||
SHA512 = hash == HashType.SHA512
|
||||
? roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToSHA512)
|
||||
.ToArray()
|
||||
? Array.ConvertAll(roms, ConvertToSHA512)
|
||||
: null,
|
||||
SpamSum = hash == HashType.SpamSum
|
||||
? roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToSpamSum)
|
||||
.ToArray()
|
||||
? Array.ConvertAll(roms, ConvertToSpamSum)
|
||||
: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.Hashfile;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -42,20 +42,20 @@ namespace SabreTools.Serialization.CrossModel
|
||||
{
|
||||
var machine = new Models.Metadata.Machine();
|
||||
|
||||
if (item.SFV != null && item.SFV.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.SFV.Select(ConvertToInternalModel).ToArray();
|
||||
else if (item.MD5 != null && item.MD5.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.MD5.Select(ConvertToInternalModel).ToArray();
|
||||
else if (item.SHA1 != null && item.SHA1.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.SHA1.Select(ConvertToInternalModel).ToArray();
|
||||
else if (item.SHA256 != null && item.SHA256.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.SHA256.Select(ConvertToInternalModel).ToArray();
|
||||
else if (item.SHA384 != null && item.SHA384.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.SHA384.Select(ConvertToInternalModel).ToArray();
|
||||
else if (item.SHA512 != null && item.SHA512.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.SHA512.Select(ConvertToInternalModel).ToArray();
|
||||
else if (item.SpamSum != null && item.SpamSum.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.SpamSum.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.SFV != null && item.SFV.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.SFV, ConvertToInternalModel);
|
||||
else if (item.MD5 != null && item.MD5.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.MD5, ConvertToInternalModel);
|
||||
else if (item.SHA1 != null && item.SHA1.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.SHA1, ConvertToInternalModel);
|
||||
else if (item.SHA256 != null && item.SHA256.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.SHA256, ConvertToInternalModel);
|
||||
else if (item.SHA384 != null && item.SHA384.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.SHA384, ConvertToInternalModel);
|
||||
else if (item.SHA512 != null && item.SHA512.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.SHA512, ConvertToInternalModel);
|
||||
else if (item.SpamSum != null && item.SpamSum.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.SpamSum, ConvertToInternalModel);
|
||||
|
||||
return machine;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Listrom;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -16,13 +16,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var metadataFile = new MetadataFile();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
metadataFile.Set = machines
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
metadataFile.Set = Array.ConvertAll(machines, ConvertMachineFromInternalModel);
|
||||
|
||||
return metadataFile;
|
||||
}
|
||||
@@ -43,14 +38,14 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms != null)
|
||||
{
|
||||
rowItems.AddRange(roms.Where(r => r != null).Select(ConvertFromInternalModel));
|
||||
rowItems.AddRange(Array.ConvertAll(roms, ConvertFromInternalModel));
|
||||
}
|
||||
|
||||
var disks = item.Read<Models.Metadata.Disk[]>(Models.Metadata.Machine.DiskKey);
|
||||
if (disks != null)
|
||||
rowItems.AddRange(disks.Where(d => d != null).Select(ConvertFromInternalModel));
|
||||
rowItems.AddRange(Array.ConvertAll(disks, ConvertFromInternalModel));
|
||||
|
||||
set.Row = rowItems.ToArray();
|
||||
set.Row = [.. rowItems];
|
||||
return set;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Listrom;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -18,12 +18,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(),
|
||||
};
|
||||
|
||||
if (obj?.Set != null && obj.Set.Any())
|
||||
if (obj?.Set != null && obj.Set.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = obj.Set
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(obj.Set, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -57,16 +55,21 @@ namespace SabreTools.Serialization.CrossModel
|
||||
machine[Models.Metadata.Machine.NameKey] = item.Driver;
|
||||
}
|
||||
|
||||
if (item.Row != null && item.Row.Any())
|
||||
if (item.Row != null && item.Row.Length > 0)
|
||||
{
|
||||
var datItems = new List<Models.Metadata.DatItem>();
|
||||
var disks = new List<Models.Metadata.Disk>();
|
||||
var roms = new List<Models.Metadata.Rom>();
|
||||
foreach (var file in item.Row)
|
||||
{
|
||||
datItems.Add(ConvertToInternalModel(file));
|
||||
var datItem = ConvertToInternalModel(file);
|
||||
if (datItem is Models.Metadata.Disk disk)
|
||||
disks.Add(disk);
|
||||
else if (datItem is Models.Metadata.Rom rom)
|
||||
roms.Add(rom);
|
||||
}
|
||||
|
||||
machine[Models.Metadata.Machine.DiskKey] = datItems.Where(i => i.ReadString(Models.Metadata.DatItem.TypeKey) == "disk").Select(d => d as Models.Metadata.Disk).ToArray();
|
||||
machine[Models.Metadata.Machine.RomKey] = datItems.Where(i => i.ReadString(Models.Metadata.DatItem.TypeKey) == "rom").Select(d => d as Models.Metadata.Rom).ToArray();
|
||||
machine[Models.Metadata.Machine.DiskKey] = disks.ToArray();
|
||||
machine[Models.Metadata.Machine.RomKey] = roms.ToArray();
|
||||
}
|
||||
|
||||
return machine;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.Listxml;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -16,13 +16,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var mame = header != null ? ConvertMameFromInternalModel(header) : new Mame();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
mame.Game = machines
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
mame.Game = Array.ConvertAll(machines, ConvertMachineFromInternalModel);
|
||||
|
||||
return mame;
|
||||
}
|
||||
@@ -39,13 +34,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var mame = header != null ? ConvertMameFromInternalModel(header) : new Mame();
|
||||
|
||||
var machines = item.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
mame.Game = machines
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
mame.Game = Array.ConvertAll(machines, ConvertMachineFromInternalModel);
|
||||
|
||||
return mame;
|
||||
}
|
||||
@@ -88,76 +78,36 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var biosSets = item.Read<Models.Metadata.BiosSet[]>(Models.Metadata.Machine.BiosSetKey);
|
||||
if (biosSets != null && biosSets.Any())
|
||||
{
|
||||
machine.BiosSet = biosSets
|
||||
.Where(b => b != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (biosSets != null && biosSets.Length > 0)
|
||||
machine.BiosSet = Array.ConvertAll(biosSets, ConvertFromInternalModel);
|
||||
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms != null && roms.Any())
|
||||
{
|
||||
machine.Rom = roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (roms != null && roms.Length > 0)
|
||||
machine.Rom = Array.ConvertAll(roms, ConvertFromInternalModel);
|
||||
|
||||
var disks = item.Read<Models.Metadata.Disk[]>(Models.Metadata.Machine.DiskKey);
|
||||
if (disks != null && disks.Any())
|
||||
{
|
||||
machine.Disk = disks
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (disks != null && disks.Length > 0)
|
||||
machine.Disk = Array.ConvertAll(disks, ConvertFromInternalModel);
|
||||
|
||||
var deviceRefs = item.Read<Models.Metadata.DeviceRef[]>(Models.Metadata.Machine.DeviceRefKey);
|
||||
if (deviceRefs != null && deviceRefs.Any())
|
||||
{
|
||||
machine.DeviceRef = deviceRefs
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (deviceRefs != null && deviceRefs.Length > 0)
|
||||
machine.DeviceRef = Array.ConvertAll(deviceRefs, ConvertFromInternalModel);
|
||||
|
||||
var samples = item.Read<Models.Metadata.Sample[]>(Models.Metadata.Machine.SampleKey);
|
||||
if (samples != null && samples.Any())
|
||||
{
|
||||
machine.Sample = samples
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (samples != null && samples.Length > 0)
|
||||
machine.Sample = Array.ConvertAll(samples, ConvertFromInternalModel);
|
||||
|
||||
var chips = item.Read<Models.Metadata.Chip[]>(Models.Metadata.Machine.ChipKey);
|
||||
if (chips != null && chips.Any())
|
||||
{
|
||||
machine.Chip = chips
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (chips != null && chips.Length > 0)
|
||||
machine.Chip = Array.ConvertAll(chips, ConvertFromInternalModel);
|
||||
|
||||
var displays = item.Read<Models.Metadata.Display[]>(Models.Metadata.Machine.DisplayKey);
|
||||
if (displays != null && displays.Any())
|
||||
{
|
||||
machine.Display = displays
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (displays != null && displays.Length > 0)
|
||||
machine.Display = Array.ConvertAll(displays, ConvertFromInternalModel);
|
||||
|
||||
var videos = item.Read<Models.Metadata.Video[]>(Models.Metadata.Machine.VideoKey);
|
||||
if (videos != null && videos.Any())
|
||||
{
|
||||
machine.Video = videos
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (videos != null && videos.Length > 0)
|
||||
machine.Video = Array.ConvertAll(videos, ConvertFromInternalModel);
|
||||
|
||||
var sound = item.Read<Models.Metadata.Sound>(Models.Metadata.Machine.SoundKey);
|
||||
if (sound != null)
|
||||
@@ -168,89 +118,44 @@ namespace SabreTools.Serialization.CrossModel
|
||||
machine.Input = ConvertFromInternalModel(input);
|
||||
|
||||
var dipSwitches = item.Read<Models.Metadata.DipSwitch[]>(Models.Metadata.Machine.DipSwitchKey);
|
||||
if (dipSwitches != null && dipSwitches.Any())
|
||||
{
|
||||
machine.DipSwitch = dipSwitches
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dipSwitches != null && dipSwitches.Length > 0)
|
||||
machine.DipSwitch = Array.ConvertAll(dipSwitches, ConvertFromInternalModel);
|
||||
|
||||
var configurations = item.Read<Models.Metadata.Configuration[]>(Models.Metadata.Machine.ConfigurationKey);
|
||||
if (configurations != null && configurations.Any())
|
||||
{
|
||||
machine.Configuration = configurations
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (configurations != null && configurations.Length > 0)
|
||||
machine.Configuration = Array.ConvertAll(configurations, ConvertFromInternalModel);
|
||||
|
||||
var ports = item.Read<Models.Metadata.Port[]>(Models.Metadata.Machine.PortKey);
|
||||
if (ports != null && ports.Any())
|
||||
{
|
||||
machine.Port = ports
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (ports != null && ports.Length > 0)
|
||||
machine.Port = Array.ConvertAll(ports, ConvertFromInternalModel);
|
||||
|
||||
var adjusters = item.Read<Models.Metadata.Adjuster[]>(Models.Metadata.Machine.AdjusterKey);
|
||||
if (adjusters != null && adjusters.Any())
|
||||
{
|
||||
machine.Adjuster = adjusters
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (adjusters != null && adjusters.Length > 0)
|
||||
machine.Adjuster = Array.ConvertAll(adjusters, ConvertFromInternalModel);
|
||||
|
||||
var driver = item.Read<Models.Metadata.Driver>(Models.Metadata.Machine.DriverKey);
|
||||
if (driver != null)
|
||||
machine.Driver = ConvertFromInternalModel(driver);
|
||||
|
||||
var features = item.Read<Models.Metadata.Feature[]>(Models.Metadata.Machine.FeatureKey);
|
||||
if (features != null && features.Any())
|
||||
{
|
||||
machine.Feature = features
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (features != null && features.Length > 0)
|
||||
machine.Feature = Array.ConvertAll(features, ConvertFromInternalModel);
|
||||
|
||||
var devices = item.Read<Models.Metadata.Device[]>(Models.Metadata.Machine.DeviceKey);
|
||||
if (devices != null && devices.Any())
|
||||
{
|
||||
machine.Device = devices
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (devices != null && devices.Length > 0)
|
||||
machine.Device = Array.ConvertAll(devices, ConvertFromInternalModel);
|
||||
|
||||
var slots = item.Read<Models.Metadata.Slot[]>(Models.Metadata.Machine.SlotKey);
|
||||
if (slots != null && slots.Any())
|
||||
{
|
||||
machine.Slot = slots
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (slots != null && slots.Length > 0)
|
||||
machine.Slot = Array.ConvertAll(slots, ConvertFromInternalModel);
|
||||
|
||||
var softwareLists = item.Read<Models.Metadata.SoftwareList[]>(Models.Metadata.Machine.SoftwareListKey);
|
||||
if (softwareLists != null && softwareLists.Any())
|
||||
{
|
||||
machine.SoftwareList = softwareLists
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (softwareLists != null && softwareLists.Length > 0)
|
||||
machine.SoftwareList = Array.ConvertAll(softwareLists, ConvertFromInternalModel);
|
||||
|
||||
var ramOptions = item.Read<Models.Metadata.RamOption[]>(Models.Metadata.Machine.RamOptionKey);
|
||||
if (ramOptions != null && ramOptions.Any())
|
||||
{
|
||||
machine.RamOption = ramOptions
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (ramOptions != null && ramOptions.Length > 0)
|
||||
machine.RamOption = Array.ConvertAll(ramOptions, ConvertFromInternalModel);
|
||||
|
||||
return machine;
|
||||
}
|
||||
@@ -347,22 +252,12 @@ namespace SabreTools.Serialization.CrossModel
|
||||
configuration.Condition = ConvertFromInternalModel(condition);
|
||||
|
||||
var confLocations = item.Read<Models.Metadata.ConfLocation[]>(Models.Metadata.Configuration.ConfLocationKey);
|
||||
if (confLocations != null && confLocations.Any())
|
||||
{
|
||||
configuration.ConfLocation = confLocations
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (confLocations != null && confLocations.Length > 0)
|
||||
configuration.ConfLocation = Array.ConvertAll(confLocations, ConvertFromInternalModel);
|
||||
|
||||
var confSettings = item.Read<Models.Metadata.ConfSetting[]>(Models.Metadata.Configuration.ConfSettingKey);
|
||||
if (confSettings != null && confSettings.Any())
|
||||
{
|
||||
configuration.ConfSetting = confSettings
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (confSettings != null && confSettings.Length > 0)
|
||||
configuration.ConfSetting = Array.ConvertAll(confSettings, ConvertFromInternalModel);
|
||||
|
||||
return configuration;
|
||||
}
|
||||
@@ -442,13 +337,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
device.Instance = ConvertFromInternalModel(instance);
|
||||
|
||||
var extensions = item.Read<Models.Metadata.Extension[]>(Models.Metadata.Device.ExtensionKey);
|
||||
if (extensions != null && extensions.Any())
|
||||
{
|
||||
device.Extension = extensions
|
||||
.Where(e => e != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (extensions != null && extensions.Length > 0)
|
||||
device.Extension = Array.ConvertAll(extensions, ConvertFromInternalModel);
|
||||
|
||||
return device;
|
||||
}
|
||||
@@ -496,22 +386,12 @@ namespace SabreTools.Serialization.CrossModel
|
||||
dipSwitch.Condition = ConvertFromInternalModel(condition);
|
||||
|
||||
var dipLocations = item.Read<Models.Metadata.DipLocation[]>(Models.Metadata.DipSwitch.DipLocationKey);
|
||||
if (dipLocations != null && dipLocations.Any())
|
||||
{
|
||||
dipSwitch.DipLocation = dipLocations
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dipLocations != null && dipLocations.Length > 0)
|
||||
dipSwitch.DipLocation = Array.ConvertAll(dipLocations, ConvertFromInternalModel);
|
||||
|
||||
var dipValues = item.Read<Models.Metadata.DipValue[]>(Models.Metadata.DipSwitch.DipValueKey);
|
||||
if (dipValues != null && dipValues.Any())
|
||||
{
|
||||
dipSwitch.DipValue = dipValues
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dipValues != null && dipValues.Length > 0)
|
||||
dipSwitch.DipValue = Array.ConvertAll(dipValues, ConvertFromInternalModel);
|
||||
|
||||
return dipSwitch;
|
||||
}
|
||||
@@ -644,13 +524,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var controls = item.Read<Models.Metadata.Control[]>(Models.Metadata.Input.ControlKey);
|
||||
if (controls != null && controls.Any())
|
||||
{
|
||||
input.Control = controls
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (controls != null && controls.Length > 0)
|
||||
input.Control = Array.ConvertAll(controls, ConvertFromInternalModel);
|
||||
|
||||
return input;
|
||||
}
|
||||
@@ -679,13 +554,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var analogs = item.Read<Models.Metadata.Analog[]>(Models.Metadata.Port.AnalogKey);
|
||||
if (analogs != null && analogs.Any())
|
||||
{
|
||||
port.Analog = analogs
|
||||
.Where(a => a != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (analogs != null && analogs.Length > 0)
|
||||
port.Analog = Array.ConvertAll(analogs, ConvertFromInternalModel);
|
||||
|
||||
return port;
|
||||
}
|
||||
@@ -750,13 +620,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var slotOptions = item.Read<Models.Metadata.SlotOption[]>(Models.Metadata.Slot.SlotOptionKey);
|
||||
if (slotOptions != null && slotOptions.Any())
|
||||
{
|
||||
slot.SlotOption = slotOptions
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (slotOptions != null && slotOptions.Length > 0)
|
||||
slot.SlotOption = Array.ConvertAll(slotOptions, ConvertFromInternalModel);
|
||||
|
||||
return slot;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.Listxml;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,12 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item),
|
||||
};
|
||||
|
||||
if (item?.Game != null && item.Game.Any())
|
||||
if (item?.Game != null && item.Game.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = item.Game
|
||||
.Where(g => g != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(item.Game, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -64,68 +62,52 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Machine.HistoryKey] = item.History,
|
||||
};
|
||||
|
||||
if (item.BiosSet != null && item.BiosSet.Any())
|
||||
if (item.BiosSet != null && item.BiosSet.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.BiosSetKey] = item.BiosSet
|
||||
.Where(b => b != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.BiosSetKey]
|
||||
= Array.ConvertAll(item.BiosSet, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Rom != null && item.Rom.Any())
|
||||
if (item.Rom != null && item.Rom.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.RomKey] = item.Rom
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.RomKey]
|
||||
= Array.ConvertAll(item.Rom, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Disk != null && item.Disk.Any())
|
||||
if (item.Disk != null && item.Disk.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DiskKey] = item.Disk
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DiskKey]
|
||||
= Array.ConvertAll(item.Disk, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.DeviceRef != null && item.DeviceRef.Any())
|
||||
if (item.DeviceRef != null && item.DeviceRef.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DeviceRefKey] = item.DeviceRef
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DeviceRefKey]
|
||||
= Array.ConvertAll(item.DeviceRef, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Sample != null && item.Sample.Any())
|
||||
if (item.Sample != null && item.Sample.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.SampleKey] = item.Sample
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.SampleKey]
|
||||
= Array.ConvertAll(item.Sample, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Chip != null && item.Chip.Any())
|
||||
if (item.Chip != null && item.Chip.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.ChipKey] = item.Chip
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.ChipKey]
|
||||
= Array.ConvertAll(item.Chip, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Display != null && item.Display.Any())
|
||||
if (item.Display != null && item.Display.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DisplayKey] = item.Display
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DisplayKey]
|
||||
= Array.ConvertAll(item.Display, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Video != null && item.Video.Any())
|
||||
if (item.Video != null && item.Video.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.VideoKey] = item.Video
|
||||
.Where(v => v != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.VideoKey]
|
||||
= Array.ConvertAll(item.Video, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Sound != null)
|
||||
@@ -134,79 +116,61 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (item.Input != null)
|
||||
machine[Models.Metadata.Machine.InputKey] = ConvertToInternalModel(item.Input);
|
||||
|
||||
if (item.DipSwitch != null && item.DipSwitch.Any())
|
||||
if (item.DipSwitch != null && item.DipSwitch.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DipSwitchKey] = item.DipSwitch
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DipSwitchKey]
|
||||
= Array.ConvertAll(item.DipSwitch, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Configuration != null && item.Configuration.Any())
|
||||
if (item.Configuration != null && item.Configuration.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.ConfigurationKey] = item.Configuration
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.ConfigurationKey]
|
||||
= Array.ConvertAll(item.Configuration, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Port != null && item.Port.Any())
|
||||
if (item.Port != null && item.Port.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.PortKey] = item.Port
|
||||
.Where(p => p != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.PortKey]
|
||||
= Array.ConvertAll(item.Port, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Adjuster != null && item.Adjuster.Any())
|
||||
if (item.Adjuster != null && item.Adjuster.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.AdjusterKey] = item.Adjuster
|
||||
.Where(a => a != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.AdjusterKey]
|
||||
= Array.ConvertAll(item.Adjuster, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Driver != null)
|
||||
machine[Models.Metadata.Machine.DriverKey] = ConvertToInternalModel(item.Driver);
|
||||
|
||||
if (item.Feature != null && item.Feature.Any())
|
||||
if (item.Feature != null && item.Feature.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.FeatureKey] = item.Feature
|
||||
.Where(f => f != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.FeatureKey]
|
||||
= Array.ConvertAll(item.Feature, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Device != null && item.Device.Any())
|
||||
if (item.Device != null && item.Device.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DeviceKey] = item.Device
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DeviceKey]
|
||||
= Array.ConvertAll(item.Device, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.Slot != null && item.Slot.Any())
|
||||
if (item.Slot != null && item.Slot.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.SlotKey] = item.Slot
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.SlotKey]
|
||||
= Array.ConvertAll(item.Slot, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.SoftwareList != null && item.SoftwareList.Any())
|
||||
if (item.SoftwareList != null && item.SoftwareList.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.SoftwareListKey] = item.SoftwareList
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.SoftwareListKey]
|
||||
= Array.ConvertAll(item.SoftwareList, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.RamOption != null && item.RamOption.Any())
|
||||
if (item.RamOption != null && item.RamOption.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.RamOptionKey] = item.RamOption
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.RamOptionKey]
|
||||
= Array.ConvertAll(item.RamOption, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return machine;
|
||||
@@ -301,20 +265,16 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (item.Condition != null)
|
||||
configuration[Models.Metadata.Configuration.ConditionKey] = ConvertToInternalModel(item.Condition);
|
||||
|
||||
if (item.ConfLocation != null && item.ConfLocation.Any())
|
||||
if (item.ConfLocation != null && item.ConfLocation.Length > 0)
|
||||
{
|
||||
configuration[Models.Metadata.Configuration.ConfLocationKey] = item.ConfLocation
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
configuration[Models.Metadata.Configuration.ConfLocationKey]
|
||||
= Array.ConvertAll(item.ConfLocation, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.ConfSetting != null && item.ConfSetting.Any())
|
||||
if (item.ConfSetting != null && item.ConfSetting.Length > 0)
|
||||
{
|
||||
configuration[Models.Metadata.Configuration.ConfSettingKey] = item.ConfSetting
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
configuration[Models.Metadata.Configuration.ConfSettingKey]
|
||||
= Array.ConvertAll(item.ConfSetting, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return configuration;
|
||||
@@ -392,12 +352,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (item.Instance != null)
|
||||
device[Models.Metadata.Device.InstanceKey] = ConvertToInternalModel(item.Instance);
|
||||
|
||||
if (item.Extension != null && item.Extension.Any())
|
||||
if (item.Extension != null && item.Extension.Length > 0)
|
||||
{
|
||||
device[Models.Metadata.Device.ExtensionKey] = item.Extension
|
||||
.Where(e => e != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
device[Models.Metadata.Device.ExtensionKey]
|
||||
= Array.ConvertAll(item.Extension, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return device;
|
||||
@@ -444,20 +402,16 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (item.Condition != null)
|
||||
dipSwitch[Models.Metadata.DipSwitch.ConditionKey] = ConvertToInternalModel(item.Condition);
|
||||
|
||||
if (item.DipLocation != null && item.DipLocation.Any())
|
||||
if (item.DipLocation != null && item.DipLocation.Length > 0)
|
||||
{
|
||||
dipSwitch[Models.Metadata.DipSwitch.DipLocationKey] = item.DipLocation
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
dipSwitch[Models.Metadata.DipSwitch.DipLocationKey]
|
||||
= Array.ConvertAll(item.DipLocation, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
if (item.DipValue != null && item.DipValue.Any())
|
||||
if (item.DipValue != null && item.DipValue.Length > 0)
|
||||
{
|
||||
dipSwitch[Models.Metadata.DipSwitch.DipValueKey] = item.DipValue
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
dipSwitch[Models.Metadata.DipSwitch.DipValueKey]
|
||||
= Array.ConvertAll(item.DipValue, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return dipSwitch;
|
||||
@@ -589,12 +543,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Input.CoinsKey] = item.Coins,
|
||||
};
|
||||
|
||||
if (item.Control != null && item.Control.Any())
|
||||
if (item.Control != null && item.Control.Length > 0)
|
||||
{
|
||||
input[Models.Metadata.Input.ControlKey] = item.Control
|
||||
.Where(c => c != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
input[Models.Metadata.Input.ControlKey]
|
||||
= Array.ConvertAll(item.Control, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return input;
|
||||
@@ -623,12 +575,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Port.TagKey] = item.Tag,
|
||||
};
|
||||
|
||||
if (item.Analog != null && item.Analog.Any())
|
||||
if (item.Analog != null && item.Analog.Length > 0)
|
||||
{
|
||||
port[Models.Metadata.Port.AnalogKey] = item.Analog
|
||||
.Where(a => a != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
port[Models.Metadata.Port.AnalogKey]
|
||||
= Array.ConvertAll(item.Analog, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return port;
|
||||
@@ -693,12 +643,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Slot.NameKey] = item.Name,
|
||||
};
|
||||
|
||||
if (item.SlotOption != null && item.SlotOption.Any())
|
||||
if (item.SlotOption != null && item.SlotOption.Length > 0)
|
||||
{
|
||||
slot[Models.Metadata.Slot.SlotOptionKey] = item.SlotOption
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
slot[Models.Metadata.Slot.SlotOptionKey]
|
||||
= Array.ConvertAll(item.SlotOption, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return slot;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -28,13 +28,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
|
||||
// TODO: Handle Dir items - Currently need to be generated from the machines
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
datafile.Game = machines
|
||||
.Where(m => m != null)
|
||||
.Select(machine => ConvertMachineFromInternalModel(machine, game))
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
datafile.Game = Array.ConvertAll(machines, m => ConvertMachineFromInternalModel(m, game));
|
||||
|
||||
return datafile;
|
||||
}
|
||||
@@ -130,89 +125,44 @@ namespace SabreTools.Serialization.CrossModel
|
||||
gameBase.Trurip = trurip;
|
||||
|
||||
var releases = item.Read<Models.Metadata.Release[]>(Models.Metadata.Machine.ReleaseKey);
|
||||
if (releases != null && releases.Any())
|
||||
{
|
||||
gameBase.Release = releases
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (releases != null && releases.Length > 0)
|
||||
gameBase.Release = Array.ConvertAll(releases, ConvertFromInternalModel);
|
||||
|
||||
var biosSets = item.Read<Models.Metadata.BiosSet[]>(Models.Metadata.Machine.BiosSetKey);
|
||||
if (biosSets != null && biosSets.Any())
|
||||
{
|
||||
gameBase.BiosSet = biosSets
|
||||
.Where(b => b != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (biosSets != null && biosSets.Length > 0)
|
||||
gameBase.BiosSet = Array.ConvertAll(biosSets, ConvertFromInternalModel);
|
||||
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms != null && roms.Any())
|
||||
{
|
||||
gameBase.Rom = roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (roms != null && roms.Length > 0)
|
||||
gameBase.Rom = Array.ConvertAll(roms, ConvertFromInternalModel);
|
||||
|
||||
var disks = item.Read<Models.Metadata.Disk[]>(Models.Metadata.Machine.DiskKey);
|
||||
if (disks != null && disks.Any())
|
||||
{
|
||||
gameBase.Disk = disks
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (disks != null && disks.Length > 0)
|
||||
gameBase.Disk = Array.ConvertAll(disks, ConvertFromInternalModel);
|
||||
|
||||
var medias = item.Read<Models.Metadata.Media[]>(Models.Metadata.Machine.MediaKey);
|
||||
if (medias != null && medias.Any())
|
||||
{
|
||||
gameBase.Media = medias
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (medias != null && medias.Length > 0)
|
||||
gameBase.Media = Array.ConvertAll(medias, ConvertFromInternalModel);
|
||||
|
||||
var deviceRefs = item.Read<Models.Metadata.DeviceRef[]>(Models.Metadata.Machine.DeviceRefKey);
|
||||
if (deviceRefs != null && deviceRefs.Any())
|
||||
{
|
||||
gameBase.DeviceRef = deviceRefs
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (deviceRefs != null && deviceRefs.Length > 0)
|
||||
gameBase.DeviceRef = Array.ConvertAll(deviceRefs, ConvertFromInternalModel);
|
||||
|
||||
var samples = item.Read<Models.Metadata.Sample[]>(Models.Metadata.Machine.SampleKey);
|
||||
if (samples != null && samples.Any())
|
||||
{
|
||||
gameBase.Sample = samples
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (samples != null && samples.Length > 0)
|
||||
gameBase.Sample = Array.ConvertAll(samples, ConvertFromInternalModel);
|
||||
|
||||
var archives = item.Read<Models.Metadata.Archive[]>(Models.Metadata.Machine.ArchiveKey);
|
||||
if (archives != null && archives.Any())
|
||||
{
|
||||
gameBase.Archive = archives
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (archives != null && archives.Length > 0)
|
||||
gameBase.Archive = Array.ConvertAll(archives, ConvertFromInternalModel);
|
||||
|
||||
var driver = item.Read<Models.Metadata.Driver>(Models.Metadata.Machine.DriverKey);
|
||||
if (driver != null)
|
||||
gameBase.Driver = ConvertFromInternalModel(driver);
|
||||
|
||||
var softwareLists = item.Read<Models.Metadata.SoftwareList[]>(Models.Metadata.Machine.SoftwareListKey);
|
||||
if (softwareLists != null && softwareLists.Any())
|
||||
{
|
||||
gameBase.SoftwareList = softwareLists
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (softwareLists != null && softwareLists.Length > 0)
|
||||
gameBase.SoftwareList = Array.ConvertAll(softwareLists, ConvertFromInternalModel);
|
||||
|
||||
return gameBase;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.Logiqx;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -20,21 +19,15 @@ namespace SabreTools.Serialization.CrossModel
|
||||
|
||||
var machines = new List<Models.Metadata.Machine>();
|
||||
|
||||
if (item.Game != null && item.Game.Any())
|
||||
if (item.Game != null && item.Game.Length > 0)
|
||||
machines.AddRange(Array.ConvertAll(item.Game, ConvertMachineToInternalModel));
|
||||
|
||||
foreach (var dir in item.Dir ?? [])
|
||||
{
|
||||
machines.AddRange(item.Game
|
||||
.Where(g => g != null)
|
||||
.Select(ConvertMachineToInternalModel));
|
||||
machines.AddRange(ConvertDirToInternalModel(dir));
|
||||
}
|
||||
|
||||
if (item.Dir != null && item.Dir.Any())
|
||||
{
|
||||
machines.AddRange(item.Dir
|
||||
.Where(d => d != null)
|
||||
.SelectMany(ConvertDirToInternalModel));
|
||||
}
|
||||
|
||||
if (machines.Any())
|
||||
if (machines.Count > 0)
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = machines.ToArray();
|
||||
|
||||
return metadataFile;
|
||||
@@ -103,18 +96,15 @@ namespace SabreTools.Serialization.CrossModel
|
||||
/// </summary>
|
||||
private static Models.Metadata.Machine[] ConvertDirToInternalModel(Dir item)
|
||||
{
|
||||
if (item.Game == null || !item.Game.Any())
|
||||
if (item.Game == null || item.Game.Length == 0)
|
||||
return [];
|
||||
|
||||
return item.Game
|
||||
.Where(g => g != null)
|
||||
.Select(game =>
|
||||
return Array.ConvertAll(item.Game, g =>
|
||||
{
|
||||
var machine = ConvertMachineToInternalModel(game);
|
||||
var machine = ConvertMachineToInternalModel(g);
|
||||
machine[Models.Metadata.Machine.DirNameKey] = item.Name;
|
||||
return machine;
|
||||
})
|
||||
.ToArray();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -146,35 +136,35 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Machine.TruripKey] = item.Trurip,
|
||||
};
|
||||
|
||||
if (item.Release != null && item.Release.Any())
|
||||
machine[Models.Metadata.Machine.ReleaseKey] = item.Release.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Release != null && item.Release.Length > 0)
|
||||
machine[Models.Metadata.Machine.ReleaseKey] = Array.ConvertAll(item.Release, ConvertToInternalModel);
|
||||
|
||||
if (item.BiosSet != null && item.BiosSet.Any())
|
||||
machine[Models.Metadata.Machine.BiosSetKey] = item.BiosSet.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.BiosSet != null && item.BiosSet.Length > 0)
|
||||
machine[Models.Metadata.Machine.BiosSetKey] = Array.ConvertAll(item.BiosSet, ConvertToInternalModel);
|
||||
|
||||
if (item.Rom != null && item.Rom.Any())
|
||||
machine[Models.Metadata.Machine.RomKey] = item.Rom.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Rom != null && item.Rom.Length > 0)
|
||||
machine[Models.Metadata.Machine.RomKey] = Array.ConvertAll(item.Rom, ConvertToInternalModel);
|
||||
|
||||
if (item.Disk != null && item.Disk.Any())
|
||||
machine[Models.Metadata.Machine.DiskKey] = item.Disk.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Disk != null && item.Disk.Length > 0)
|
||||
machine[Models.Metadata.Machine.DiskKey] = Array.ConvertAll(item.Disk, ConvertToInternalModel);
|
||||
|
||||
if (item.Media != null && item.Media.Any())
|
||||
machine[Models.Metadata.Machine.MediaKey] = item.Media.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Media != null && item.Media.Length > 0)
|
||||
machine[Models.Metadata.Machine.MediaKey] = Array.ConvertAll(item.Media, ConvertToInternalModel);
|
||||
|
||||
if (item.DeviceRef != null && item.DeviceRef.Any())
|
||||
machine[Models.Metadata.Machine.DeviceRefKey] = item.DeviceRef.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.DeviceRef != null && item.DeviceRef.Length > 0)
|
||||
machine[Models.Metadata.Machine.DeviceRefKey] = Array.ConvertAll(item.DeviceRef, ConvertToInternalModel);
|
||||
|
||||
if (item.Sample != null && item.Sample.Any())
|
||||
machine[Models.Metadata.Machine.SampleKey] = item.Sample.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Sample != null && item.Sample.Length > 0)
|
||||
machine[Models.Metadata.Machine.SampleKey] = Array.ConvertAll(item.Sample, ConvertToInternalModel);
|
||||
|
||||
if (item.Archive != null && item.Archive.Any())
|
||||
machine[Models.Metadata.Machine.ArchiveKey] = item.Archive.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Archive != null && item.Archive.Length > 0)
|
||||
machine[Models.Metadata.Machine.ArchiveKey] = Array.ConvertAll(item.Archive, ConvertToInternalModel);
|
||||
|
||||
if (item.Driver != null)
|
||||
machine[Models.Metadata.Machine.DriverKey] = ConvertToInternalModel(item.Driver);
|
||||
|
||||
if (item.SoftwareList != null && item.SoftwareList.Any())
|
||||
machine[Models.Metadata.Machine.SoftwareListKey] = item.SoftwareList.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.SoftwareList != null && item.SoftwareList.Length > 0)
|
||||
machine[Models.Metadata.Machine.SoftwareListKey] = Array.ConvertAll(item.SoftwareList, ConvertToInternalModel);
|
||||
|
||||
return machine;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
@@ -15,13 +15,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var m1 = header != null ? ConvertM1FromInternalModel(header) : new Models.Listxml.M1();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
m1.Game = machines
|
||||
.Where(m => m != null)
|
||||
.Select(Listxml.ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
m1.Game = Array.ConvertAll(machines, Listxml.ConvertMachineFromInternalModel);
|
||||
|
||||
return m1;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.CrossModel
|
||||
@@ -16,12 +16,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item),
|
||||
};
|
||||
|
||||
if (item?.Game != null && item.Game.Any())
|
||||
if (item?.Game != null && item.Game.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = item.Game
|
||||
.Where(g => g != null)
|
||||
.Select(Listxml.ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(item.Game, Listxml.ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.OfflineList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -16,14 +16,11 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var dat = header != null ? ConvertHeaderFromInternalModel(header) : new Dat();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
if (machines != null && machines.Length > 0)
|
||||
{
|
||||
dat.Games = new Games
|
||||
{
|
||||
Game = machines
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertMachineFromInternalModel)
|
||||
.ToArray()
|
||||
Game = Array.ConvertAll(machines, ConvertMachineFromInternalModel),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -101,17 +98,12 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms != null && roms.Any())
|
||||
if (roms != null && roms.Length > 0)
|
||||
{
|
||||
game.RomSize = roms
|
||||
.Select(rom => rom.ReadString(Models.Metadata.Rom.SizeKey))
|
||||
.FirstOrDefault(s => s != null);
|
||||
|
||||
var romCRCs = roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
var romSizes = Array.ConvertAll(roms, r => r.ReadLong(Models.Metadata.Rom.SizeKey) ?? -1);
|
||||
game.RomSize = Array.Find(romSizes, s => s > -1).ToString();
|
||||
|
||||
var romCRCs = Array.ConvertAll(roms, ConvertFromInternalModel);;
|
||||
game.Files = new Models.OfflineList.Files { RomCRC = romCRCs };
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.OfflineList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,12 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item),
|
||||
};
|
||||
|
||||
if (item?.Games?.Game != null && item.Games.Game.Any())
|
||||
if (item?.Games?.Game != null && item.Games.Game.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = item.Games.Game
|
||||
.Where(g => g != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(item.Games.Game, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -82,17 +80,15 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Machine.DuplicateIDKey] = item.DuplicateID,
|
||||
};
|
||||
|
||||
if (item.Files?.RomCRC != null && item.Files.RomCRC.Any())
|
||||
if (item.Files?.RomCRC != null && item.Files.RomCRC.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.RomKey] = item.Files.RomCRC
|
||||
.Where(r => r != null)
|
||||
.Select(romCRC =>
|
||||
{
|
||||
var rom = ConvertToInternalModel(romCRC);
|
||||
rom[Models.Metadata.Rom.SizeKey] = item.RomSize;
|
||||
return rom;
|
||||
})
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.RomKey]
|
||||
= Array.ConvertAll(item.Files.RomCRC, romCRC =>
|
||||
{
|
||||
var rom = ConvertToInternalModel(romCRC);
|
||||
rom[Models.Metadata.Rom.SizeKey] = item.RomSize;
|
||||
return rom;
|
||||
});
|
||||
}
|
||||
|
||||
return machine;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.OpenMSX;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -16,13 +16,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var softwareDb = header != null ? ConvertHeaderFromInternalModel(header) : new SoftwareDb();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
softwareDb.Software = machines
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
softwareDb.Software = Array.ConvertAll(machines, ConvertMachineFromInternalModel);
|
||||
|
||||
return softwareDb;
|
||||
}
|
||||
@@ -55,13 +50,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var dumps = item.Read<Models.Metadata.Dump[]>(Models.Metadata.Machine.DumpKey);
|
||||
if (dumps != null && dumps.Any())
|
||||
{
|
||||
game.Dump = dumps
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dumps != null && dumps.Length > 0)
|
||||
game.Dump = Array.ConvertAll(dumps, ConvertFromInternalModel);
|
||||
|
||||
return game;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.OpenMSX;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,12 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item),
|
||||
};
|
||||
|
||||
if (item?.Software != null && item.Software.Any())
|
||||
if (item?.Software != null && item.Software.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = item.Software
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(item.Software, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -55,12 +53,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Machine.CountryKey] = item.Country,
|
||||
};
|
||||
|
||||
if (item.Dump != null && item.Dump.Any())
|
||||
if (item.Dump != null && item.Dump.Length > 0)
|
||||
{
|
||||
machine[Models.Metadata.Machine.DumpKey] = item.Dump
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertToInternalModel)
|
||||
.ToArray();
|
||||
machine[Models.Metadata.Machine.DumpKey]
|
||||
= Array.ConvertAll(item.Dump, ConvertToInternalModel);
|
||||
}
|
||||
|
||||
return machine;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using SabreTools.Models.RomCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,17 +17,13 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var metadataFile = header != null ? ConvertHeaderFromInternalModel(header) : new MetadataFile();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
var items = new List<Rom>();
|
||||
foreach (var machine in machines ?? [])
|
||||
{
|
||||
metadataFile.Games = new Games
|
||||
{
|
||||
Rom = machines
|
||||
.Where(m => m != null)
|
||||
.SelectMany(ConvertMachineFromInternalModel)
|
||||
.ToArray()
|
||||
};
|
||||
items.AddRange(ConvertMachineFromInternalModel(machine));
|
||||
}
|
||||
|
||||
metadataFile.Games = new Games { Rom = [.. items] };
|
||||
return metadataFile;
|
||||
}
|
||||
|
||||
@@ -93,10 +89,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
if (roms == null)
|
||||
return [];
|
||||
|
||||
return roms
|
||||
.Where(r => r != null)
|
||||
.Select(rom => ConvertFromInternalModel(rom, item))
|
||||
.ToArray();
|
||||
return Array.ConvertAll(roms, r => ConvertFromInternalModel(r, item));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.RomCenter;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,11 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(obj),
|
||||
};
|
||||
|
||||
if (obj?.Games?.Rom != null && obj.Games.Rom.Any())
|
||||
if (obj?.Games?.Rom != null && obj.Games.Rom.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = obj.Games.Rom
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertMachineToInternalModel).ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(obj.Games.Rom, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using SabreTools.Models.SeparatedValue;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,14 +17,13 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var metadataFile = header != null ? ConvertHeaderFromInternalModel(header) : new MetadataFile();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
var items = new List<Row>();
|
||||
foreach (var machine in machines ?? [])
|
||||
{
|
||||
metadataFile.Row = machines
|
||||
.Where(m => m != null)
|
||||
.SelectMany(m => ConvertMachineFromInternalModel(m, header))
|
||||
.ToArray();
|
||||
items.AddRange(ConvertMachineFromInternalModel(machine, header));
|
||||
}
|
||||
|
||||
metadataFile.Row = [.. items];
|
||||
return metadataFile;
|
||||
}
|
||||
|
||||
@@ -48,27 +47,24 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var rowItems = new List<Row>();
|
||||
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.Machine.RomKey);
|
||||
if (roms != null && roms.Any())
|
||||
if (roms != null && roms.Length > 0)
|
||||
{
|
||||
rowItems.AddRange(roms
|
||||
.Where(r => r != null)
|
||||
.Select(rom => ConvertFromInternalModel(rom, item, header)));
|
||||
rowItems.AddRange(
|
||||
Array.ConvertAll(roms, r => ConvertFromInternalModel(r, item, header)));
|
||||
}
|
||||
|
||||
var disks = item.Read<Models.Metadata.Disk[]>(Models.Metadata.Machine.DiskKey);
|
||||
if (disks != null && disks.Any())
|
||||
if (disks != null && disks.Length > 0)
|
||||
{
|
||||
rowItems.AddRange(disks
|
||||
.Where(d => d != null)
|
||||
.Select(disk => ConvertFromInternalModel(disk, item, header)));
|
||||
rowItems.AddRange(
|
||||
Array.ConvertAll(disks, d => ConvertFromInternalModel(d, item, header)));
|
||||
}
|
||||
|
||||
var media = item.Read<Models.Metadata.Media[]>(Models.Metadata.Machine.MediaKey);
|
||||
if (media != null && media.Any())
|
||||
if (media != null && media.Length > 0)
|
||||
{
|
||||
rowItems.AddRange(media
|
||||
.Where(m => m != null)
|
||||
.Select(medium => ConvertFromInternalModel(medium, item, header)));
|
||||
rowItems.AddRange(
|
||||
Array.ConvertAll(media, m => ConvertFromInternalModel(m, item, header)));
|
||||
}
|
||||
|
||||
return rowItems.ToArray();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.SeparatedValue;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,8 +17,11 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(obj),
|
||||
};
|
||||
|
||||
if (obj?.Row != null && obj.Row.Any())
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = obj.Row.Select(ConvertMachineToInternalModel).ToArray();
|
||||
if (obj?.Row != null && obj.Row.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(obj.Row, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
}
|
||||
@@ -33,7 +36,7 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Header.HeaderKey] = item.Header,
|
||||
};
|
||||
|
||||
if (item.Row != null && item.Row.Any())
|
||||
if (item.Row != null && item.Row.Length > 0)
|
||||
{
|
||||
var first = item.Row[0];
|
||||
//header[Models.Metadata.Header.FileNameKey] = first.FileName; // Not possible to map
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.SoftwareList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -16,13 +16,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
var metadataFile = header != null ? ConvertHeaderFromInternalModel(header) : new Models.SoftwareList.SoftwareList();
|
||||
|
||||
var machines = obj.Read<Models.Metadata.Machine[]>(Models.Metadata.MetadataFile.MachineKey);
|
||||
if (machines != null && machines.Any())
|
||||
{
|
||||
metadataFile.Software = machines
|
||||
.Where(m => m != null)
|
||||
.Select(ConvertMachineFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (machines != null && machines.Length > 0)
|
||||
metadataFile.Software = Array.ConvertAll(machines, ConvertMachineFromInternalModel);
|
||||
|
||||
return metadataFile;
|
||||
}
|
||||
@@ -58,31 +53,16 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var infos = item.Read<Models.Metadata.Info[]>(Models.Metadata.Machine.InfoKey);
|
||||
if (infos != null && infos.Any())
|
||||
{
|
||||
software.Info = infos
|
||||
.Where(i => i != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (infos != null && infos.Length > 0)
|
||||
software.Info = Array.ConvertAll(infos, ConvertFromInternalModel);
|
||||
|
||||
var sharedFeats = item.Read<Models.Metadata.SharedFeat[]>(Models.Metadata.Machine.SharedFeatKey);
|
||||
if (sharedFeats != null && sharedFeats.Any())
|
||||
{
|
||||
software.SharedFeat = sharedFeats
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (sharedFeats != null && sharedFeats.Length > 0)
|
||||
software.SharedFeat = Array.ConvertAll(sharedFeats, ConvertFromInternalModel);
|
||||
|
||||
var parts = item.Read<Models.Metadata.Part[]>(Models.Metadata.Machine.PartKey);
|
||||
if (parts != null && parts.Any())
|
||||
{
|
||||
software.Part = parts
|
||||
.Where(p => p != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (parts != null && parts.Length > 0)
|
||||
software.Part = Array.ConvertAll(parts, ConvertFromInternalModel);
|
||||
|
||||
return software;
|
||||
}
|
||||
@@ -101,13 +81,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var roms = item.Read<Models.Metadata.Rom[]>(Models.Metadata.DataArea.RomKey);
|
||||
if (roms != null && roms.Any())
|
||||
{
|
||||
dataArea.Rom = roms
|
||||
.Where(r => r != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (roms != null && roms.Length > 0)
|
||||
dataArea.Rom = Array.ConvertAll(roms,ConvertFromInternalModel);
|
||||
|
||||
return dataArea;
|
||||
}
|
||||
@@ -125,13 +100,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var dipValues = item.Read<Models.Metadata.DipValue[]>(Models.Metadata.DipSwitch.DipValueKey);
|
||||
if (dipValues != null && dipValues.Any())
|
||||
{
|
||||
dipSwitch.DipValue = dipValues
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dipValues != null && dipValues.Length > 0)
|
||||
dipSwitch.DipValue = Array.ConvertAll(dipValues, ConvertFromInternalModel);
|
||||
|
||||
return dipSwitch;
|
||||
}
|
||||
@@ -177,13 +147,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var disks = item.Read<Models.Metadata.Disk[]>(Models.Metadata.DiskArea.DiskKey);
|
||||
if (disks != null && disks.Any())
|
||||
{
|
||||
diskArea.Disk = disks
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (disks != null && disks.Length > 0)
|
||||
diskArea.Disk = Array.ConvertAll(disks, ConvertFromInternalModel);
|
||||
|
||||
return diskArea;
|
||||
}
|
||||
@@ -226,40 +191,20 @@ namespace SabreTools.Serialization.CrossModel
|
||||
};
|
||||
|
||||
var features = item.Read<Models.Metadata.Feature[]>(Models.Metadata.Part.FeatureKey);
|
||||
if (features != null && features.Any())
|
||||
{
|
||||
part.Feature = features
|
||||
.Where(f => f != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (features != null && features.Length > 0)
|
||||
part.Feature = Array.ConvertAll(features, ConvertFromInternalModel);
|
||||
|
||||
var dataAreas = item.Read<Models.Metadata.DataArea[]>(Models.Metadata.Part.DataAreaKey);
|
||||
if (dataAreas != null && dataAreas.Any())
|
||||
{
|
||||
part.DataArea = dataAreas
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dataAreas != null && dataAreas.Length > 0)
|
||||
part.DataArea = Array.ConvertAll(dataAreas, ConvertFromInternalModel);
|
||||
|
||||
var diskAreas = item.Read<Models.Metadata.DiskArea[]>(Models.Metadata.Part.DiskAreaKey);
|
||||
if (diskAreas != null && diskAreas.Any())
|
||||
{
|
||||
part.DiskArea = diskAreas
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (diskAreas != null && diskAreas.Length > 0)
|
||||
part.DiskArea = Array.ConvertAll(diskAreas, ConvertFromInternalModel);
|
||||
|
||||
var dipSwitches = item.Read<Models.Metadata.DipSwitch[]>(Models.Metadata.Part.DipSwitchKey);
|
||||
if (dipSwitches != null && dipSwitches.Any())
|
||||
{
|
||||
part.DipSwitch = dipSwitches
|
||||
.Where(d => d != null)
|
||||
.Select(ConvertFromInternalModel)
|
||||
.ToArray();
|
||||
}
|
||||
if (dipSwitches != null && dipSwitches.Length > 0)
|
||||
part.DipSwitch = Array.ConvertAll(dipSwitches, ConvertFromInternalModel);
|
||||
|
||||
return part;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Linq;
|
||||
using System;
|
||||
using SabreTools.Models.SoftwareList;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,12 +17,10 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.MetadataFile.HeaderKey] = ConvertHeaderToInternalModel(item),
|
||||
};
|
||||
|
||||
if (item?.Software != null && item.Software.Any())
|
||||
if (item?.Software != null && item.Software.Length > 0)
|
||||
{
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey] = item.Software
|
||||
.Where(s => s != null)
|
||||
.Select(ConvertMachineToInternalModel)
|
||||
.ToArray();
|
||||
metadataFile[Models.Metadata.MetadataFile.MachineKey]
|
||||
= Array.ConvertAll(item.Software, ConvertMachineToInternalModel);
|
||||
}
|
||||
|
||||
return metadataFile;
|
||||
@@ -58,14 +56,14 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Machine.NotesKey] = item.Notes,
|
||||
};
|
||||
|
||||
if (item.Info != null && item.Info.Any())
|
||||
machine[Models.Metadata.Machine.InfoKey] = item.Info.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Info != null && item.Info.Length > 0)
|
||||
machine[Models.Metadata.Machine.InfoKey] = Array.ConvertAll(item.Info, ConvertToInternalModel);
|
||||
|
||||
if (item.SharedFeat != null && item.SharedFeat.Any())
|
||||
machine[Models.Metadata.Machine.SharedFeatKey] = item.SharedFeat.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.SharedFeat != null && item.SharedFeat.Length > 0)
|
||||
machine[Models.Metadata.Machine.SharedFeatKey] = Array.ConvertAll(item.SharedFeat, ConvertToInternalModel);
|
||||
|
||||
if (item.Part != null && item.Part.Any())
|
||||
machine[Models.Metadata.Machine.PartKey] = item.Part.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Part != null && item.Part.Length > 0)
|
||||
machine[Models.Metadata.Machine.PartKey] = Array.ConvertAll(item.Part, ConvertToInternalModel);
|
||||
|
||||
return machine;
|
||||
}
|
||||
@@ -83,8 +81,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.DataArea.EndiannessKey] = item.Endianness,
|
||||
};
|
||||
|
||||
if (item.Rom != null && item.Rom.Any())
|
||||
dataArea[Models.Metadata.DataArea.RomKey] = item.Rom.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Rom != null && item.Rom.Length > 0)
|
||||
dataArea[Models.Metadata.DataArea.RomKey] = Array.ConvertAll(item.Rom, ConvertToInternalModel);
|
||||
|
||||
return dataArea;
|
||||
}
|
||||
@@ -101,8 +99,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.DipSwitch.MaskKey] = item.Mask,
|
||||
};
|
||||
|
||||
if (item.DipValue != null && item.DipValue.Any())
|
||||
dipSwitch[Models.Metadata.DipSwitch.DipValueKey] = item.DipValue.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.DipValue != null && item.DipValue.Length > 0)
|
||||
dipSwitch[Models.Metadata.DipSwitch.DipValueKey] = Array.ConvertAll(item.DipValue, ConvertToInternalModel);
|
||||
|
||||
return dipSwitch;
|
||||
}
|
||||
@@ -147,8 +145,8 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.DiskArea.NameKey] = item.Name,
|
||||
};
|
||||
|
||||
if (item.Disk != null && item.Disk.Any())
|
||||
diskArea[Models.Metadata.DiskArea.DiskKey] = item.Disk.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Disk != null && item.Disk.Length > 0)
|
||||
diskArea[Models.Metadata.DiskArea.DiskKey] = Array.ConvertAll(item.Disk, ConvertToInternalModel);
|
||||
|
||||
return diskArea;
|
||||
}
|
||||
@@ -190,17 +188,17 @@ namespace SabreTools.Serialization.CrossModel
|
||||
[Models.Metadata.Part.InterfaceKey] = item.Interface,
|
||||
};
|
||||
|
||||
if (item.Feature != null && item.Feature.Any())
|
||||
part[Models.Metadata.Part.FeatureKey] = item.Feature.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.Feature != null && item.Feature.Length > 0)
|
||||
part[Models.Metadata.Part.FeatureKey] = Array.ConvertAll(item.Feature, ConvertToInternalModel);
|
||||
|
||||
if (item.DataArea != null && item.DataArea.Any())
|
||||
part[Models.Metadata.Part.DataAreaKey] = item.DataArea.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.DataArea != null && item.DataArea.Length > 0)
|
||||
part[Models.Metadata.Part.DataAreaKey] = Array.ConvertAll(item.DataArea, ConvertToInternalModel);
|
||||
|
||||
if (item.DiskArea != null && item.DiskArea.Any())
|
||||
part[Models.Metadata.Part.DiskAreaKey] = item.DiskArea.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.DiskArea != null && item.DiskArea.Length > 0)
|
||||
part[Models.Metadata.Part.DiskAreaKey] = Array.ConvertAll(item.DiskArea, ConvertToInternalModel);
|
||||
|
||||
if (item.DipSwitch != null && item.DipSwitch.Any())
|
||||
part[Models.Metadata.Part.DipSwitchKey] = item.DipSwitch.Select(ConvertToInternalModel).ToArray();
|
||||
if (item.DipSwitch != null && item.DipSwitch.Length > 0)
|
||||
part[Models.Metadata.Part.DipSwitchKey] = Array.ConvertAll(item.DipSwitch, ConvertToInternalModel);
|
||||
|
||||
return part;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Set the records
|
||||
mediaKeyBlock.Records = records.ToArray();
|
||||
mediaKeyBlock.Records = [.. records];
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -164,7 +164,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Set the subset differences
|
||||
record.SubsetDifferences = subsetDifferences.ToArray();
|
||||
record.SubsetDifferences = [.. subsetDifferences];
|
||||
|
||||
// If there's any data left, discard it
|
||||
if (data.Position < initialOffset + length)
|
||||
@@ -205,7 +205,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Set the media keys
|
||||
record.MediaKeyData = mediaKeys.ToArray();
|
||||
record.MediaKeyData = [.. mediaKeys];
|
||||
|
||||
return record;
|
||||
}
|
||||
@@ -243,7 +243,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Set the offsets
|
||||
record.Offsets = offsets.ToArray();
|
||||
record.Offsets = [.. offsets];
|
||||
|
||||
return record;
|
||||
}
|
||||
@@ -322,7 +322,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Set the signature blocks
|
||||
record.SignatureBlocks = blocks.ToArray();
|
||||
record.SignatureBlocks = [.. blocks];
|
||||
|
||||
// If there's any data left, discard it
|
||||
if (data.Position < initialOffset + length)
|
||||
@@ -383,7 +383,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Set the signature blocks
|
||||
record.SignatureBlocks = blocks.ToArray();
|
||||
record.SignatureBlocks = [.. blocks];
|
||||
|
||||
// If there's any data left, discard it
|
||||
if (data.Position < initialOffset + length)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Readers;
|
||||
using SabreTools.Models.AttractMode;
|
||||
@@ -38,7 +37,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (!reader.ReadHeader() || reader.HeaderValues == null)
|
||||
return null;
|
||||
|
||||
dat.Header = reader.HeaderValues.ToArray();
|
||||
dat.Header = [.. reader.HeaderValues];
|
||||
|
||||
// Loop through the rows and parse out values
|
||||
var rows = new List<Row>();
|
||||
@@ -72,10 +71,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
Extra = reader.Line[15],
|
||||
Buttons = reader.Line[16],
|
||||
};
|
||||
|
||||
// If we have additional fields
|
||||
if (reader.Line.Count > HeaderWithoutRomnameCount)
|
||||
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutRomnameCount).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,17 +94,13 @@ namespace SabreTools.Serialization.Deserializers
|
||||
Extra = reader.Line[15],
|
||||
Buttons = reader.Line[16],
|
||||
};
|
||||
|
||||
// If we have additional fields
|
||||
if (reader.Line.Count > HeaderWithRomnameCount)
|
||||
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithRomnameCount).ToArray();
|
||||
}
|
||||
|
||||
rows.Add(row);
|
||||
}
|
||||
|
||||
// Assign the rows to the Dat and return
|
||||
dat.Row = rows.ToArray();
|
||||
dat.Row = [.. rows];
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.BSP;
|
||||
@@ -165,9 +164,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// TODO: Use marshalling here instead of building
|
||||
var texture = new Texture();
|
||||
|
||||
byte[]? name = data.ReadBytes(16)?.TakeWhile(c => c != '\0')?.ToArray();
|
||||
byte[]? name = data.ReadBytes(16);
|
||||
if (name != null)
|
||||
texture.Name = Encoding.ASCII.GetString(name);
|
||||
texture.Name = Encoding.ASCII.GetString(name).TrimEnd('\0');
|
||||
texture.Width = data.ReadUInt32();
|
||||
texture.Height = data.ReadUInt32();
|
||||
texture.Offsets = new uint[4];
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
@@ -17,6 +15,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 +45,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);
|
||||
}
|
||||
|
||||
@@ -103,12 +106,13 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (deserializerName == null)
|
||||
return default;
|
||||
|
||||
// If the deserializer has no model type
|
||||
Type? modelType = typeof(TDeserializer).GetGenericArguments()?.FirstOrDefault();
|
||||
if (modelType == null)
|
||||
// If the deserializer has no generic arguments
|
||||
var genericArgs = typeof(TDeserializer).GetGenericArguments();
|
||||
if (genericArgs.Length == 0)
|
||||
return default;
|
||||
|
||||
// Loop through all loaded assemblies
|
||||
Type modelType = genericArgs[0];
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
// If the assembly is invalid
|
||||
@@ -116,19 +120,23 @@ namespace SabreTools.Serialization.Deserializers
|
||||
return default;
|
||||
|
||||
// If not all types can be loaded, use the ones that could be
|
||||
List<Type> assemblyTypes = [];
|
||||
Type?[] assemblyTypes = [];
|
||||
try
|
||||
{
|
||||
assemblyTypes = assembly.GetTypes().ToList<Type>();
|
||||
assemblyTypes = assembly.GetTypes();
|
||||
}
|
||||
catch (ReflectionTypeLoadException rtle)
|
||||
{
|
||||
assemblyTypes = rtle.Types.Where(t => t != null)!.ToList<Type>();
|
||||
assemblyTypes = rtle.Types ?? [];
|
||||
}
|
||||
|
||||
// Loop through all types
|
||||
foreach (Type type in assemblyTypes)
|
||||
foreach (Type? type in assemblyTypes)
|
||||
{
|
||||
// If the type is invalid
|
||||
if (type == null)
|
||||
continue;
|
||||
|
||||
// If the type isn't a class
|
||||
if (!type.IsClass)
|
||||
continue;
|
||||
|
||||
@@ -77,7 +77,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Assign the DIFAT sectors table
|
||||
binary.DIFATSectorNumbers = difatSectors.ToArray();
|
||||
binary.DIFATSectorNumbers = [.. difatSectors];
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Assign the FAT sectors table
|
||||
binary.FATSectorNumbers = fatSectors.ToArray();
|
||||
binary.FATSectorNumbers = [.. fatSectors];
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Assign the mini FAT sectors table
|
||||
binary.MiniFATSectorNumbers = miniFatSectors.ToArray();
|
||||
binary.MiniFATSectorNumbers = [.. miniFatSectors];
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -219,7 +219,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Assign the Directory sectors table
|
||||
binary.DirectoryEntries = directorySectors.ToArray();
|
||||
binary.DirectoryEntries = [.. directorySectors];
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
253
SabreTools.Serialization/Deserializers/CHD.cs
Normal file
253
SabreTools.Serialization/Deserializers/CHD.cs
Normal file
@@ -0,0 +1,253 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.CHD;
|
||||
|
||||
namespace SabreTools.Serialization.Deserializers
|
||||
{
|
||||
// TODO: Expand this to full CHD files eventually
|
||||
public class CHD : BaseBinaryDeserializer<Header>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override Header? 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;
|
||||
|
||||
// Determine the header version
|
||||
uint version = GetVersion(data);
|
||||
|
||||
// Read and return the current CHD
|
||||
return version switch
|
||||
{
|
||||
1 => ParseHeaderV1(data),
|
||||
2 => ParseHeaderV2(data),
|
||||
3 => ParseHeaderV3(data),
|
||||
4 => ParseHeaderV4(data),
|
||||
5 => ParseHeaderV5(data),
|
||||
_ => null,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the matching CHD version, if possible
|
||||
/// </summary>
|
||||
/// <returns>Matching version, 0 if none</returns>
|
||||
private static uint GetVersion(Stream data)
|
||||
{
|
||||
// Read the header values
|
||||
byte[] tagBytes = data.ReadBytes(8);
|
||||
string tag = Encoding.ASCII.GetString(tagBytes);
|
||||
uint length = data.ReadUInt32BigEndian();
|
||||
uint version = data.ReadUInt32BigEndian();
|
||||
|
||||
// Seek back to start
|
||||
data.SeekIfPossible();
|
||||
|
||||
// Check the signature
|
||||
if (!string.Equals(tag, Constants.SignatureString, StringComparison.Ordinal))
|
||||
return 0;
|
||||
|
||||
// Match the version to header length
|
||||
#if NET472_OR_GREATER || NETCOREAPP
|
||||
return (version, length) switch
|
||||
{
|
||||
(1, Constants.HeaderV1Size) => version,
|
||||
(2, Constants.HeaderV2Size) => version,
|
||||
(3, Constants.HeaderV3Size) => version,
|
||||
(4, Constants.HeaderV4Size) => version,
|
||||
(5, Constants.HeaderV5Size) => version,
|
||||
_ => 0,
|
||||
};
|
||||
#else
|
||||
return version switch
|
||||
{
|
||||
1 => length == Constants.HeaderV1Size ? version : 0,
|
||||
2 => length == Constants.HeaderV2Size ? version : 0,
|
||||
3 => length == Constants.HeaderV3Size ? version : 0,
|
||||
4 => length == Constants.HeaderV4Size ? version : 0,
|
||||
5 => length == Constants.HeaderV5Size ? version : 0,
|
||||
_ => 0,
|
||||
};
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a V1 header
|
||||
/// </summary>
|
||||
private static HeaderV1? ParseHeaderV1(Stream data)
|
||||
{
|
||||
var header = new HeaderV1();
|
||||
|
||||
byte[] tagBytes = data.ReadBytes(8);
|
||||
header.Tag = Encoding.ASCII.GetString(tagBytes);
|
||||
if (header.Tag != Constants.SignatureString)
|
||||
return null;
|
||||
|
||||
header.Length = data.ReadUInt32BigEndian();
|
||||
if (header.Length != Constants.HeaderV1Size)
|
||||
return null;
|
||||
|
||||
header.Version = data.ReadUInt32BigEndian();
|
||||
header.Flags = (Flags)data.ReadUInt32BigEndian();
|
||||
header.Compression = (CompressionType)data.ReadUInt32BigEndian();
|
||||
if (header.Compression > CompressionType.CHDCOMPRESSION_ZLIB)
|
||||
return null;
|
||||
|
||||
header.HunkSize = data.ReadUInt32BigEndian();
|
||||
header.TotalHunks = data.ReadUInt32BigEndian();
|
||||
header.Cylinders = data.ReadUInt32BigEndian();
|
||||
header.Heads = data.ReadUInt32BigEndian();
|
||||
header.Sectors = data.ReadUInt32BigEndian();
|
||||
header.MD5 = data.ReadBytes(16);
|
||||
header.ParentMD5 = data.ReadBytes(16);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a V2 header
|
||||
/// </summary>
|
||||
private static HeaderV2? ParseHeaderV2(Stream data)
|
||||
{
|
||||
var header = new HeaderV2();
|
||||
|
||||
byte[] tagBytes = data.ReadBytes(8);
|
||||
header.Tag = Encoding.ASCII.GetString(tagBytes);
|
||||
if (header.Tag != Constants.SignatureString)
|
||||
return null;
|
||||
|
||||
header.Length = data.ReadUInt32BigEndian();
|
||||
if (header.Length != Constants.HeaderV2Size)
|
||||
return null;
|
||||
|
||||
header.Version = data.ReadUInt32BigEndian();
|
||||
header.Flags = (Flags)data.ReadUInt32BigEndian();
|
||||
header.Compression = (CompressionType)data.ReadUInt32BigEndian();
|
||||
if (header.Compression > CompressionType.CHDCOMPRESSION_ZLIB)
|
||||
return null;
|
||||
|
||||
header.HunkSize = data.ReadUInt32BigEndian();
|
||||
header.TotalHunks = data.ReadUInt32BigEndian();
|
||||
header.Cylinders = data.ReadUInt32BigEndian();
|
||||
header.Heads = data.ReadUInt32BigEndian();
|
||||
header.Sectors = data.ReadUInt32BigEndian();
|
||||
header.MD5 = data.ReadBytes(16);
|
||||
header.ParentMD5 = data.ReadBytes(16);
|
||||
header.BytesPerSector = data.ReadUInt32BigEndian();
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a V3 header
|
||||
/// </summary>
|
||||
private static HeaderV3? ParseHeaderV3(Stream data)
|
||||
{
|
||||
var header = new HeaderV3();
|
||||
|
||||
byte[] tagBytes = data.ReadBytes(8);
|
||||
header.Tag = Encoding.ASCII.GetString(tagBytes);
|
||||
if (header.Tag != Constants.SignatureString)
|
||||
return null;
|
||||
|
||||
header.Length = data.ReadUInt32BigEndian();
|
||||
if (header.Length != Constants.HeaderV3Size)
|
||||
return null;
|
||||
|
||||
header.Version = data.ReadUInt32BigEndian();
|
||||
header.Flags = (Flags)data.ReadUInt32BigEndian();
|
||||
header.Compression = (CompressionType)data.ReadUInt32BigEndian();
|
||||
if (header.Compression > CompressionType.CHDCOMPRESSION_ZLIB_PLUS)
|
||||
return null;
|
||||
|
||||
header.TotalHunks = data.ReadUInt32BigEndian();
|
||||
header.LogicalBytes = data.ReadUInt64BigEndian();
|
||||
header.MetaOffset = data.ReadUInt64BigEndian();
|
||||
header.MD5 = data.ReadBytes(16);
|
||||
header.ParentMD5 = data.ReadBytes(16);
|
||||
header.HunkBytes = data.ReadUInt32BigEndian();
|
||||
header.SHA1 = data.ReadBytes(20);
|
||||
header.ParentSHA1 = data.ReadBytes(20);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a V4 header
|
||||
/// </summary>
|
||||
private static HeaderV4? ParseHeaderV4(Stream data)
|
||||
{
|
||||
var header = new HeaderV4();
|
||||
|
||||
byte[] tagBytes = data.ReadBytes(8);
|
||||
header.Tag = Encoding.ASCII.GetString(tagBytes);
|
||||
if (header.Tag != Constants.SignatureString)
|
||||
return null;
|
||||
|
||||
header.Length = data.ReadUInt32BigEndian();
|
||||
if (header.Length != Constants.HeaderV4Size)
|
||||
return null;
|
||||
|
||||
header.Version = data.ReadUInt32BigEndian();
|
||||
header.Flags = (Flags)data.ReadUInt32BigEndian();
|
||||
header.Compression = (CompressionType)data.ReadUInt32BigEndian();
|
||||
if (header.Compression > CompressionType.CHDCOMPRESSION_AV)
|
||||
return null;
|
||||
|
||||
header.TotalHunks = data.ReadUInt32BigEndian();
|
||||
header.LogicalBytes = data.ReadUInt64BigEndian();
|
||||
header.MetaOffset = data.ReadUInt64BigEndian();
|
||||
header.HunkBytes = data.ReadUInt32BigEndian();
|
||||
header.SHA1 = data.ReadBytes(20);
|
||||
header.ParentSHA1 = data.ReadBytes(20);
|
||||
header.RawSHA1 = data.ReadBytes(20);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into a V5 header
|
||||
/// </summary>
|
||||
private static HeaderV5? ParseHeaderV5(Stream data)
|
||||
{
|
||||
var header = new HeaderV5();
|
||||
|
||||
byte[] tagBytes = data.ReadBytes(8);
|
||||
header.Tag = Encoding.ASCII.GetString(tagBytes);
|
||||
if (header.Tag != Constants.SignatureString)
|
||||
return null;
|
||||
|
||||
header.Length = data.ReadUInt32BigEndian();
|
||||
if (header.Length != Constants.HeaderV5Size)
|
||||
return null;
|
||||
|
||||
header.Version = data.ReadUInt32BigEndian();
|
||||
header.Compressors = new CodecType[4];
|
||||
for (int i = 0; i < header.Compressors.Length; i++)
|
||||
{
|
||||
header.Compressors[i] = (CodecType)data.ReadUInt32BigEndian();
|
||||
}
|
||||
|
||||
header.LogicalBytes = data.ReadUInt64BigEndian();
|
||||
header.MapOffset = data.ReadUInt64BigEndian();
|
||||
header.MetaOffset = data.ReadUInt64BigEndian();
|
||||
header.HunkBytes = data.ReadUInt32BigEndian();
|
||||
header.UnitBytes = data.ReadUInt32BigEndian();
|
||||
header.RawSHA1 = data.ReadBytes(20);
|
||||
header.SHA1 = data.ReadBytes(20);
|
||||
header.ParentSHA1 = data.ReadBytes(20);
|
||||
|
||||
return header;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,7 +70,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var deserializer = new ClrMamePro();
|
||||
return deserializer.Deserialize(data, quotes);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override MetadataFile? Deserialize(Stream? data)
|
||||
=> Deserialize(data, true);
|
||||
@@ -102,9 +102,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var videos = new List<Video>();
|
||||
var dipSwitches = new List<DipSwitch>();
|
||||
|
||||
var additional = new List<string>();
|
||||
var headerAdditional = new List<string>();
|
||||
var gameAdditional = new List<string>();
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
// If we have no next line
|
||||
@@ -120,12 +117,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case CmpRowType.EndTopLevel:
|
||||
switch (lastTopLevel)
|
||||
{
|
||||
case "doscenter":
|
||||
if (dat.ClrMamePro != null)
|
||||
dat.ClrMamePro.ADDITIONAL_ELEMENTS = [.. headerAdditional];
|
||||
|
||||
headerAdditional.Clear();
|
||||
break;
|
||||
case "game":
|
||||
case "machine":
|
||||
case "resource":
|
||||
@@ -142,7 +133,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
game.Chip = [.. chips];
|
||||
game.Video = [.. videos];
|
||||
game.DipSwitch = [.. dipSwitches];
|
||||
game.ADDITIONAL_ELEMENTS = [.. gameAdditional];
|
||||
|
||||
games.Add(game);
|
||||
game = null;
|
||||
@@ -158,10 +148,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
chips.Clear();
|
||||
videos.Clear();
|
||||
dipSwitches.Clear();
|
||||
gameAdditional.Clear();
|
||||
break;
|
||||
default:
|
||||
// No-op
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -188,10 +174,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "set":
|
||||
game = new Set();
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
additional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,10 +231,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "forcepacking":
|
||||
dat.ClrMamePro.ForcePacking = reader.Standalone?.Value;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
headerAdditional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,14 +281,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var sample = new Sample
|
||||
{
|
||||
Name = reader.Standalone?.Value ?? string.Empty,
|
||||
ADDITIONAL_ELEMENTS = [],
|
||||
};
|
||||
samples.Add(sample);
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
gameAdditional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -391,22 +364,13 @@ namespace SabreTools.Serialization.Deserializers
|
||||
game.Driver = driver;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
gameAdditional.Add(reader.CurrentLine);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (reader.CurrentLine != null)
|
||||
additional.Add(reader.CurrentLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Add extra pieces and return
|
||||
dat.Game = [.. games];
|
||||
dat.ADDITIONAL_ELEMENTS = [.. additional];
|
||||
return dat;
|
||||
}
|
||||
|
||||
@@ -447,7 +411,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
}
|
||||
|
||||
release.ADDITIONAL_ELEMENTS = [.. itemAdditional];
|
||||
return release;
|
||||
}
|
||||
|
||||
@@ -461,7 +424,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var biosset = new BiosSet();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -476,13 +438,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "default":
|
||||
biosset.Default = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
biosset.ADDITIONAL_ELEMENTS = [.. itemAdditional];
|
||||
return biosset;
|
||||
}
|
||||
|
||||
@@ -496,7 +454,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var rom = new Rom();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -565,13 +522,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "mia":
|
||||
rom.MIA = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rom.ADDITIONAL_ELEMENTS = [.. itemAdditional];
|
||||
return rom;
|
||||
}
|
||||
|
||||
@@ -585,7 +538,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var disk = new Disk();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -609,13 +561,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "flags":
|
||||
disk.Flags = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
disk.ADDITIONAL_ELEMENTS = [.. itemAdditional];
|
||||
return disk;
|
||||
}
|
||||
|
||||
@@ -629,7 +577,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var media = new Media();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -650,13 +597,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "spamsum":
|
||||
media.SpamSum = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
media.ADDITIONAL_ELEMENTS = [.. itemAdditional];
|
||||
return media;
|
||||
}
|
||||
|
||||
@@ -670,7 +613,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var sample = new Sample();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -679,13 +621,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "name":
|
||||
sample.Name = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sample.ADDITIONAL_ELEMENTS = [.. itemAdditional];
|
||||
return sample;
|
||||
}
|
||||
|
||||
@@ -699,7 +637,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var archive = new Archive();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -708,13 +645,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "name":
|
||||
archive.Name = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
archive.ADDITIONAL_ELEMENTS = [.. itemAdditional];
|
||||
return archive;
|
||||
}
|
||||
|
||||
@@ -728,7 +661,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var chip = new Chip();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -746,13 +678,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "clock":
|
||||
chip.Clock = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
chip.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
|
||||
return chip;
|
||||
}
|
||||
|
||||
@@ -766,7 +694,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var video = new Video();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -793,13 +720,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "freq":
|
||||
video.Freq = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
video.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
|
||||
return video;
|
||||
}
|
||||
|
||||
@@ -813,7 +736,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var sound = new Sound();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -822,13 +744,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "channels":
|
||||
sound.Channels = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sound.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
|
||||
return sound;
|
||||
}
|
||||
|
||||
@@ -842,7 +760,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var input = new Input();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -866,13 +783,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "service":
|
||||
input.Service = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
input.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
|
||||
return input;
|
||||
}
|
||||
|
||||
@@ -886,7 +799,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var dipswitch = new DipSwitch();
|
||||
var entries = new List<string>();
|
||||
foreach (var kvp in reader.Internal)
|
||||
@@ -902,14 +814,10 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "default":
|
||||
dipswitch.Default = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dipswitch.Entry = [.. entries];
|
||||
dipswitch.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
|
||||
return dipswitch;
|
||||
}
|
||||
|
||||
@@ -923,7 +831,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var driver = new Driver();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -944,13 +851,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "blit":
|
||||
driver.Blit = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
itemAdditional.Add($"{kvp.Key}: {kvp.Value}");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
driver.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
|
||||
return driver;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.CueSheets;
|
||||
@@ -44,11 +43,13 @@ namespace SabreTools.Serialization.Deserializers
|
||||
continue;
|
||||
|
||||
// http://stackoverflow.com/questions/554013/regular-expression-to-split-on-spaces-unless-in-quotes
|
||||
string[] splitLine = Regex
|
||||
.Matches(line, @"[^\s""]+|""[^""]*""")
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Groups[0].Value)
|
||||
.ToArray();
|
||||
var matchCol = Regex.Matches(line, @"[^\s""]+|""[^""]*""");
|
||||
var splitLine = new List<string>();
|
||||
foreach (Match? match in matchCol)
|
||||
{
|
||||
if (match != null)
|
||||
splitLine.Add(match.Groups[0].Value);
|
||||
}
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
@@ -59,7 +60,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read MCN
|
||||
case "CATALOG":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"CATALOG line malformed: {line}");
|
||||
|
||||
cueSheet.Catalog = splitLine[1].Trim('"');
|
||||
@@ -67,7 +68,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read external CD-Text file path
|
||||
case "CDTEXTFILE":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"CDTEXTFILE line malformed: {line}");
|
||||
|
||||
cueSheet.CdTextFile = splitLine[1].Trim('"');
|
||||
@@ -75,7 +76,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read CD-Text enhanced performer
|
||||
case "PERFORMER":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"PERFORMER line malformed: {line}");
|
||||
|
||||
cueSheet.Performer = splitLine[1].Trim('"');
|
||||
@@ -83,7 +84,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read CD-Text enhanced songwriter
|
||||
case "SONGWRITER":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"SONGWRITER line malformed: {line}");
|
||||
|
||||
cueSheet.Songwriter = splitLine[1].Trim('"');
|
||||
@@ -91,7 +92,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read CD-Text enhanced title
|
||||
case "TITLE":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"TITLE line malformed: {line}");
|
||||
|
||||
cueSheet.Title = splitLine[1].Trim('"');
|
||||
@@ -99,7 +100,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read file information
|
||||
case "FILE":
|
||||
if (splitLine.Length < 3)
|
||||
if (splitLine.Count < 3)
|
||||
throw new FormatException($"FILE line malformed: {line}");
|
||||
|
||||
var file = CreateCueFile(splitLine[1], splitLine[2], data, out lastLine);
|
||||
@@ -152,11 +153,13 @@ namespace SabreTools.Serialization.Deserializers
|
||||
continue;
|
||||
|
||||
// http://stackoverflow.com/questions/554013/regular-expression-to-split-on-spaces-unless-in-quotes
|
||||
string[] splitLine = Regex
|
||||
.Matches(line, @"[^\s""]+|""[^""]*""")
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Groups[0].Value)
|
||||
.ToArray();
|
||||
var matchCol = Regex.Matches(line, @"[^\s""]+|""[^""]*""");
|
||||
var splitLine = new List<string>();
|
||||
foreach (Match? match in matchCol)
|
||||
{
|
||||
if (match != null)
|
||||
splitLine.Add(match.Groups[0].Value);
|
||||
}
|
||||
|
||||
switch (splitLine[0])
|
||||
{
|
||||
@@ -167,7 +170,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read track information
|
||||
case "TRACK":
|
||||
if (splitLine.Length < 3)
|
||||
if (splitLine.Count < 3)
|
||||
throw new FormatException($"TRACK line malformed: {line}");
|
||||
|
||||
var track = CreateCueTrack(splitLine[1], splitLine[2], data, out lastLine);
|
||||
@@ -237,12 +240,13 @@ namespace SabreTools.Serialization.Deserializers
|
||||
continue;
|
||||
|
||||
// http://stackoverflow.com/questions/554013/regular-expression-to-split-on-spaces-unless-in-quotes
|
||||
string[] splitLine = Regex
|
||||
.Matches(line, @"[^\s""]+|""[^""]*""")
|
||||
.Cast<Match>()
|
||||
.Select(m => m.Groups[0].Value)
|
||||
.ToArray();
|
||||
|
||||
var matchCol = Regex.Matches(line, @"[^\s""]+|""[^""]*""");
|
||||
var splitLine = new List<string>();
|
||||
foreach (Match? match in matchCol)
|
||||
{
|
||||
if (match != null)
|
||||
splitLine.Add(match.Groups[0].Value);
|
||||
}
|
||||
switch (splitLine[0])
|
||||
{
|
||||
// Read comments
|
||||
@@ -252,15 +256,15 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read flag information
|
||||
case "FLAGS":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"FLAGS line malformed: {line}");
|
||||
|
||||
cueTrack.Flags = GetFlags(splitLine);
|
||||
cueTrack.Flags = GetFlags([.. splitLine]);
|
||||
break;
|
||||
|
||||
// Read International Standard Recording Code
|
||||
case "ISRC":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"ISRC line malformed: {line}");
|
||||
|
||||
cueTrack.ISRC = splitLine[1].Trim('"');
|
||||
@@ -268,7 +272,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read CD-Text enhanced performer
|
||||
case "PERFORMER":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"PERFORMER line malformed: {line}");
|
||||
|
||||
cueTrack.Performer = splitLine[1].Trim('"');
|
||||
@@ -276,7 +280,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read CD-Text enhanced songwriter
|
||||
case "SONGWRITER":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"SONGWRITER line malformed: {line}");
|
||||
|
||||
cueTrack.Songwriter = splitLine[1].Trim('"');
|
||||
@@ -284,7 +288,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read CD-Text enhanced title
|
||||
case "TITLE":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"TITLE line malformed: {line}");
|
||||
|
||||
cueTrack.Title = splitLine[1].Trim('"');
|
||||
@@ -292,7 +296,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read pregap information
|
||||
case "PREGAP":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"PREGAP line malformed: {line}");
|
||||
|
||||
var pregap = CreatePreGap(splitLine[1]);
|
||||
@@ -304,7 +308,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read index information
|
||||
case "INDEX":
|
||||
if (splitLine.Length < 3)
|
||||
if (splitLine.Count < 3)
|
||||
throw new FormatException($"INDEX line malformed: {line}");
|
||||
|
||||
var index = CreateCueIndex(splitLine[1], splitLine[2]);
|
||||
@@ -316,7 +320,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Read postgap information
|
||||
case "POSTGAP":
|
||||
if (splitLine.Length < 2)
|
||||
if (splitLine.Count < 2)
|
||||
throw new FormatException($"POSTGAP line malformed: {line}");
|
||||
|
||||
var postgap = CreatePostGap(splitLine[1]);
|
||||
@@ -356,7 +360,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
throw new ArgumentException("Length was null or whitespace");
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (length!.Length != 8 || length.Count(c => c == ':') != 2)
|
||||
if (length!.Length != 8)
|
||||
throw new FormatException($"Length was not in a recognized format: {length}");
|
||||
|
||||
// Split the line
|
||||
@@ -413,7 +417,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
throw new ArgumentException("Start time was null or whitespace");
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (startTime!.Length != 8 || startTime.Count(c => c == ':') != 2)
|
||||
if (startTime!.Length != 8)
|
||||
throw new FormatException($"Start time was not in a recognized format: {startTime}");
|
||||
|
||||
// Split the line
|
||||
@@ -464,7 +468,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
throw new ArgumentException("Length was null or whitespace");
|
||||
|
||||
// Ignore lines that don't contain the correct information
|
||||
if (length!.Length != 8 || length.Count(c => c == ':') != 2)
|
||||
if (length!.Length != 8)
|
||||
throw new FormatException($"Length was not in a recognized format: {length}");
|
||||
|
||||
// Split the line
|
||||
|
||||
@@ -26,9 +26,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var games = new List<Game>();
|
||||
var files = new List<Models.DosCenter.File>();
|
||||
|
||||
var additional = new List<string>();
|
||||
var headerAdditional = new List<string>();
|
||||
var gameAdditional = new List<string>();
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
// If we have no next line
|
||||
@@ -44,26 +41,15 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case CmpRowType.EndTopLevel:
|
||||
switch (lastTopLevel)
|
||||
{
|
||||
case "doscenter":
|
||||
if (dat.DosCenter != null)
|
||||
dat.DosCenter.ADDITIONAL_ELEMENTS = headerAdditional.ToArray();
|
||||
|
||||
headerAdditional.Clear();
|
||||
break;
|
||||
case "game":
|
||||
if (game != null)
|
||||
{
|
||||
game.File = files.ToArray();
|
||||
game.ADDITIONAL_ELEMENTS = gameAdditional.ToArray();
|
||||
game.File = [.. files];
|
||||
games.Add(game);
|
||||
}
|
||||
|
||||
game = null;
|
||||
files.Clear();
|
||||
gameAdditional.Clear();
|
||||
break;
|
||||
default:
|
||||
// No-op
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
@@ -81,10 +67,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "game":
|
||||
game = new Game();
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
additional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,10 +99,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "comment:":
|
||||
dat.DosCenter.Comment = reader.Standalone?.Value;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
headerAdditional.Add(item: reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,10 +113,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "name":
|
||||
game.Name = reader.Standalone?.Value;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
gameAdditional.Add(item: reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,28 +121,17 @@ namespace SabreTools.Serialization.Deserializers
|
||||
{
|
||||
// If we have an unknown type, log it
|
||||
if (reader.InternalName != "file")
|
||||
{
|
||||
if (reader.CurrentLine != null)
|
||||
gameAdditional.Add(reader.CurrentLine);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create the file and add to the list
|
||||
var file = CreateFile(reader);
|
||||
if (file != null)
|
||||
files.Add(file);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (reader.CurrentLine != null)
|
||||
additional.Add(item: reader.CurrentLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Add extra pieces and return
|
||||
dat.Game = games.ToArray();
|
||||
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
|
||||
dat.Game = [.. games];
|
||||
return dat;
|
||||
}
|
||||
|
||||
@@ -182,7 +145,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Internal == null)
|
||||
return null;
|
||||
|
||||
var itemAdditional = new List<string>();
|
||||
var file = new Models.DosCenter.File();
|
||||
foreach (var kvp in reader.Internal)
|
||||
{
|
||||
@@ -200,14 +162,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "date":
|
||||
file.Date = kvp.Value;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
itemAdditional.Add(item: reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
file.ADDITIONAL_ELEMENTS = itemAdditional.ToArray();
|
||||
return file;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Readers;
|
||||
using SabreTools.Models.EverdriveSMDB;
|
||||
@@ -47,15 +46,11 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (reader.Line.Count > 5)
|
||||
row.Size = reader.Line[5];
|
||||
|
||||
// If we have additional fields
|
||||
if (reader.Line.Count > 6)
|
||||
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(5).ToArray();
|
||||
|
||||
rows.Add(row);
|
||||
}
|
||||
|
||||
// Assign the rows to the Dat and return
|
||||
dat.Row = rows.ToArray();
|
||||
dat.Row = [.. rows];
|
||||
return dat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SabreTools.Hashing;
|
||||
using SabreTools.Models.Hashfile;
|
||||
|
||||
@@ -60,7 +59,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
using var stream = PathProcessor.OpenStream(path);
|
||||
return DeserializeStream(stream, hash);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region IStreamDeserializer
|
||||
@@ -71,7 +70,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var deserializer = new Hashfile();
|
||||
return deserializer.Deserialize(data, hash);
|
||||
}
|
||||
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override Models.Hashfile.Hashfile? Deserialize(Stream? data)
|
||||
=> Deserialize(data, HashType.CRC32);
|
||||
@@ -86,19 +85,22 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// Setup the reader and output
|
||||
var reader = new StreamReader(data);
|
||||
var dat = new Models.Hashfile.Hashfile();
|
||||
var additional = new List<string>();
|
||||
|
||||
// Create lists for each hash type
|
||||
var sfvList = new List<SFV>();
|
||||
var md5List = new List<MD5>();
|
||||
var sha1List = new List<SHA1>();
|
||||
var sha256List = new List<SHA256>();
|
||||
var sha384List = new List<SHA384>();
|
||||
var sha512List = new List<SHA512>();
|
||||
var spamsumList = new List<SpamSum>();
|
||||
|
||||
// Loop through the rows and parse out values
|
||||
var hashes = new List<object>();
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
// Read and split the line
|
||||
string? line = reader.ReadLine();
|
||||
#if NETFRAMEWORK || NETCOREAPP3_1
|
||||
string[]? lineParts = line?.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
#else
|
||||
string[]? lineParts = line?.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||
#endif
|
||||
string[]? lineParts = line?.Split([' '], StringSplitOptions.RemoveEmptyEntries);
|
||||
if (lineParts == null)
|
||||
continue;
|
||||
|
||||
@@ -106,93 +108,60 @@ namespace SabreTools.Serialization.Deserializers
|
||||
switch (hash)
|
||||
{
|
||||
case HashType.CRC32:
|
||||
case HashType.CRC32_ISO:
|
||||
case HashType.CRC32_Naive:
|
||||
case HashType.CRC32_Optimized:
|
||||
case HashType.CRC32_Parallel:
|
||||
var sfv = new SFV
|
||||
{
|
||||
#if NETFRAMEWORK
|
||||
File = string.Join(" ", lineParts.Take(lineParts.Length - 1).ToArray()),
|
||||
File = string.Join(" ", lineParts, 0, lineParts.Length - 1),
|
||||
Hash = lineParts[lineParts.Length - 1],
|
||||
#else
|
||||
File = string.Join(" ", lineParts[..^1]),
|
||||
Hash = lineParts[^1],
|
||||
#endif
|
||||
};
|
||||
hashes.Add(sfv);
|
||||
sfvList.Add(sfv);
|
||||
break;
|
||||
case HashType.MD5:
|
||||
var md5 = new MD5
|
||||
{
|
||||
Hash = lineParts[0],
|
||||
#if NETFRAMEWORK
|
||||
File = string.Join(" ", lineParts.Skip(1).ToArray()),
|
||||
#else
|
||||
File = string.Join(" ", lineParts[1..]),
|
||||
#endif
|
||||
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
|
||||
};
|
||||
hashes.Add(md5);
|
||||
md5List.Add(md5);
|
||||
break;
|
||||
case HashType.SHA1:
|
||||
var sha1 = new SHA1
|
||||
{
|
||||
Hash = lineParts[0],
|
||||
#if NETFRAMEWORK
|
||||
File = string.Join(" ", lineParts.Skip(1).ToArray()),
|
||||
#else
|
||||
File = string.Join(" ", lineParts[1..]),
|
||||
#endif
|
||||
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
|
||||
};
|
||||
hashes.Add(sha1);
|
||||
sha1List.Add(sha1);
|
||||
break;
|
||||
case HashType.SHA256:
|
||||
var sha256 = new SHA256
|
||||
{
|
||||
Hash = lineParts[0],
|
||||
#if NETFRAMEWORK
|
||||
File = string.Join(" ", lineParts.Skip(1).ToArray()),
|
||||
#else
|
||||
File = string.Join(" ", lineParts[1..]),
|
||||
#endif
|
||||
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
|
||||
};
|
||||
hashes.Add(sha256);
|
||||
sha256List.Add(sha256);
|
||||
break;
|
||||
case HashType.SHA384:
|
||||
var sha384 = new SHA384
|
||||
{
|
||||
Hash = lineParts[0],
|
||||
#if NETFRAMEWORK
|
||||
File = string.Join(" ", lineParts.Skip(1).ToArray()),
|
||||
#else
|
||||
File = string.Join(" ", lineParts[1..]),
|
||||
#endif
|
||||
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
|
||||
};
|
||||
hashes.Add(sha384);
|
||||
sha384List.Add(sha384);
|
||||
break;
|
||||
case HashType.SHA512:
|
||||
var sha512 = new SHA512
|
||||
{
|
||||
Hash = lineParts[0],
|
||||
#if NETFRAMEWORK
|
||||
File = string.Join(" ", lineParts.Skip(1).ToArray()),
|
||||
#else
|
||||
File = string.Join(" ", lineParts[1..]),
|
||||
#endif
|
||||
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
|
||||
};
|
||||
hashes.Add(sha512);
|
||||
sha512List.Add(sha512);
|
||||
break;
|
||||
case HashType.SpamSum:
|
||||
var spamSum = new SpamSum
|
||||
{
|
||||
Hash = lineParts[0],
|
||||
#if NETFRAMEWORK
|
||||
File = string.Join(" ", lineParts.Skip(1).ToArray()),
|
||||
#else
|
||||
File = string.Join(" ", lineParts[1..]),
|
||||
#endif
|
||||
File = string.Join(" ", lineParts, 1, lineParts.Length - 1),
|
||||
};
|
||||
hashes.Add(spamSum);
|
||||
spamsumList.Add(spamSum);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -201,32 +170,28 @@ namespace SabreTools.Serialization.Deserializers
|
||||
switch (hash)
|
||||
{
|
||||
case HashType.CRC32:
|
||||
case HashType.CRC32_ISO:
|
||||
case HashType.CRC32_Naive:
|
||||
case HashType.CRC32_Optimized:
|
||||
case HashType.CRC32_Parallel:
|
||||
dat.SFV = hashes.Cast<SFV>().ToArray();
|
||||
dat.SFV = [.. sfvList];
|
||||
break;
|
||||
case HashType.MD5:
|
||||
dat.MD5 = hashes.Cast<MD5>().ToArray();
|
||||
dat.MD5 = [.. md5List];
|
||||
break;
|
||||
case HashType.SHA1:
|
||||
dat.SHA1 = hashes.Cast<SHA1>().ToArray();
|
||||
dat.SHA1 = [.. sha1List];
|
||||
break;
|
||||
case HashType.SHA256:
|
||||
dat.SHA256 = hashes.Cast<SHA256>().ToArray();
|
||||
dat.SHA256 = [.. sha256List];
|
||||
break;
|
||||
case HashType.SHA384:
|
||||
dat.SHA384 = hashes.Cast<SHA384>().ToArray();
|
||||
dat.SHA384 = [.. sha384List];
|
||||
break;
|
||||
case HashType.SHA512:
|
||||
dat.SHA512 = hashes.Cast<SHA512>().ToArray();
|
||||
dat.SHA512 = [.. sha512List];
|
||||
break;
|
||||
case HashType.SpamSum:
|
||||
dat.SpamSum = hashes.Cast<SpamSum>().ToArray();
|
||||
dat.SpamSum = [.. spamsumList];
|
||||
break;
|
||||
}
|
||||
dat.ADDITIONAL_ELEMENTS = [.. additional];
|
||||
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.InstallShieldArchiveV3;
|
||||
|
||||
@@ -114,7 +115,17 @@ namespace SabreTools.Serialization.Deserializers
|
||||
/// <returns>Filled directory on success, null on error</returns>
|
||||
public static Models.InstallShieldArchiveV3.Directory? ParseDirectory(Stream data)
|
||||
{
|
||||
return data.ReadType<Models.InstallShieldArchiveV3.Directory>();
|
||||
var directory = new Models.InstallShieldArchiveV3.Directory();
|
||||
|
||||
directory.FileCount = data.ReadUInt16();
|
||||
directory.ChunkSize = data.ReadUInt16();
|
||||
|
||||
// TODO: Is there any equivilent automatic type for UInt16-prefixed ANSI?
|
||||
ushort nameLength = data.ReadUInt16();
|
||||
byte[] nameBytes = data.ReadBytes(nameLength);
|
||||
directory.Name = Encoding.ASCII.GetString(nameBytes);
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SabreTools.IO.Extensions;
|
||||
@@ -447,14 +448,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var fileGroup = new FileGroup();
|
||||
|
||||
fileGroup.NameOffset = data.ReadUInt32();
|
||||
|
||||
fileGroup.ExpandedSize = data.ReadUInt32();
|
||||
fileGroup.Reserved0 = data.ReadBytes(4);
|
||||
fileGroup.CompressedSize = data.ReadUInt32();
|
||||
fileGroup.Reserved1 = data.ReadBytes(4);
|
||||
fileGroup.Reserved2 = data.ReadBytes(2);
|
||||
fileGroup.Attribute1 = data.ReadUInt16();
|
||||
fileGroup.Attribute2 = data.ReadUInt16();
|
||||
fileGroup.Attributes = (FileGroupAttributes)data.ReadUInt16();
|
||||
|
||||
// TODO: Figure out what data lives in this area for V5 and below
|
||||
if (majorVersion <= 5)
|
||||
@@ -462,19 +458,19 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
fileGroup.FirstFile = data.ReadUInt32();
|
||||
fileGroup.LastFile = data.ReadUInt32();
|
||||
fileGroup.UnknownOffset = data.ReadUInt32();
|
||||
fileGroup.Var4Offset = data.ReadUInt32();
|
||||
fileGroup.Var1Offset = data.ReadUInt32();
|
||||
fileGroup.UnknownStringOffset = data.ReadUInt32();
|
||||
fileGroup.OperatingSystemOffset = data.ReadUInt32();
|
||||
fileGroup.LanguageOffset = data.ReadUInt32();
|
||||
fileGroup.HTTPLocationOffset = data.ReadUInt32();
|
||||
fileGroup.FTPLocationOffset = data.ReadUInt32();
|
||||
fileGroup.MiscOffset = data.ReadUInt32();
|
||||
fileGroup.Var2Offset = data.ReadUInt32();
|
||||
fileGroup.TargetDirectoryOffset = data.ReadUInt32();
|
||||
fileGroup.Reserved3 = data.ReadBytes(2);
|
||||
fileGroup.Reserved4 = data.ReadBytes(2);
|
||||
fileGroup.Reserved5 = data.ReadBytes(2);
|
||||
fileGroup.Reserved6 = data.ReadBytes(2);
|
||||
fileGroup.Reserved7 = data.ReadBytes(2);
|
||||
fileGroup.OverwriteFlags = (FileGroupFlags)data.ReadUInt32();
|
||||
fileGroup.Reserved = new uint[4];
|
||||
for (int i = 0; i < fileGroup.Reserved.Length; i++)
|
||||
{
|
||||
fileGroup.Reserved[i] = data.ReadUInt32();
|
||||
}
|
||||
|
||||
// Cache the current position
|
||||
long currentPosition = data.Position;
|
||||
@@ -489,7 +485,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (majorVersion >= 17)
|
||||
fileGroup.Name = data.ReadNullTerminatedUnicodeString();
|
||||
else
|
||||
fileGroup.Name = data.ReadNullTerminatedUnicodeString();
|
||||
fileGroup.Name = data.ReadNullTerminatedAnsiString();
|
||||
}
|
||||
|
||||
// Seek back to the correct offset
|
||||
@@ -512,15 +508,19 @@ namespace SabreTools.Serialization.Deserializers
|
||||
component.IdentifierOffset = data.ReadUInt32();
|
||||
component.DescriptorOffset = data.ReadUInt32();
|
||||
component.DisplayNameOffset = data.ReadUInt32();
|
||||
component.Reserved0 = data.ReadUInt16();
|
||||
component.ReservedOffset0 = data.ReadUInt32();
|
||||
component.ReservedOffset1 = data.ReadUInt32();
|
||||
component.Status = (ComponentStatus)data.ReadUInt16();
|
||||
component.PasswordOffset = data.ReadUInt32();
|
||||
component.MiscOffset = data.ReadUInt32();
|
||||
component.ComponentIndex = data.ReadUInt16();
|
||||
component.NameOffset = data.ReadUInt32();
|
||||
component.ReservedOffset2 = data.ReadUInt32();
|
||||
component.ReservedOffset3 = data.ReadUInt32();
|
||||
component.ReservedOffset4 = data.ReadUInt32();
|
||||
component.Reserved1 = data.ReadBytes(32);
|
||||
component.CDRomFolderOffset = data.ReadUInt32();
|
||||
component.HTTPLocationOffset = data.ReadUInt32();
|
||||
component.FTPLocationOffset = data.ReadUInt32();
|
||||
component.Guid = new Guid[2];
|
||||
for (int i = 0; i < component.Guid.Length; i++)
|
||||
{
|
||||
component.Guid[i] = data.ReadGuid();
|
||||
}
|
||||
component.CLSIDOffset = data.ReadUInt32();
|
||||
component.Reserved2 = data.ReadBytes(28);
|
||||
component.Reserved3 = data.ReadBytes(majorVersion <= 5 ? 2 : 1);
|
||||
@@ -533,10 +533,10 @@ namespace SabreTools.Serialization.Deserializers
|
||||
component.SubComponentsCount = data.ReadUInt16();
|
||||
component.SubComponentsOffset = data.ReadUInt32();
|
||||
component.NextComponentOffset = data.ReadUInt32();
|
||||
component.ReservedOffset5 = data.ReadUInt32();
|
||||
component.ReservedOffset6 = data.ReadUInt32();
|
||||
component.ReservedOffset7 = data.ReadUInt32();
|
||||
component.ReservedOffset8 = data.ReadUInt32();
|
||||
component.OnInstallingOffset = data.ReadUInt32();
|
||||
component.OnInstalledOffset = data.ReadUInt32();
|
||||
component.OnUninstallingOffset = data.ReadUInt32();
|
||||
component.OnUninstalledOffset = data.ReadUInt32();
|
||||
|
||||
// Cache the current position
|
||||
long currentPosition = data.Position;
|
||||
|
||||
@@ -476,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)
|
||||
@@ -810,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)
|
||||
@@ -831,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)
|
||||
@@ -862,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)
|
||||
|
||||
@@ -23,7 +23,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
var sets = new List<Set>();
|
||||
var rows = new List<Row>();
|
||||
|
||||
var additional = new List<string>();
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
// Read the line and don't split yet
|
||||
@@ -33,7 +32,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// If we have a set to process
|
||||
if (set != null)
|
||||
{
|
||||
set.Row = rows.ToArray();
|
||||
set.Row = [.. rows];
|
||||
sets.Add(set);
|
||||
set = null;
|
||||
rows.Clear();
|
||||
@@ -215,7 +214,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
default:
|
||||
row = null;
|
||||
additional.Add(line);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -226,15 +224,14 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// If we have a set to process
|
||||
if (set != null)
|
||||
{
|
||||
set.Row = rows.ToArray();
|
||||
set.Row = [.. rows];
|
||||
sets.Add(set);
|
||||
set = null;
|
||||
rows.Clear();
|
||||
}
|
||||
|
||||
// Add extra pieces and return
|
||||
dat.Set = sets.ToArray();
|
||||
dat.ADDITIONAL_ELEMENTS = additional.ToArray();
|
||||
dat.Set = [.. sets];
|
||||
return dat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
hashTable.Add(hashEntry);
|
||||
}
|
||||
|
||||
archive.HashTable = hashTable.ToArray();
|
||||
archive.HashTable = [.. hashTable];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
hashTable.Add(hashEntry);
|
||||
}
|
||||
|
||||
archive.HashTable = hashTable.ToArray();
|
||||
archive.HashTable = [.. hashTable];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
hashTable.Add(hashEntry);
|
||||
}
|
||||
|
||||
archive.HashTable = hashTable.ToArray();
|
||||
archive.HashTable = [.. hashTable];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
blockTable.Add(blockEntry);
|
||||
}
|
||||
|
||||
archive.BlockTable = blockTable.ToArray();
|
||||
archive.BlockTable = [.. blockTable];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
blockTable.Add(blockEntry);
|
||||
}
|
||||
|
||||
archive.BlockTable = blockTable.ToArray();
|
||||
archive.BlockTable = [.. blockTable];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,7 +251,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
blockTable.Add(blockEntry);
|
||||
}
|
||||
|
||||
archive.BlockTable = blockTable.ToArray();
|
||||
archive.BlockTable = [.. blockTable];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
hiBlockTable.Add(hiBlockEntry);
|
||||
}
|
||||
|
||||
archive.HiBlockTable = hiBlockTable.ToArray();
|
||||
archive.HiBlockTable = [.. hiBlockTable];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
return null;
|
||||
|
||||
// Cache the current offset
|
||||
int initialOffset = (int)data.Position;
|
||||
long initialOffset = data.Position;
|
||||
|
||||
// Create a new cart image to fill
|
||||
var cart = new Cart();
|
||||
@@ -62,118 +62,74 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
#endregion
|
||||
|
||||
#region Partitions
|
||||
|
||||
// Create the partition table
|
||||
cart.Partitions = new NCCHHeader[8];
|
||||
|
||||
// Iterate and build the partitions
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
cart.Partitions[i] = ParseNCCHHeader(data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
// Cache the media unit size for further use
|
||||
long mediaUnitSize = 0;
|
||||
if (header.PartitionFlags != null)
|
||||
mediaUnitSize = (uint)(0x200 * Math.Pow(2, header.PartitionFlags[(int)NCSDFlags.MediaUnitSize]));
|
||||
|
||||
#region Extended Headers
|
||||
#region Partitions
|
||||
|
||||
// Create the extended header table
|
||||
cart.ExtendedHeaders = new NCCHExtendedHeader[8];
|
||||
// Create the tables
|
||||
cart.Partitions = new NCCHHeader[8];
|
||||
cart.ExtendedHeaders = new NCCHExtendedHeader?[8];
|
||||
cart.ExeFSHeaders = new ExeFSHeader?[8];
|
||||
cart.RomFSHeaders = new RomFSHeader?[8];
|
||||
|
||||
// Iterate and build the extended headers
|
||||
// Iterate and build the partitions
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// If we have an encrypted or invalid partition
|
||||
if (cart.Partitions[i]!.MagicID != NCCHMagicNumber)
|
||||
// Find the offset to the partition
|
||||
long partitionOffset = cart.Header.PartitionsTable?[i]?.Offset ?? 0;
|
||||
partitionOffset *= mediaUnitSize;
|
||||
if (partitionOffset == 0)
|
||||
continue;
|
||||
|
||||
// If we have no partitions table
|
||||
if (cart.Header!.PartitionsTable == null)
|
||||
// Seek to the start of the partition
|
||||
data.Seek(partitionOffset, SeekOrigin.Begin);
|
||||
|
||||
// Handle the normal header
|
||||
var partition = ParseNCCHHeader(data);
|
||||
if (partition == null || partition.MagicID != NCCHMagicNumber)
|
||||
continue;
|
||||
|
||||
// Get the extended header offset
|
||||
long offset = (cart.Header.PartitionsTable[i]!.Offset * mediaUnitSize) + 0x200;
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
continue;
|
||||
// Set the normal header
|
||||
cart.Partitions[i] = partition;
|
||||
|
||||
// Seek to the extended header
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
// Handle the extended header, if it exists
|
||||
if (partition.ExtendedHeaderSizeInBytes > 0)
|
||||
{
|
||||
var extendedHeader = ParseNCCHExtendedHeader(data);
|
||||
if (extendedHeader != null)
|
||||
cart.ExtendedHeaders[i] = extendedHeader;
|
||||
}
|
||||
|
||||
// Parse the extended header
|
||||
var extendedHeader = ParseNCCHExtendedHeader(data);
|
||||
if (extendedHeader != null)
|
||||
cart.ExtendedHeaders[i] = extendedHeader;
|
||||
}
|
||||
// Handle the ExeFS, if it exists
|
||||
if (partition.ExeFSSizeInMediaUnits > 0)
|
||||
{
|
||||
long offset = partition.ExeFSOffsetInMediaUnits * mediaUnitSize;
|
||||
data.Seek(partitionOffset + offset, SeekOrigin.Begin);
|
||||
|
||||
#endregion
|
||||
var exeFsHeader = ParseExeFSHeader(data);
|
||||
if (exeFsHeader == null)
|
||||
return null;
|
||||
|
||||
#region ExeFS Headers
|
||||
cart.ExeFSHeaders[i] = exeFsHeader;
|
||||
}
|
||||
|
||||
// Create the ExeFS header table
|
||||
cart.ExeFSHeaders = new ExeFSHeader[8];
|
||||
// Handle the RomFS, if it exists
|
||||
if (partition.RomFSSizeInMediaUnits > 0)
|
||||
{
|
||||
long offset = partition.RomFSOffsetInMediaUnits * mediaUnitSize;
|
||||
data.Seek(partitionOffset + offset, SeekOrigin.Begin);
|
||||
|
||||
// Iterate and build the ExeFS headers
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// If we have an encrypted or invalid partition
|
||||
if (cart.Partitions[i]!.MagicID != NCCHMagicNumber)
|
||||
continue;
|
||||
var romFsHeader = ParseRomFSHeader(data);
|
||||
if (romFsHeader == null)
|
||||
continue;
|
||||
else if (romFsHeader.MagicString != RomFSMagicNumber || romFsHeader.MagicNumber != RomFSSecondMagicNumber)
|
||||
continue;
|
||||
|
||||
// If we have no partitions table
|
||||
if (cart.Header!.PartitionsTable == null)
|
||||
continue;
|
||||
|
||||
// Get the ExeFS header offset
|
||||
long offset = (cart.Header.PartitionsTable[i]!.Offset + cart.Partitions[i]!.ExeFSOffsetInMediaUnits) * mediaUnitSize;
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
continue;
|
||||
|
||||
// Seek to the ExeFS header
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Parse the ExeFS header
|
||||
var exeFsHeader = ParseExeFSHeader(data);
|
||||
if (exeFsHeader == null)
|
||||
return null;
|
||||
|
||||
cart.ExeFSHeaders[i] = exeFsHeader;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region RomFS Headers
|
||||
|
||||
// Create the RomFS header table
|
||||
cart.RomFSHeaders = new RomFSHeader[8];
|
||||
|
||||
// Iterate and build the RomFS headers
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
// If we have an encrypted or invalid partition
|
||||
if (cart.Partitions[i]!.MagicID != NCCHMagicNumber)
|
||||
continue;
|
||||
|
||||
// If we have no partitions table
|
||||
if (cart.Header!.PartitionsTable == null)
|
||||
continue;
|
||||
|
||||
// Get the RomFS header offset
|
||||
long offset = (cart.Header.PartitionsTable[i]!.Offset + cart.Partitions[i]!.RomFSOffsetInMediaUnits) * mediaUnitSize;
|
||||
if (offset < 0 || offset >= data.Length)
|
||||
continue;
|
||||
|
||||
// Seek to the RomFS header
|
||||
data.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
// Parse the RomFS header
|
||||
var romFsHeader = ParseRomFSHeader(data);
|
||||
if (romFsHeader != null)
|
||||
cart.RomFSHeaders[i] = romFsHeader;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -259,7 +215,43 @@ namespace SabreTools.Serialization.Deserializers
|
||||
/// <returns>Filled card info header on success, null on error</returns>
|
||||
public static CardInfoHeader? ParseCardInfoHeader(Stream data)
|
||||
{
|
||||
return data.ReadType<CardInfoHeader>();
|
||||
// TODO: Use marshalling here instead of building
|
||||
var header = new CardInfoHeader();
|
||||
|
||||
header.WritableAddressMediaUnits = data.ReadUInt32();
|
||||
header.CardInfoBitmask = data.ReadUInt32();
|
||||
header.Reserved1 = data.ReadBytes(0xF8);
|
||||
header.FilledSize = data.ReadUInt32();
|
||||
header.Reserved2 = data.ReadBytes(0x0C);
|
||||
header.TitleVersion = data.ReadUInt16();
|
||||
header.CardRevision = data.ReadUInt16();
|
||||
header.Reserved3 = data.ReadBytes(0x0C);
|
||||
header.CVerTitleID = data.ReadBytes(0x08);
|
||||
header.CVerVersionNumber = data.ReadUInt16();
|
||||
header.Reserved4 = data.ReadBytes(0xCD6);
|
||||
header.InitialData = ParseInitialData(data);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into initial data
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled initial data on success, null on error</returns>
|
||||
public static InitialData? ParseInitialData(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
var id = new InitialData();
|
||||
|
||||
id.CardSeedKeyY = data.ReadBytes(0x10);
|
||||
id.EncryptedCardSeed = data.ReadBytes(0x10);
|
||||
id.CardSeedAESMAC = data.ReadBytes(0x10);
|
||||
id.CardSeedNonce = data.ReadBytes(0x0C);
|
||||
id.Reserved = data.ReadBytes(0xC4);
|
||||
id.BackupHeader = ParseNCCHHeader(data, skipSignature: true);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -339,7 +331,51 @@ namespace SabreTools.Serialization.Deserializers
|
||||
/// <returns>Filled NCCH extended header on success, null on error</returns>
|
||||
public static NCCHExtendedHeader? ParseNCCHExtendedHeader(Stream data)
|
||||
{
|
||||
return data.ReadType<NCCHExtendedHeader>();
|
||||
// TODO: Replace with `data.ReadType<NCCHExtendedHeader>();` when enum serialization fixed
|
||||
var header = new NCCHExtendedHeader();
|
||||
|
||||
header.SCI = data.ReadType<SystemControlInfo>();
|
||||
header.ACI = ParseAccessControlInfo(data);
|
||||
header.AccessDescSignature = data.ReadBytes(0x100);
|
||||
header.NCCHHDRPublicKey = data.ReadBytes(0x100);
|
||||
header.ACIForLimitations = ParseAccessControlInfo(data);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
/// <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>
|
||||
public static AccessControlInfo? ParseAccessControlInfo(Stream data)
|
||||
{
|
||||
var aci = new AccessControlInfo();
|
||||
|
||||
aci.ARM11LocalSystemCapabilities = data.ReadType<ARM11LocalSystemCapabilities>();
|
||||
aci.ARM11KernelCapabilities = data.ReadType<ARM11KernelCapabilities>();
|
||||
aci.ARM9AccessControl = ParseARM9AccessControl(data);
|
||||
|
||||
return aci;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a Stream into an ARM9 access control
|
||||
/// </summary>
|
||||
/// <param name="data">Stream to parse</param>
|
||||
/// <returns>Filled ARM9 access control on success, null on error</returns>
|
||||
public static ARM9AccessControl? ParseARM9AccessControl(Stream data)
|
||||
{
|
||||
var a9ac = new ARM9AccessControl();
|
||||
|
||||
a9ac.Descriptors = new ARM9AccessControlDescriptors[15];
|
||||
for (int i = 0; i < a9ac.Descriptors.Length; i++)
|
||||
{
|
||||
a9ac.Descriptors[i] = (ARM9AccessControlDescriptors)data.ReadByteValue();
|
||||
}
|
||||
a9ac.DescriptorVersion = data.ReadByteValue();
|
||||
|
||||
return a9ac;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.NewExecutable;
|
||||
using static SabreTools.Models.NewExecutable.Constants;
|
||||
@@ -76,7 +75,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;
|
||||
|
||||
@@ -262,7 +261,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
/// <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;
|
||||
|
||||
@@ -270,13 +269,23 @@ 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++)
|
||||
{
|
||||
@@ -287,22 +296,40 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
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)
|
||||
.Select(rt => rt!.TypeID)
|
||||
.Union(resourceTable.ResourceTypes
|
||||
.Where(rt => rt != null)
|
||||
.SelectMany(rt => rt!.Resources ?? [])
|
||||
.Where(r => r!.IsIntegerType() == false)
|
||||
.Select(r => r!.ResourceID))
|
||||
.Distinct()
|
||||
.OrderBy(o => o)
|
||||
.ToList();
|
||||
var stringOffsets = new List<ushort>();
|
||||
foreach (var rtie in resourceTable.ResourceTypes)
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (rtie == null || rtie.TypeID == 0)
|
||||
continue;
|
||||
|
||||
// Handle offset types
|
||||
if (!rtie.IsIntegerType() && !stringOffsets.Contains(rtie.TypeID))
|
||||
stringOffsets.Add(rtie.TypeID);
|
||||
|
||||
// Handle types with resources
|
||||
foreach (var rtre in rtie.Resources ?? [])
|
||||
{
|
||||
// Skip invalid entries
|
||||
if (rtre == null || rtre.IsIntegerType() || rtre.ResourceID == 0)
|
||||
continue;
|
||||
|
||||
// Skip already added entries
|
||||
if (stringOffsets.Contains(rtre.ResourceID))
|
||||
continue;
|
||||
|
||||
stringOffsets.Add(rtre.ResourceID);
|
||||
}
|
||||
}
|
||||
|
||||
// Order the offsets list
|
||||
stringOffsets.Sort();
|
||||
|
||||
// Populate the type and name string dictionary
|
||||
resourceTable.TypeAndNameStrings = [];
|
||||
@@ -359,7 +386,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// 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 = ParseResidentNameTableEntry(data);
|
||||
if (entry == null)
|
||||
@@ -432,7 +459,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// TODO: Use marshalling here instead of building
|
||||
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 = ParseImportedNameTableEntry(data);
|
||||
@@ -472,7 +499,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();
|
||||
@@ -511,7 +538,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// 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 = ParseNonResidentNameTableEntry(data);
|
||||
if (entry == null)
|
||||
|
||||
@@ -110,7 +110,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Set the file allocation table
|
||||
cart.FileAllocationTable = fileAllocationTable.ToArray();
|
||||
cart.FileAllocationTable = [.. fileAllocationTable];
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -170,7 +170,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Assign the folder allocation table
|
||||
nameTable.FolderAllocationTable = folderAllocationTable.ToArray();
|
||||
nameTable.FolderAllocationTable = [.. folderAllocationTable];
|
||||
|
||||
// Create a variable-length table
|
||||
var nameList = new List<NameListEntry>();
|
||||
@@ -184,7 +184,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Assign the name list
|
||||
nameTable.NameList = nameList.ToArray();
|
||||
nameTable.NameList = [.. nameList];
|
||||
|
||||
return nameTable;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
|
||||
// Assign the units and return
|
||||
di.Units = diUnits.ToArray();
|
||||
di.Units = [.. diUnits];
|
||||
return di;
|
||||
}
|
||||
|
||||
|
||||
697
SabreTools.Serialization/Deserializers/PKZIP.cs
Normal file
697
SabreTools.Serialization/Deserializers/PKZIP.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
#if NET35_OR_GREATER || NETCOREAPP
|
||||
using System.Linq;
|
||||
#endif
|
||||
using System.Text;
|
||||
using SabreTools.IO.Extensions;
|
||||
using SabreTools.Models.PortableExecutable;
|
||||
@@ -495,7 +497,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;
|
||||
|
||||
@@ -668,7 +670,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);
|
||||
@@ -678,7 +680,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
_ = data.ReadByteValue();
|
||||
}
|
||||
|
||||
return attributeCertificateTable.ToArray();
|
||||
return [.. attributeCertificateTable];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -703,7 +705,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();
|
||||
|
||||
@@ -724,12 +726,12 @@ namespace SabreTools.Serialization.Deserializers
|
||||
totalSize += 2;
|
||||
}
|
||||
|
||||
baseRelocationBlock.TypeOffsetFieldEntries = typeOffsetFieldEntries.ToArray();
|
||||
baseRelocationBlock.TypeOffsetFieldEntries = [.. typeOffsetFieldEntries];
|
||||
|
||||
baseRelocationTable.Add(baseRelocationBlock);
|
||||
}
|
||||
|
||||
return baseRelocationTable.ToArray();
|
||||
return [.. baseRelocationTable];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -745,7 +747,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
var debugDirectoryTable = new List<DebugDirectoryEntry>();
|
||||
|
||||
while (data.Position < endOffset)
|
||||
while (data.Position < endOffset && data.Position < data.Length)
|
||||
{
|
||||
var debugDirectoryEntry = data.ReadType<DebugDirectoryEntry>();
|
||||
if (debugDirectoryEntry == null)
|
||||
@@ -913,7 +915,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
break;
|
||||
}
|
||||
|
||||
importTable.ImportDirectoryTable = importDirectoryTable.ToArray();
|
||||
importTable.ImportDirectoryTable = [.. importDirectoryTable];
|
||||
|
||||
// Names
|
||||
for (int i = 0; i < importTable.ImportDirectoryTable.Length; i++)
|
||||
@@ -981,7 +983,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
break;
|
||||
}
|
||||
|
||||
importLookupTables[i] = entryLookupTable.ToArray();
|
||||
importLookupTables[i] = [.. entryLookupTable];
|
||||
}
|
||||
|
||||
importTable.ImportLookupTables = importLookupTables;
|
||||
@@ -1035,7 +1037,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
break;
|
||||
}
|
||||
|
||||
importAddressTables[i] = addressLookupTable.ToArray();
|
||||
importAddressTables[i] = [.. addressLookupTable];
|
||||
}
|
||||
|
||||
importTable.ImportAddressTables = importAddressTables;
|
||||
@@ -1047,38 +1049,70 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|| importTable.ImportAddressTables != null && importTable.ImportAddressTables.Count > 0)
|
||||
{
|
||||
// Get the addresses of the hint/name table entries
|
||||
List<int> hintNameTableEntryAddresses = new List<int>();
|
||||
var hintNameTableEntryAddresses = new List<int>();
|
||||
|
||||
// If we have import lookup tables
|
||||
if (importTable.ImportLookupTables != null && importLookupTables.Count > 0)
|
||||
{
|
||||
#if NET20
|
||||
var addresses = new List<int>();
|
||||
foreach (var kvp in importTable.ImportLookupTables)
|
||||
{
|
||||
if (kvp.Value == null)
|
||||
continue;
|
||||
|
||||
var vaddrs = Array.ConvertAll(kvp.Value,
|
||||
ilte => ilte == null ? 0 : (int)ilte.HintNameTableRVA.ConvertVirtualAddress(sections));
|
||||
addresses.AddRange(vaddrs);
|
||||
}
|
||||
#else
|
||||
var addresses = importTable.ImportLookupTables
|
||||
.Where(kvp => kvp.Value != null)
|
||||
.SelectMany(kvp => kvp.Value!)
|
||||
.SelectMany(kvp => kvp.Value ?? [])
|
||||
.Where(ilte => ilte != null)
|
||||
.Select(ilte => (int)ilte!.HintNameTableRVA.ConvertVirtualAddress(sections));
|
||||
#endif
|
||||
hintNameTableEntryAddresses.AddRange(addresses);
|
||||
}
|
||||
|
||||
// If we have import address tables
|
||||
if (importTable.ImportAddressTables != null && importTable.ImportAddressTables.Count > 0)
|
||||
{
|
||||
#if NET20
|
||||
var addresses = new List<int>();
|
||||
foreach (var kvp in importTable.ImportAddressTables)
|
||||
{
|
||||
if (kvp.Value == null)
|
||||
continue;
|
||||
|
||||
var vaddrs = Array.ConvertAll(kvp.Value,
|
||||
iate => iate == null ? 0 : (int)iate.HintNameTableRVA.ConvertVirtualAddress(sections));
|
||||
addresses.AddRange(vaddrs);
|
||||
}
|
||||
#else
|
||||
var addresses = importTable.ImportAddressTables
|
||||
.Where(kvp => kvp.Value != null)
|
||||
.SelectMany(kvp => kvp.Value!)
|
||||
.SelectMany(kvp => kvp.Value ?? [])
|
||||
.Where(iate => iate != null)
|
||||
.Select(iate => (int)iate!.HintNameTableRVA.ConvertVirtualAddress(sections));
|
||||
#endif
|
||||
hintNameTableEntryAddresses.AddRange(addresses);
|
||||
}
|
||||
|
||||
// Sanitize the addresses
|
||||
hintNameTableEntryAddresses = hintNameTableEntryAddresses.Where(addr => addr != 0)
|
||||
.Distinct()
|
||||
.OrderBy(a => a)
|
||||
.ToList();
|
||||
hintNameTableEntryAddresses = hintNameTableEntryAddresses.FindAll(addr => addr != 0);
|
||||
#if NET20
|
||||
var temp = new List<int>();
|
||||
foreach (int value in hintNameTableEntryAddresses)
|
||||
{
|
||||
if (!temp.Contains(value))
|
||||
temp.Add(value);
|
||||
}
|
||||
#else
|
||||
hintNameTableEntryAddresses = hintNameTableEntryAddresses.Distinct().ToList();
|
||||
#endif
|
||||
hintNameTableEntryAddresses.Sort();
|
||||
|
||||
// If we have any addresses, add them to the table
|
||||
if (hintNameTableEntryAddresses.Any())
|
||||
if (hintNameTableEntryAddresses.Count > 0)
|
||||
{
|
||||
for (int i = 0; i < hintNameTableEntryAddresses.Count; i++)
|
||||
{
|
||||
@@ -1164,7 +1198,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;
|
||||
@@ -1194,7 +1228,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);
|
||||
@@ -1216,11 +1250,12 @@ namespace SabreTools.Serialization.Deserializers
|
||||
return resourceDirectoryTable;
|
||||
|
||||
// If we're not aligned to a section
|
||||
if (!sections.Any(s => s != null && s.PointerToRawData == initialOffset))
|
||||
var firstSection = Array.Find(sections, s => s != null && s.PointerToRawData == initialOffset);
|
||||
if (firstSection == null)
|
||||
return resourceDirectoryTable;
|
||||
|
||||
// Get the section size
|
||||
int size = (int)sections.First(s => s != null && s.PointerToRawData == initialOffset)!.SizeOfRawData;
|
||||
int size = (int)firstSection.SizeOfRawData;
|
||||
|
||||
// Align to the 512-byte boundary, we find the start of an MS-DOS header, or the end of the file
|
||||
while (data.Position - initialOffset < size && data.Position % 0x200 != 0 && data.Position < data.Length - 1)
|
||||
@@ -1246,7 +1281,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
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Readers;
|
||||
using SabreTools.Models.RomCenter;
|
||||
@@ -25,11 +24,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// Loop through and parse out the values
|
||||
var roms = new List<Rom>();
|
||||
var additional = new List<string>();
|
||||
var creditsAdditional = new List<string>();
|
||||
var datAdditional = new List<string>();
|
||||
var emulatorAdditional = new List<string>();
|
||||
var gamesAdditional = new List<string>();
|
||||
while (!reader.EndOfStream)
|
||||
{
|
||||
// If we have no next line
|
||||
@@ -57,10 +51,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "games":
|
||||
dat.Games ??= new Games();
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
additional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -94,10 +84,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "comment":
|
||||
dat.Credits.Comment = reader.KeyValuePair?.Value;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
creditsAdditional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,10 +107,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "merge":
|
||||
dat.Dat.Merge = reader.KeyValuePair?.Value;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
datAdditional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,10 +124,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
case "version":
|
||||
dat.Emulator.Version = reader.KeyValuePair?.Value;
|
||||
break;
|
||||
default:
|
||||
if (reader.CurrentLine != null)
|
||||
emulatorAdditional.Add(reader.CurrentLine);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,13 +134,12 @@ namespace SabreTools.Serialization.Deserializers
|
||||
dat.Games ??= new Games();
|
||||
|
||||
// If the line doesn't contain the delimiter
|
||||
#if NETFRAMEWORK
|
||||
if (!(reader.CurrentLine?.Contains("¬") ?? false))
|
||||
#else
|
||||
if (!(reader.CurrentLine?.Contains('¬') ?? false))
|
||||
{
|
||||
if (reader.CurrentLine != null)
|
||||
gamesAdditional.Add(reader.CurrentLine);
|
||||
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
|
||||
// Otherwise, separate out the line
|
||||
string[] splitLine = reader.CurrentLine.Split('¬');
|
||||
@@ -181,32 +158,14 @@ namespace SabreTools.Serialization.Deserializers
|
||||
// EMPTY = splitLine[10]
|
||||
};
|
||||
|
||||
if (splitLine.Length > 11)
|
||||
rom.ADDITIONAL_ELEMENTS = splitLine.Skip(11).ToArray();
|
||||
|
||||
roms.Add(rom);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
if (reader.CurrentLine != null)
|
||||
additional.Add(reader.CurrentLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Add extra pieces and return
|
||||
dat.ADDITIONAL_ELEMENTS = additional.Where(s => s != null).ToArray();
|
||||
if (dat.Credits != null)
|
||||
dat.Credits.ADDITIONAL_ELEMENTS = creditsAdditional.Where(s => s != null).ToArray();
|
||||
if (dat.Dat != null)
|
||||
dat.Dat.ADDITIONAL_ELEMENTS = datAdditional.Where(s => s != null).ToArray();
|
||||
if (dat.Emulator != null)
|
||||
dat.Emulator.ADDITIONAL_ELEMENTS = emulatorAdditional.Where(s => s != null).ToArray();
|
||||
if (dat.Games != null)
|
||||
{
|
||||
dat.Games.Rom = roms.ToArray();
|
||||
dat.Games.ADDITIONAL_ELEMENTS = gamesAdditional.Where(s => s != null).Select(s => s).ToArray();
|
||||
}
|
||||
dat.Games.Rom = [.. roms];
|
||||
|
||||
return dat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using SabreTools.IO.Readers;
|
||||
using SabreTools.Models.SeparatedValue;
|
||||
@@ -104,7 +103,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
if (!reader.ReadHeader() || reader.HeaderValues == null)
|
||||
return null;
|
||||
|
||||
dat.Header = reader.HeaderValues.ToArray();
|
||||
dat.Header = [.. reader.HeaderValues];
|
||||
|
||||
// Loop through the rows and parse out values
|
||||
var rows = new List<Row>();
|
||||
@@ -135,10 +134,6 @@ namespace SabreTools.Serialization.Deserializers
|
||||
SHA256 = reader.Line[12],
|
||||
Status = reader.Line[13],
|
||||
};
|
||||
|
||||
// If we have additional fields
|
||||
if (reader.Line.Count > HeaderWithoutExtendedHashesCount)
|
||||
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithoutExtendedHashesCount).ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -162,16 +157,12 @@ namespace SabreTools.Serialization.Deserializers
|
||||
SpamSum = reader.Line[15],
|
||||
Status = reader.Line[16],
|
||||
};
|
||||
|
||||
// If we have additional fields
|
||||
if (reader.Line.Count > HeaderWithExtendedHashesCount)
|
||||
row.ADDITIONAL_ELEMENTS = reader.Line.Skip(HeaderWithExtendedHashesCount).ToArray();
|
||||
}
|
||||
rows.Add(row);
|
||||
}
|
||||
|
||||
// Assign the rows to the Dat and return
|
||||
dat.Row = rows.ToArray();
|
||||
dat.Row = [.. rows];
|
||||
return dat;
|
||||
}
|
||||
|
||||
|
||||
@@ -67,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>();
|
||||
@@ -192,7 +195,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
}
|
||||
}
|
||||
|
||||
return directoryItems.ToArray();
|
||||
return [.. directoryItems];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -218,7 +221,9 @@ namespace SabreTools.Serialization.Deserializers
|
||||
|
||||
// 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;
|
||||
@@ -231,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;
|
||||
|
||||
@@ -184,7 +184,7 @@ namespace SabreTools.Serialization.Deserializers
|
||||
private static DirectoryItem ParseDirectoryItem(Stream data)
|
||||
{
|
||||
// TODO: Use marshalling here instead of building
|
||||
DirectoryItem directoryItem = new DirectoryItem();
|
||||
var directoryItem = new DirectoryItem();
|
||||
|
||||
directoryItem.FileNameCRC = data.ReadUInt32();
|
||||
directoryItem.NameOffset = data.ReadUInt32();
|
||||
|
||||
9
SabreTools.Serialization/ExtensionAttribute.cs
Normal file
9
SabreTools.Serialization/ExtensionAttribute.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
#if NET20
|
||||
|
||||
namespace System.Runtime.CompilerServices
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Method)]
|
||||
internal sealed class ExtensionAttribute : Attribute {}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -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;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Xml.Serialization;
|
||||
using SabreTools.IO.Extensions;
|
||||
@@ -28,7 +27,7 @@ namespace SabreTools.Serialization
|
||||
return 0;
|
||||
|
||||
// If the RVA matches a section start exactly, use that
|
||||
var matchingSection = sections.FirstOrDefault(s => s != null && s.VirtualAddress == rva);
|
||||
var matchingSection = Array.Find(sections, s => s != null && s.VirtualAddress == rva);
|
||||
if (matchingSection != null)
|
||||
return rva - matchingSection.VirtualAddress + matchingSection.PointerToRawData;
|
||||
|
||||
@@ -127,6 +126,15 @@ namespace SabreTools.Serialization
|
||||
if (rsdsProgramDatabase.Signature != 0x53445352)
|
||||
return null;
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -156,7 +164,9 @@ namespace SabreTools.Serialization
|
||||
if (string.IsNullOrEmpty(addD.Version))
|
||||
offset = originalOffset + 0x10;
|
||||
|
||||
addD.Build = data.ReadBytes(ref offset, 4)?.Select(b => (char)b)?.ToArray();
|
||||
var buildBytes = data.ReadBytes(ref offset, 4);
|
||||
var buildChars = Array.ConvertAll(buildBytes, b => (char)b);
|
||||
addD.Build = buildChars;
|
||||
|
||||
// Distinguish between v1 and v2
|
||||
int bytesToRead = 112; // v2
|
||||
@@ -595,7 +605,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
|
||||
@@ -631,7 +645,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
|
||||
@@ -891,7 +909,7 @@ namespace SabreTools.Serialization
|
||||
if (menuHeaderExtended == null)
|
||||
return null;
|
||||
|
||||
menuResource.ExtendedMenuHeader = menuHeaderExtended;
|
||||
menuResource.MenuHeader = menuHeaderExtended;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -920,7 +938,7 @@ namespace SabreTools.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
menuResource.ExtendedMenuItems = [.. extendedMenuItems];
|
||||
menuResource.MenuItems = [.. extendedMenuItems];
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -928,7 +946,7 @@ namespace SabreTools.Serialization
|
||||
{
|
||||
#region Menu header
|
||||
|
||||
var menuHeader = entry.Data.ReadType<MenuHeader>(ref offset);
|
||||
var menuHeader = entry.Data.ReadType<NormalMenuHeader>(ref offset);
|
||||
if (menuHeader == null)
|
||||
return null;
|
||||
|
||||
@@ -1067,21 +1085,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;
|
||||
}
|
||||
@@ -1118,7 +1124,7 @@ 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 = entry.Data.ReadType<FixedFileInfo>(ref offset);
|
||||
|
||||
|
||||
18
SabreTools.Serialization/Interfaces/IPrinter.cs
Normal file
18
SabreTools.Serialization/Interfaces/IPrinter.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
454
SabreTools.Serialization/Printer.cs
Normal file
454
SabreTools.Serialization/Printer.cs
Normal file
@@ -0,0 +1,454 @@
|
||||
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.CHD 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.CHD 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.CHD item)
|
||||
{
|
||||
var builder = new StringBuilder();
|
||||
CHD.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
|
||||
}
|
||||
}
|
||||
290
SabreTools.Serialization/Printers/AACSMediaKeyBlock.cs
Normal file
290
SabreTools.Serialization/Printers/AACSMediaKeyBlock.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
28
SabreTools.Serialization/Printers/BDPlusSVM.cs
Normal file
28
SabreTools.Serialization/Printers/BDPlusSVM.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
68
SabreTools.Serialization/Printers/BFPK.cs
Normal file
68
SabreTools.Serialization/Printers/BFPK.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
150
SabreTools.Serialization/Printers/BSP.cs
Normal file
150
SabreTools.Serialization/Printers/BSP.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
125
SabreTools.Serialization/Printers/CFB.cs
Normal file
125
SabreTools.Serialization/Printers/CFB.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
159
SabreTools.Serialization/Printers/CHD.cs
Normal file
159
SabreTools.Serialization/Printers/CHD.cs
Normal file
@@ -0,0 +1,159 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using SabreTools.Models.CHD;
|
||||
using SabreTools.Serialization.Interfaces;
|
||||
|
||||
namespace SabreTools.Serialization.Printers
|
||||
{
|
||||
public class CHD : IPrinter<Header>
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public void PrintInformation(StringBuilder builder, Header model)
|
||||
=> Print(builder, model);
|
||||
|
||||
public static void Print(StringBuilder builder, Header header)
|
||||
{
|
||||
builder.AppendLine("CHD Header Information:");
|
||||
builder.AppendLine("-------------------------");
|
||||
|
||||
if (header == null)
|
||||
{
|
||||
builder.AppendLine("No header");
|
||||
builder.AppendLine();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (header)
|
||||
{
|
||||
case HeaderV1 v1:
|
||||
Print(builder, v1);
|
||||
break;
|
||||
case HeaderV2 v2:
|
||||
Print(builder, v2);
|
||||
break;
|
||||
case HeaderV3 v3:
|
||||
Print(builder, v3);
|
||||
break;
|
||||
case HeaderV4 v4:
|
||||
Print(builder, v4);
|
||||
break;
|
||||
case HeaderV5 v5:
|
||||
Print(builder, v5);
|
||||
break;
|
||||
default:
|
||||
builder.AppendLine("Unrecognized header type");
|
||||
builder.AppendLine();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void Print(StringBuilder builder, HeaderV1 header)
|
||||
{
|
||||
builder.AppendLine(header.Tag, $"Tag");
|
||||
builder.AppendLine(header.Length, $"Length");
|
||||
builder.AppendLine(header.Version, $"Version");
|
||||
builder.AppendLine($" Flags: {header.Flags} (0x{header.Flags:X})");
|
||||
builder.AppendLine($" Compression: {header.Compression} (0x{header.Compression:X})");
|
||||
builder.AppendLine(header.HunkSize, $"Hunk size");
|
||||
builder.AppendLine(header.TotalHunks, $"Total hunks");
|
||||
builder.AppendLine(header.Cylinders, $"Cylinders");
|
||||
builder.AppendLine(header.Heads, $"Heads");
|
||||
builder.AppendLine(header.Sectors, $"Sectors");
|
||||
builder.AppendLine(header.MD5, $"MD5");
|
||||
builder.AppendLine(header.ParentMD5, $"Parent MD5");
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
private static void Print(StringBuilder builder, HeaderV2 header)
|
||||
{
|
||||
builder.AppendLine(header.Tag, $"Tag");
|
||||
builder.AppendLine(header.Length, $"Length");
|
||||
builder.AppendLine(header.Version, $"Version");
|
||||
builder.AppendLine($" Flags: {header.Flags} (0x{header.Flags:X})");
|
||||
builder.AppendLine($" Compression: {header.Compression} (0x{header.Compression:X})");
|
||||
builder.AppendLine(header.HunkSize, $"Hunk size");
|
||||
builder.AppendLine(header.TotalHunks, $"Total hunks");
|
||||
builder.AppendLine(header.Cylinders, $"Cylinders");
|
||||
builder.AppendLine(header.Heads, $"Heads");
|
||||
builder.AppendLine(header.Sectors, $"Sectors");
|
||||
builder.AppendLine(header.MD5, $"MD5");
|
||||
builder.AppendLine(header.ParentMD5, $"Parent MD5");
|
||||
builder.AppendLine(header.BytesPerSector, $"Bytes per sector");
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
private static void Print(StringBuilder builder, HeaderV3 header)
|
||||
{
|
||||
builder.AppendLine(header.Tag, $"Tag");
|
||||
builder.AppendLine(header.Length, $"Length");
|
||||
builder.AppendLine(header.Version, $"Version");
|
||||
builder.AppendLine($" Flags: {header.Flags} (0x{header.Flags:X})");
|
||||
builder.AppendLine($" Compression: {header.Compression} (0x{header.Compression:X})");
|
||||
builder.AppendLine(header.TotalHunks, $"Total hunks");
|
||||
builder.AppendLine(header.LogicalBytes, $"Logical bytes");
|
||||
builder.AppendLine(header.MetaOffset, $"Meta offset");
|
||||
builder.AppendLine(header.MD5, $"MD5");
|
||||
builder.AppendLine(header.ParentMD5, $"Parent MD5");
|
||||
builder.AppendLine(header.HunkBytes, $"Hunk bytes");
|
||||
builder.AppendLine(header.SHA1, $"SHA-1");
|
||||
builder.AppendLine(header.ParentSHA1, $"Parent SHA-1");
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
private static void Print(StringBuilder builder, HeaderV4 header)
|
||||
{
|
||||
builder.AppendLine(header.Tag, $"Tag");
|
||||
builder.AppendLine(header.Length, $"Length");
|
||||
builder.AppendLine(header.Version, $"Version");
|
||||
builder.AppendLine($" Flags: {header.Flags} (0x{header.Flags:X})");
|
||||
builder.AppendLine($" Compression: {header.Compression} (0x{header.Compression:X})");
|
||||
builder.AppendLine(header.TotalHunks, $"Total hunks");
|
||||
builder.AppendLine(header.LogicalBytes, $"Logical bytes");
|
||||
builder.AppendLine(header.MetaOffset, $"Meta offset");
|
||||
builder.AppendLine(header.HunkBytes, $"Hunk bytes");
|
||||
builder.AppendLine(header.SHA1, $"SHA-1");
|
||||
builder.AppendLine(header.ParentSHA1, $"Parent SHA-1");
|
||||
builder.AppendLine(header.RawSHA1, $"Raw SHA-1");
|
||||
builder.AppendLine();
|
||||
}
|
||||
|
||||
private static void Print(StringBuilder builder, HeaderV5 header)
|
||||
{
|
||||
builder.AppendLine(header.Tag, $"Tag");
|
||||
builder.AppendLine(header.Length, $"Length");
|
||||
builder.AppendLine(header.Version, $"Version");
|
||||
|
||||
string compressorsLine = "Compressors: ";
|
||||
if (header.Compressors == null)
|
||||
{
|
||||
compressorsLine += "[NULL]";
|
||||
}
|
||||
else
|
||||
{
|
||||
var compressors = new List<string>();
|
||||
for (int i = 0; i < header.Compressors.Length; i++)
|
||||
{
|
||||
uint compressor = (uint)header.Compressors[i];
|
||||
byte[] compressorBytes = BitConverter.GetBytes(compressor);
|
||||
Array.Reverse(compressorBytes);
|
||||
string compressorString = Encoding.ASCII.GetString(compressorBytes);
|
||||
compressors.Add(compressorString);
|
||||
}
|
||||
|
||||
compressorsLine += string.Join(", ", [.. compressors]);
|
||||
}
|
||||
builder.AppendLine(compressorsLine);
|
||||
|
||||
builder.AppendLine(header.LogicalBytes, $"Logical bytes");
|
||||
builder.AppendLine(header.MapOffset, $"Map offset");
|
||||
builder.AppendLine(header.MetaOffset, $"Meta offset");
|
||||
builder.AppendLine(header.HunkBytes, $"Hunk bytes");
|
||||
builder.AppendLine(header.UnitBytes, $"Unit bytes");
|
||||
builder.AppendLine(header.RawSHA1, $"Raw SHA-1");
|
||||
builder.AppendLine(header.SHA1, $"SHA-1");
|
||||
builder.AppendLine(header.ParentSHA1, $"Parent SHA-1");
|
||||
builder.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
454
SabreTools.Serialization/Printers/CIA.cs
Normal file
454
SabreTools.Serialization/Printers/CIA.cs
Normal 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
539
SabreTools.Serialization/Printers/GCF.cs
Normal file
539
SabreTools.Serialization/Printers/GCF.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
55
SabreTools.Serialization/Printers/IRD.cs
Normal file
55
SabreTools.Serialization/Printers/IRD.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
409
SabreTools.Serialization/Printers/InstallShieldCabinet.cs
Normal file
409
SabreTools.Serialization/Printers/InstallShieldCabinet.cs
Normal file
@@ -0,0 +1,409 @@
|
||||
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.CompressedSize, " Compressed size");
|
||||
builder.AppendLine($" Attributes: {fileGroup.Attributes} (0x{fileGroup.Attributes:X})");
|
||||
builder.AppendLine(fileGroup.FirstFile, " First file");
|
||||
builder.AppendLine(fileGroup.LastFile, " Last file");
|
||||
builder.AppendLine(fileGroup.UnknownStringOffset, " Unknown string offset");
|
||||
builder.AppendLine(fileGroup.OperatingSystemOffset, " Operating system offset");
|
||||
builder.AppendLine(fileGroup.LanguageOffset, " Language offset");
|
||||
builder.AppendLine(fileGroup.HTTPLocationOffset, " HTTP location offset");
|
||||
builder.AppendLine(fileGroup.FTPLocationOffset, " FTP location offset");
|
||||
builder.AppendLine(fileGroup.MiscOffset, " Misc. offset");
|
||||
builder.AppendLine(fileGroup.TargetDirectoryOffset, " Target directory offset");
|
||||
builder.AppendLine($" Overwrite flags: {fileGroup.OverwriteFlags} (0x{fileGroup.OverwriteFlags:X})");
|
||||
builder.AppendLine(fileGroup.Reserved, " Reserved");
|
||||
}
|
||||
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($" Status: {component.Status} (0x{component.Status:X})");
|
||||
builder.AppendLine(component.PasswordOffset, " Password offset");
|
||||
builder.AppendLine(component.MiscOffset, " Misc. offset");
|
||||
builder.AppendLine(component.ComponentIndex, " Component index");
|
||||
builder.AppendLine(component.NameOffset, " Name offset");
|
||||
builder.AppendLine(component.Name, " Name");
|
||||
builder.AppendLine(component.CDRomFolderOffset, " CD-ROM folder offset");
|
||||
builder.AppendLine(component.HTTPLocationOffset, " HTTP location offset");
|
||||
builder.AppendLine(component.FTPLocationOffset, " FTP location offset");
|
||||
builder.AppendLine(component.Guid, " GUIDs");
|
||||
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.OnInstallingOffset, " On installing offset");
|
||||
builder.AppendLine(component.OnInstalledOffset, " On installed offset");
|
||||
builder.AppendLine(component.OnUninstallingOffset, " On uninstalling offset");
|
||||
builder.AppendLine(component.OnUninstalledOffset, " On uninstalled offset");
|
||||
}
|
||||
builder.AppendLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
783
SabreTools.Serialization/Printers/LinearExecutable.cs
Normal file
783
SabreTools.Serialization/Printers/LinearExecutable.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
78
SabreTools.Serialization/Printers/MSDOS.cs
Normal file
78
SabreTools.Serialization/Printers/MSDOS.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
172
SabreTools.Serialization/Printers/MicrosoftCabinet.cs
Normal file
172
SabreTools.Serialization/Printers/MicrosoftCabinet.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
243
SabreTools.Serialization/Printers/MoPaQ.cs
Normal file
243
SabreTools.Serialization/Printers/MoPaQ.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
695
SabreTools.Serialization/Printers/N3DS.cs
Normal file
695
SabreTools.Serialization/Printers/N3DS.cs
Normal file
@@ -0,0 +1,695 @@
|
||||
using System;
|
||||
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();
|
||||
|
||||
Print(builder, header.InitialData);
|
||||
}
|
||||
|
||||
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(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, InitialData? id)
|
||||
{
|
||||
builder.AppendLine(" Initial Data Information:");
|
||||
builder.AppendLine(" -------------------------");
|
||||
if (id == null)
|
||||
{
|
||||
builder.AppendLine(" No initial data");
|
||||
builder.AppendLine();
|
||||
return;
|
||||
}
|
||||
|
||||
builder.AppendLine(id.CardSeedKeyY, " Card seed KeyY");
|
||||
builder.AppendLine(id.EncryptedCardSeed, " Encrypted card seed");
|
||||
builder.AppendLine(id.CardSeedAESMAC, " Card seed AES-MAC");
|
||||
builder.AppendLine(id.CardSeedNonce, " Card seed nonce");
|
||||
builder.AppendLine(id.Reserved, " Reserved");
|
||||
builder.AppendLine();
|
||||
|
||||
PrintBackup(builder, id.BackupHeader);
|
||||
}
|
||||
|
||||
private static void PrintBackup(StringBuilder builder, NCCHHeader? header)
|
||||
{
|
||||
builder.AppendLine(" Backup NCCH Header Information:");
|
||||
builder.AppendLine(" -------------------------");
|
||||
if (header == null)
|
||||
{
|
||||
builder.AppendLine(" No backup NCCH header");
|
||||
builder.AppendLine();
|
||||
return;
|
||||
}
|
||||
|
||||
if (header.MagicID == string.Empty)
|
||||
{
|
||||
builder.AppendLine(" Empty backup header, no data can be parsed");
|
||||
}
|
||||
else if (header.MagicID != Constants.NCCHMagicNumber)
|
||||
{
|
||||
builder.AppendLine(" Unrecognized backup header, no data can be parsed");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Backup header omits RSA signature
|
||||
builder.AppendLine(header.MagicID, " Magic ID");
|
||||
builder.AppendLine(header.ContentSizeInMediaUnits, " Content size in media units");
|
||||
builder.AppendLine(header.PartitionId, " Partition ID");
|
||||
builder.AppendLine(header.MakerCode, " Maker code");
|
||||
builder.AppendLine(header.Version, " Version");
|
||||
builder.AppendLine(header.VerificationHash, " Verification hash");
|
||||
builder.AppendLine(header.ProgramId, " Program ID");
|
||||
builder.AppendLine(header.Reserved1, " Reserved 1");
|
||||
builder.AppendLine(header.LogoRegionHash, " Logo region SHA-256 hash");
|
||||
builder.AppendLine(header.ProductCode, " Product code");
|
||||
builder.AppendLine(header.ExtendedHeaderHash, " Extended header SHA-256 hash");
|
||||
builder.AppendLine(header.ExtendedHeaderSizeInBytes, " Extended header size in bytes");
|
||||
builder.AppendLine(header.Reserved2, " Reserved 2");
|
||||
builder.AppendLine(" Flags:");
|
||||
if (header.Flags == null)
|
||||
{
|
||||
builder.AppendLine(" [NULL]");
|
||||
}
|
||||
else
|
||||
{
|
||||
builder.AppendLine(header.Flags.Reserved0, " Reserved 0");
|
||||
builder.AppendLine(header.Flags.Reserved1, " Reserved 1");
|
||||
builder.AppendLine(header.Flags.Reserved2, " Reserved 2");
|
||||
builder.AppendLine($" Crypto method: {header.Flags.CryptoMethod} (0x{header.Flags.CryptoMethod:X})");
|
||||
builder.AppendLine($" Content platform: {header.Flags.ContentPlatform} (0x{header.Flags.ContentPlatform:X})");
|
||||
builder.AppendLine($" Content type: {header.Flags.MediaPlatformIndex} (0x{header.Flags.MediaPlatformIndex:X})");
|
||||
builder.AppendLine(header.Flags.ContentUnitSize, " Content unit size");
|
||||
builder.AppendLine($" Bitmasks: {header.Flags.BitMasks} (0x{header.Flags.BitMasks:X})");
|
||||
}
|
||||
builder.AppendLine(header.PlainRegionOffsetInMediaUnits, " Plain region offset, in media units");
|
||||
builder.AppendLine(header.PlainRegionSizeInMediaUnits, " Plain region size, in media units");
|
||||
builder.AppendLine(header.LogoRegionOffsetInMediaUnits, " Logo region offset, in media units");
|
||||
builder.AppendLine(header.LogoRegionSizeInMediaUnits, " Logo region size, in media units");
|
||||
builder.AppendLine(header.ExeFSOffsetInMediaUnits, " ExeFS offset, in media units");
|
||||
builder.AppendLine(header.ExeFSSizeInMediaUnits, " ExeFS size, in media units");
|
||||
builder.AppendLine(header.ExeFSHashRegionSizeInMediaUnits, " ExeFS hash region size, in media units");
|
||||
builder.AppendLine(header.Reserved3, " Reserved 3");
|
||||
builder.AppendLine(header.RomFSOffsetInMediaUnits, " RomFS offset, in media units");
|
||||
builder.AppendLine(header.RomFSSizeInMediaUnits, " RomFS size, in media units");
|
||||
builder.AppendLine(header.RomFSHashRegionSizeInMediaUnits, " RomFS hash region size, in media units");
|
||||
builder.AppendLine(header.Reserved4, " Reserved 4");
|
||||
builder.AppendLine(header.ExeFSSuperblockHash, " ExeFS superblock SHA-256 hash");
|
||||
builder.AppendLine(header.RomFSSuperblockHash, " RomFS superblock SHA-256 hash");
|
||||
}
|
||||
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
|
||||
{
|
||||
string descriptorsStr = "[NULL]";
|
||||
if (entry.ACI.ARM9AccessControl.Descriptors != null)
|
||||
{
|
||||
var descriptors = Array.ConvertAll(entry.ACI.ARM9AccessControl.Descriptors, d => d.ToString());
|
||||
descriptorsStr = string.Join(", ", descriptors);
|
||||
}
|
||||
builder.AppendLine(descriptorsStr, " 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
|
||||
{
|
||||
string descriptorsStr = "[NULL]";
|
||||
if (entry.ACIForLimitations.ARM9AccessControl.Descriptors != null)
|
||||
{
|
||||
var descriptors = Array.ConvertAll(entry.ACIForLimitations.ARM9AccessControl.Descriptors, d => d.ToString());
|
||||
descriptorsStr = string.Join(", ", descriptors);
|
||||
}
|
||||
builder.AppendLine(descriptorsStr, " 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
360
SabreTools.Serialization/Printers/NCF.cs
Normal file
360
SabreTools.Serialization/Printers/NCF.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
379
SabreTools.Serialization/Printers/NewExecutable.cs
Normal file
379
SabreTools.Serialization/Printers/NewExecutable.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
259
SabreTools.Serialization/Printers/Nitro.cs
Normal file
259
SabreTools.Serialization/Printers/Nitro.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
68
SabreTools.Serialization/Printers/PAK.cs
Normal file
68
SabreTools.Serialization/Printers/PAK.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
92
SabreTools.Serialization/Printers/PFF.cs
Normal file
92
SabreTools.Serialization/Printers/PFF.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
87
SabreTools.Serialization/Printers/PIC.cs
Normal file
87
SabreTools.Serialization/Printers/PIC.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
279
SabreTools.Serialization/Printers/PKZIP.cs
Normal file
279
SabreTools.Serialization/Printers/PKZIP.cs
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
183
SabreTools.Serialization/Printers/PlayJAudioFile.cs
Normal file
183
SabreTools.Serialization/Printers/PlayJAudioFile.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
226
SabreTools.Serialization/Printers/PlayJPlaylist.cs
Normal file
226
SabreTools.Serialization/Printers/PlayJPlaylist.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user