mirror of
https://github.com/encounter/nod.git
synced 2026-07-10 12:18:48 -07:00
Add dat check command for verifying collections
This commit is contained in:
Generated
+7
-6
@@ -457,6 +457,7 @@ dependencies = [
|
|||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
"xxhash-rust",
|
"xxhash-rust",
|
||||||
"zerocopy",
|
"zerocopy",
|
||||||
|
"zstd",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1006,27 +1007,27 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zstd"
|
name = "zstd"
|
||||||
version = "0.13.0"
|
version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
|
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zstd-safe",
|
"zstd-safe",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zstd-safe"
|
name = "zstd-safe"
|
||||||
version = "7.0.0"
|
version = "7.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
|
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zstd-sys",
|
"zstd-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zstd-sys"
|
name = "zstd-sys"
|
||||||
version = "2.0.9+zstd.1.5.5"
|
version = "2.0.11+zstd.1.5.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
|
checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"pkg-config",
|
"pkg-config",
|
||||||
|
|||||||
+6
-6
@@ -161,7 +161,7 @@ pub struct WIADisc {
|
|||||||
///
|
///
|
||||||
/// RVZ only:
|
/// RVZ only:
|
||||||
/// > This is signed (instead of unsigned) to support negative compression levels in
|
/// > This is signed (instead of unsigned) to support negative compression levels in
|
||||||
/// [Zstandard](WIACompression::Zstandard) (RVZ only).
|
/// > [Zstandard](WIACompression::Zstandard) (RVZ only).
|
||||||
pub compression_level: I32,
|
pub compression_level: I32,
|
||||||
/// The size of the chunks that data is divided into.
|
/// The size of the chunks that data is divided into.
|
||||||
///
|
///
|
||||||
@@ -170,13 +170,13 @@ pub struct WIADisc {
|
|||||||
///
|
///
|
||||||
/// RVZ only:
|
/// RVZ only:
|
||||||
/// > Chunk sizes smaller than 2 MiB are supported. The following applies when using a chunk size
|
/// > Chunk sizes smaller than 2 MiB are supported. The following applies when using a chunk size
|
||||||
/// smaller than 2 MiB:
|
/// > smaller than 2 MiB:
|
||||||
/// > - The chunk size must be at least 32 KiB and must be a power of two. (Just like with WIA,
|
/// > - The chunk size must be at least 32 KiB and must be a power of two. (Just like with WIA,
|
||||||
/// sizes larger than 2 MiB do not have to be a power of two, they just have to be an integer
|
/// > sizes larger than 2 MiB do not have to be a power of two, they just have to be an integer
|
||||||
/// multiple of 2 MiB.)
|
/// > multiple of 2 MiB.)
|
||||||
/// > - For Wii partition data, each chunk contains one [WIAExceptionList] which contains
|
/// > - For Wii partition data, each chunk contains one [WIAExceptionList] which contains
|
||||||
/// exceptions for that chunk (and no other chunks). Offset 0 refers to the first hash of the
|
/// > exceptions for that chunk (and no other chunks). Offset 0 refers to the first hash of the
|
||||||
/// current chunk, not the first hash of the full 2 MiB of data.
|
/// > current chunk, not the first hash of the full 2 MiB of data.
|
||||||
pub chunk_size: U32,
|
pub chunk_size: U32,
|
||||||
/// The first 0x80 bytes of the disc image.
|
/// The first 0x80 bytes of the disc image.
|
||||||
pub disc_head: [u8; DISC_HEAD_SIZE],
|
pub disc_head: [u8; DISC_HEAD_SIZE],
|
||||||
|
|||||||
@@ -25,11 +25,14 @@ base16ct = "0.2.0"
|
|||||||
crc32fast = "1.4.0"
|
crc32fast = "1.4.0"
|
||||||
digest = "0.10.7"
|
digest = "0.10.7"
|
||||||
enable-ansi-support = "0.2.1"
|
enable-ansi-support = "0.2.1"
|
||||||
|
hex = { version = "0.4.3", features = ["serde"] }
|
||||||
indicatif = "0.17.8"
|
indicatif = "0.17.8"
|
||||||
itertools = "0.12.1"
|
itertools = "0.12.1"
|
||||||
log = "0.4.20"
|
log = "0.4.20"
|
||||||
md-5 = "0.10.6"
|
md-5 = "0.10.6"
|
||||||
nod = { path = "../nod" }
|
nod = { path = "../nod" }
|
||||||
|
quick-xml = { version = "0.31.0", features = ["serialize"] }
|
||||||
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
sha1 = "0.10.6"
|
sha1 = "0.10.6"
|
||||||
size = "0.4.1"
|
size = "0.4.1"
|
||||||
supports-color = "3.0.0"
|
supports-color = "3.0.0"
|
||||||
@@ -38,9 +41,11 @@ tracing-attributes = "0.1.27"
|
|||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
xxhash-rust = { version = "0.8.10", features = ["xxh64"] }
|
xxhash-rust = { version = "0.8.10", features = ["xxh64"] }
|
||||||
zerocopy = { version = "0.7.32", features = ["alloc", "derive"] }
|
zerocopy = { version = "0.7.32", features = ["alloc", "derive"] }
|
||||||
|
zstd = "0.13.1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
hex = { version = "0.4.3", features = ["serde"] }
|
hex = { version = "0.4.3", features = ["serde"] }
|
||||||
quick-xml = { version = "0.31.0", features = ["serialize"] }
|
quick-xml = { version = "0.31.0", features = ["serialize"] }
|
||||||
serde = { version = "1.0.197", features = ["derive"] }
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
zerocopy = { version = "0.7.32", features = ["alloc", "derive"] }
|
zerocopy = { version = "0.7.32", features = ["alloc", "derive"] }
|
||||||
|
zstd = "0.13.1"
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,155 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<datafile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://datomatic.no-intro.org/stuff https://datomatic.no-intro.org/stuff/schema_nointro_datfile_v3.xsd">
|
||||||
|
<header>
|
||||||
|
<id>261</id>
|
||||||
|
<name>Nintendo - Nintendo GameCube (NPDP Carts)</name>
|
||||||
|
<description>Nintendo - Nintendo GameCube (NPDP Carts)</description>
|
||||||
|
<version>20240104-124921</version>
|
||||||
|
<author>Hiccup, NovaAurora, relax, togemet2</author>
|
||||||
|
<homepage>No-Intro</homepage>
|
||||||
|
<url>https://www.no-intro.org</url>
|
||||||
|
<clrmamepro forcenodump="required"/>
|
||||||
|
</header>
|
||||||
|
<game name="2 Games in 1 - Nickelodeon Bob L'eponge - Le Film & Nickelodeon Bob L'eponge - La Bataille de Bikini Bottom (France) (Disc 2) (Proto)" id="0028" cloneofid="0027">
|
||||||
|
<description>2 Games in 1 - Nickelodeon Bob L'eponge - Le Film & Nickelodeon Bob L'eponge - La Bataille de Bikini Bottom (France) (Disc 2) (Proto)</description>
|
||||||
|
<rom name="2 Games in 1 - Nickelodeon Bob L'eponge - Le Film & Nickelodeon Bob L'eponge - La Bataille de Bikini Bottom (France) (Disc 2) (Proto).iso" size="1459978240" crc="4d3ea301" md5="623194c072b69e2521ac92d9982c2685" sha1="c61f74db3d7dedac3e93a34ff6c901a526282ebf" sha256="3754e462e1bf865266671369f8cd1f1f35c1a7dcfa8d9004ae400d2979d8fab8" serial="GU4X78"/>
|
||||||
|
</game>
|
||||||
|
<game name="2 Games in 1 - Nickelodeon Bob L'eponge - Le Film & Nickelodeon Bob L'eponge - La Bataille de Bikini Bottom (France) (Disc 1) (Proto)" id="0027">
|
||||||
|
<description>2 Games in 1 - Nickelodeon Bob L'eponge - Le Film & Nickelodeon Bob L'eponge - La Bataille de Bikini Bottom (France) (Disc 1) (Proto)</description>
|
||||||
|
<rom name="2 Games in 1 - Nickelodeon Bob L'eponge - Le Film & Nickelodeon Bob L'eponge - La Bataille de Bikini Bottom (France) (Disc 1) (Proto).iso" size="1459978240" crc="75a51568" md5="fe3f90953a51a296af0ffddeced57ec0" sha1="26ebef10cfe279385bc1709b52e5a9a9c715dec8" sha256="72b22532b85069cd05e1d5beb3988bbf759266186e93437cb703ca4c33c85314" serial="GU4X78"/>
|
||||||
|
</game>
|
||||||
|
<game name="2 Games in 1 - Nickelodeon SpongeBob SquarePants - The Movie & Nickelodeon SpongeBob SquarePants - Battle for Bikini Bottom (Europe) (Disc 2) (Proto) (2005-11-10)" id="0021" cloneofid="0020">
|
||||||
|
<description>2 Games in 1 - Nickelodeon SpongeBob SquarePants - The Movie & Nickelodeon SpongeBob SquarePants - Battle for Bikini Bottom (Europe) (Disc 2) (Proto) (2005-11-10)</description>
|
||||||
|
<rom name="2 Games in 1 - Nickelodeon SpongeBob SquarePants - The Movie & Nickelodeon SpongeBob SquarePants - Battle for Bikini Bottom (Europe) (Disc 2) (Proto) (2005-11-10).iso" size="1459978240" crc="a582fd52" md5="66048f7dc3ddb9326a9c05aec6cb720f" sha1="b21c8bfef984f0fd0c3aa2f8c1acd19b9ae70394" sha256="4dae493c263b74fa07a2e6be4aa6c9454fb03f6d403666a5f914484f4284fdc2" serial="GU4P78"/>
|
||||||
|
</game>
|
||||||
|
<game name="2 Games in 1 - Nickelodeon SpongeBob SquarePants - The Movie & Nickelodeon SpongeBob SquarePants - Battle for Bikini Bottom (Europe) (Disc 1) (Proto) (2005-11-10)" id="0020">
|
||||||
|
<description>2 Games in 1 - Nickelodeon SpongeBob SquarePants - The Movie & Nickelodeon SpongeBob SquarePants - Battle for Bikini Bottom (Europe) (Disc 1) (Proto) (2005-11-10)</description>
|
||||||
|
<rom name="2 Games in 1 - Nickelodeon SpongeBob SquarePants - The Movie & Nickelodeon SpongeBob SquarePants - Battle for Bikini Bottom (Europe) (Disc 1) (Proto) (2005-11-10).iso" size="1459978240" crc="09fbd438" md5="face4ab02e61ae7f6905e0824603a208" sha1="df85835fc6216aa074a90654d90e502b1411aa35" sha256="9089d6c6a464fb3063828f640a504eba832edc5dd02e5f654357b2f6d66f9959" serial="GU4P78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Batman Begins (Europe) (Beta) (2005-05-01)" id="0035">
|
||||||
|
<category>Games</category>
|
||||||
|
<category>Preproduction</category>
|
||||||
|
<description>Batman Begins (Europe) (Beta) (2005-05-01)</description>
|
||||||
|
<rom name="Batman Begins (Europe) (Beta) (2005-05-01).iso" size="1459978240" crc="02257052" md5="bb96b0fb81c3270ac8272717224954f5" sha1="20ee958717211d217f64b681192d6d19704617aa" sha256="a48973507f5f6d16f159f10714354b60729c64ecebb2c6cf1d9f100f33962bbe" serial="GINX69"/>
|
||||||
|
</game>
|
||||||
|
<game name="Crash Bandicoot - The Wrath of Cortex (USA) (Beta) (2002-07-24)" id="0032">
|
||||||
|
<category>Games</category>
|
||||||
|
<category>Preproduction</category>
|
||||||
|
<description>Crash Bandicoot - The Wrath of Cortex (USA) (Beta) (2002-07-24)</description>
|
||||||
|
<rom name="Crash Bandicoot - The Wrath of Cortex (USA) (Beta) (2002-07-24).iso" size="1459978240" crc="f11e97f0" md5="6769d7ec3cd073578e4654c7201887d1" sha1="46964de0d45bf251d4fdf329a9b6888a336b52d6" sha256="384f706d06c4fe1f080a59899db0e24f0b8344b0ee7258e53e44825784319230" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="Crash Bandicoot - The Wrath of Cortex (USA) (Beta) (2001-12-17)" id="0031" cloneofid="0032">
|
||||||
|
<category>Games</category>
|
||||||
|
<category>Preproduction</category>
|
||||||
|
<description>Crash Bandicoot - The Wrath of Cortex (USA) (Beta) (2001-12-17)</description>
|
||||||
|
<rom name="Crash Bandicoot - The Wrath of Cortex (USA) (Beta) (2001-12-17).iso" size="1459978240" crc="3a214885" md5="0ba69be36d249ce4afa71e8046cce0b9" sha1="d2e66b9799bca1c462b71fba96e642ad4e31dd13" sha256="48694418a9b25baab806cd5cbb15018ccbf9551babf06d78724f51d4dbafd9b2" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar Mr. Incredible (Japan) (Beta) (2004-09-20)" id="0017">
|
||||||
|
<description>Disney-Pixar Mr. Incredible (Japan) (Beta) (2004-09-20)</description>
|
||||||
|
<rom name="Disney-Pixar Mr. Incredible (Japan) (Beta) (2004-09-20).iso" size="1459978240" crc="f250e2ed" md5="3a44c962eb0f3dfbfb5ee7ed85b76248" sha1="b5ad24c3b4290b4900cfab0a70cacd72c2381e15" sha256="6a643c55b05812fc1e94d7b06a14d6ae7e5430d9ea8628ca31e0d875272e89b0" serial="GICJ78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar Mr. Incredible (Japan) (Beta) (2004-09-13)" id="0016">
|
||||||
|
<description>Disney-Pixar Mr. Incredible (Japan) (Beta) (2004-09-13)</description>
|
||||||
|
<rom name="Disney-Pixar Mr. Incredible (Japan) (Beta) (2004-09-13).iso" size="1459978240" crc="ecfaa615" md5="9876d5bca863ebb700531bb2ca466e7d" sha1="c68823cb2b4e759350780d4df24d5b3c73a568cb" serial="GICJ78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar Mr. Incredible - Kyouteki Underminer Toujou (Japan) (Beta) (2005-09-15)" id="0023">
|
||||||
|
<description>Disney-Pixar Mr. Incredible - Kyouteki Underminer Toujou (Japan) (Beta) (2005-09-15)</description>
|
||||||
|
<rom name="Disney-Pixar Mr. Incredible - Kyouteki Underminer Toujou (Japan) (Beta) (2005-09-15).iso" size="1459978240" crc="d218556f" md5="24b9e09645b661f00625934539337ae2" sha1="3d9debbeed127cd1d362335183760e030cfb7582" sha256="05c7748894eaaeda8cf1ef64eed809ee5b660b0618eb00fb7ddc46fdef1f3924" serial="GIQJ8P"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar Mr. Incredible - Kyouteki Underminer Toujou (Japan) (Beta) (2005-10-21)" id="0022">
|
||||||
|
<description>Disney-Pixar Mr. Incredible - Kyouteki Underminer Toujou (Japan) (Beta) (2005-10-21)</description>
|
||||||
|
<rom name="Disney-Pixar Mr. Incredible - Kyouteki Underminer Toujou (Japan) (Beta) (2005-10-21).iso" size="1459978240" crc="159a0b00" md5="fa0bd879f7d488889a8c5bfe904b4770" sha1="cf528ef871e58744c60d282e0f9f0eb30711046b" sha256="c82f820d1a46bc23bd815aa91dc520e62376a3fd83c4ebc49edb46fc09fbd7c5" serial="GIQE78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar Ratatouille (USA) (Beta) (Later)" id="0004">
|
||||||
|
<description>Disney-Pixar Ratatouille (USA) (Beta) (Later)</description>
|
||||||
|
<rom name="Disney-Pixar Ratatouille (USA) (Beta) (Later).iso" size="1459978240" crc="7b595396" md5="027171c92d603ae4c90d69956d0bd94a" sha1="ba44bbe5780c34d2a6ebd66eeed52eaaab941468" sha256="61482c63289902767598a2f0bd8ebf44992190186fcd4e5e38301e7266f7c688" serial="GIQE78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar Ratatouille (USA) (Beta) (2006-01-18)" id="0005" cloneofid="0004">
|
||||||
|
<description>Disney-Pixar Ratatouille (USA) (Beta) (2006-01-18)</description>
|
||||||
|
<rom name="Disney-Pixar Ratatouille (USA) (Beta) (2006-01-18).iso" size="1459978240" crc="524b2418" md5="e277ac9371b89ac6c06588a65c4d0c2d" sha1="0901c7a4fbbd9a8ba86589513a7d37e546cfb6c6" sha256="b60ae1c08cd86e11fd3f0c54a2027a895d8495888c542e9ee6dd884226ee9860" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar The Incredibles (USA) (Beta) (2004-09-12)" id="0015">
|
||||||
|
<description>Disney-Pixar The Incredibles (USA) (Beta) (2004-09-12)</description>
|
||||||
|
<rom name="Disney-Pixar The Incredibles (USA) (Beta) (2004-09-12).iso" size="1459978240" crc="8bcdcaaf" md5="eb7529c0932291614aeaa846b9fd7b79" sha1="8100b0fc005ec46ee472c6ec79ec76b5503231b2" sha256="f0a50affdf1c435d67ec29063c163d7bd3fb8a6d374ce3e6f0d40f335d5741db" serial="GICE78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar The Incredibles (USA) (Beta) (2004-07-19)" id="0014">
|
||||||
|
<description>Disney-Pixar The Incredibles (USA) (Beta) (2004-07-19)</description>
|
||||||
|
<rom name="Disney-Pixar The Incredibles (USA) (Beta) (2004-07-19).iso" size="1459978240" crc="e5d4fa8a" md5="7d4f8bb9b0fa4a739c71aecf879a6c7a" sha1="12748f0e726199bfba3af6b98ef52d5ef750574f" sha256="abd8e0a57a92955147b72f1dff948b20e5a9ef2568e51f515bdba14c48c94f3f" serial="GICE78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Disney-Pixar The Incredibles - Rise of the Underminer (Europe) (Beta) (2005-09-15)" id="0024">
|
||||||
|
<description>Disney-Pixar The Incredibles - Rise of the Underminer (Europe) (Beta) (2005-09-15)</description>
|
||||||
|
<rom name="Disney-Pixar The Incredibles - Rise of the Underminer (Europe) (Beta) (2005-09-15).iso" size="1459978240" crc="5adab4b5" md5="ed5a39eddd75df27bbd9fdaf0bef8100" sha1="2e9eb84c8c845450842170114a042bba95489575" sha256="03bc3a9f560738a412fb55174eae9084c5c7a0c7b762cd60f7ffa5659cafcac2" serial="GIQX78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Gun (USA) (Beta) (2004-04-07)" id="0001">
|
||||||
|
<description>Gun (USA) (Beta) (2004-04-07)</description>
|
||||||
|
<rom name="Gun (USA) (Beta) (2004-04-07).iso" size="1459978240" crc="c98922bb" md5="d556b453ce46d0b521722f11eee22fcc" sha1="55999e5c50edc82bb4ed93beb1d6b51d641698d8" sha256="efc1e3cd43b51b1c08e33083e57f69c266e7c44707a87f5ba3974c5b07c36ccf" serial="G2TE52"/>
|
||||||
|
</game>
|
||||||
|
<game name="Ice Age 2 - The Meltdown (Europe) (Beta)" id="0033" cloneofid="0034">
|
||||||
|
<category>Games</category>
|
||||||
|
<category>Preproduction</category>
|
||||||
|
<description>Ice Age 2 - The Meltdown (Europe) (Beta)</description>
|
||||||
|
<rom name="Ice Age 2 - The Meltdown (Europe) (Beta).iso" size="1459978240" crc="a7e661da" md5="e446973ca12a66f54f5cc2fd5299811e" sha1="1402cf45209ae18bfc609dcec05574670ee78e5f" sha256="a469b003393e7ef828980b6d7cde813e8aa5b6368740667ccc593eced025f237" serial="GIAP7D"/>
|
||||||
|
</game>
|
||||||
|
<game name="Ice Age 2 - The Meltdown (Europe) (En,Fr,De,Nl) (Beta) (2005-12-12)" id="0034">
|
||||||
|
<category>Games</category>
|
||||||
|
<category>Preproduction</category>
|
||||||
|
<description>Ice Age 2 - The Meltdown (Europe) (En,Fr,De,Nl) (Beta) (2005-12-12)</description>
|
||||||
|
<rom name="Ice Age 2 - The Meltdown (Europe) (En,Fr,De,Nl) (Beta) (2005-12-12).iso" size="1459978240" crc="85b0ae66" md5="add555f6926d847f1b31e71ae786b294" sha1="14284b7976c7eaead364eb12a5d9fa517fa03301" sha256="5ed283718faedc0519fd349782ae3c5f5c8dd701d09a7c777923a26bfd5e8e32" serial="GIAP7D"/>
|
||||||
|
</game>
|
||||||
|
<game name="kpaddemo (Unknown)" id="0026">
|
||||||
|
<description>kpaddemo (Unknown)</description>
|
||||||
|
<rom name="kpaddemo (Unknown).iso" size="1459978240" crc="911795ae" md5="02e8f7e86df9c3e4dceed8fff66a1fdc" sha1="cdc13d1de7bc99ccfeda88e6197dd51d46e7e900" sha256="cb847d32215694285d70fda9cd44a3e6683213e2466c8a8c714f71efa9cdb193" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="Memory Card Utility Program (Japan) (v1.1.0)" id="0030">
|
||||||
|
<description>Memory Card Utility Program (Japan) (v1.1.0)</description>
|
||||||
|
<rom name="Memory Card Utility Program (Japan) (v1.1.0).iso" size="1459978240" crc="1d74ad4a" md5="ed44f29fd55b3cfb7f9d5b5b1a24e148" sha1="1a4a14148901ac27d24e93b949ed66e51d2e1c85" sha256="f7c0b3bde6212416e0c36a22d0683916bd5eed06442f299dd0139a2cf6311fb6" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="Memory Card Utility Program (USA) (v1.1.0)" id="0029">
|
||||||
|
<description>Memory Card Utility Program (USA) (v1.1.0)</description>
|
||||||
|
<rom name="Memory Card Utility Program (USA) (v1.1.0).iso" size="1459978240" crc="af7e5d39" md5="7b6d6c0e5c2d96a0b1fe85ea9c901de2" sha1="221fcf1109a0df55dcd7009682d645add15c7f88" sha256="1a8eaead5836dcac5a62731182c74d97837fb49de4f1c1f80c4198e48769187b" serial="327E01"/>
|
||||||
|
</game>
|
||||||
|
<game name="Memory Card Utility Program (Unknown) (v1.0.4) (Alt)" id="0010" cloneofid="0009">
|
||||||
|
<description>Memory Card Utility Program (Unknown) (v1.0.4) (Alt)</description>
|
||||||
|
<rom name="Memory Card Utility Program (Unknown) (v1.0.4) (Alt).iso" size="1459978240" crc="0c20db86" md5="efa23737d1df50a1a14fd329c6a9e943" sha1="613adf9e4c5ff341260ff1c1f6d0d11ed5d787cf" sha256="6ef055b0e626ec7e132ab7ee0a197eea9d398ed4863d8bbe17d8acd4d42372cb" serial="G2TP52"/>
|
||||||
|
</game>
|
||||||
|
<game name="Memory Card Utility Program (Unknown) (v1.0.4)" id="0009">
|
||||||
|
<description>Memory Card Utility Program (Unknown) (v1.0.4)</description>
|
||||||
|
<rom name="Memory Card Utility Program (Unknown) (v1.0.4).iso" size="1459978240" crc="ee959c7e" md5="1ecfd29e8b723e7239e2b6755c7eb753" sha1="ba2050fddb5ba172e8fad55d357f8042a1430060" sha256="3a6b1de8eb0576bb161dad3b5fe8c0cb1efb1a1a32415eb1cc9037e220ee643e" serial="G2TP52"/>
|
||||||
|
</game>
|
||||||
|
<game name="Metroid Prime 3 - Corruption (USA) (Demo) (Kiosk, E3 2006)" id="0011">
|
||||||
|
<description>Metroid Prime 3 - Corruption (USA) (Demo) (Kiosk, E3 2006)</description>
|
||||||
|
<rom name="Metroid Prime 3 - Corruption (USA) (Demo) (Kiosk, E3 2006).iso" size="1459978240" crc="97ba74c5" md5="2f8a935e5209f6ae86923e977c86de67" sha1="c84d04d98919c45502dcb54db3e2cd3bf6969b91" sha256="400a87852acecac9079494ec7f291208fd95368686f92a58ce14ccd1a17c3132" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="Pirates of the Caribbean (USA) (Proto) (2004-04-05)" id="0002">
|
||||||
|
<description>Pirates of the Caribbean (USA) (Proto) (2004-04-05)</description>
|
||||||
|
<rom name="Pirates of the Caribbean (USA) (Proto) (2004-04-05).iso" size="1459978240" crc="f1eef03f" md5="1d3608f19a16f0d9d1f4296104d7e13c" sha1="80f0fc50a2602f1281cf84aa2d44cf330dcf50b3" sha256="3d49fa4e6e4322c2ba95b10c2a9e389b3ccaed1d6fc842c4779736156da78839" serial="GXPE78"/>
|
||||||
|
</game>
|
||||||
|
<game name="Shadow the Hedgehog - Trial Version (Japan) (Demo) (2005-10-31)" id="0019">
|
||||||
|
<description>Shadow the Hedgehog - Trial Version (Japan) (Demo) (2005-10-31)</description>
|
||||||
|
<rom name="Shadow the Hedgehog - Trial Version (Japan) (Demo) (2005-10-31).iso" size="1459978240" crc="15dc6e3d" md5="27d5be21b6e9a198dd61ed92e6c9cfd5" sha1="bc071ad2ee8bb992dbddbfff84ef06496e630abd" serial="GUPJ8P"/>
|
||||||
|
</game>
|
||||||
|
<game name="Sonic Heroes (Japan) (Beta) (2003-10-30)" id="0012">
|
||||||
|
<description>Sonic Heroes (Japan) (Beta) (2003-10-30)</description>
|
||||||
|
<rom name="Sonic Heroes (Japan) (Beta) (2003-10-30).iso" size="1459978240" crc="e291dd98" md5="42c93193d0b50a2aba3cf56071c8c892" sha1="35219e4e4e9120aa24862fa9f2622b7b3a4d2540" serial="G9SJ8P"/>
|
||||||
|
</game>
|
||||||
|
<game name="Sonic Heroes (USA) (Beta)" id="0013">
|
||||||
|
<description>Sonic Heroes (USA) (Beta)</description>
|
||||||
|
<rom name="Sonic Heroes (USA) (Beta).iso" size="1459978240" crc="dafde48b" md5="95c1feb22eb3271e9d89fcbbcaaed50e" sha1="949ddae3973272f622c422a66262cf4639bbd497" serial="G9SE8P"/>
|
||||||
|
</game>
|
||||||
|
<game name="Sonic Riders (USA) (Beta)" id="0018">
|
||||||
|
<description>Sonic Riders (USA) (Beta)</description>
|
||||||
|
<rom name="Sonic Riders (USA) (Beta).iso" size="1459978240" crc="5f4eb455" md5="4fd040173b6ade79c533a3c2d5434939" sha1="e3d5bcf51deab5801d7e7f8b0c226c6cd764cc3e" serial="GXEE8P"/>
|
||||||
|
</game>
|
||||||
|
<game name="Summoner - The Prophecy (USA) (Beta) (Rev 1121B)" id="0007">
|
||||||
|
<description>Summoner - The Prophecy (USA) (Beta) (Rev 1121B)</description>
|
||||||
|
<rom name="Summoner - The Prophecy (USA) (Beta) (Rev 1121B).iso" size="1459978240" crc="146e4a5a" md5="ff5f979d070b96dc71cbdb6194556078" sha1="7f40be75acaf413f635726221714493582e7330d" sha256="e0f9a4adf5156199a836e412803e7c5075eeea2d3b239ceb89192f94eb7b547d" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="Summoner - The Prophecy (USA) (Beta) (Rev 1121A)" id="0006" cloneofid="0007">
|
||||||
|
<description>Summoner - The Prophecy (USA) (Beta) (Rev 1121A)</description>
|
||||||
|
<rom name="Summoner - The Prophecy (USA) (Beta) (Rev 1121A).iso" size="1459978240" crc="16d7bcce" md5="9f4fb9ee478d0b808ee0234950b69234" sha1="07e402efe512f5b664bc8f3a6f43ec36da6afa03" sha256="7b5c0603a3627dfc60c24cdcf37261c874200955a9acfa39bebdee4c1c9e9d47" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
<game name="There Is No Program on This Disc (Unknown)" id="0025">
|
||||||
|
<description>There Is No Program on This Disc (Unknown)</description>
|
||||||
|
<rom name="There Is No Program on This Disc (Unknown).iso" size="1459978240" crc="64addc63" md5="6f26e9779e57150182a5c8247a714b83" sha1="09fb6c2dc26fe66a52bf9a4b50ad6970851d98bc" sha256="a46582e2fe9d86efe5e958e242dce41afcb8a37b892d98f913cfee3a9a96ab82" serial="RELSAB"/>
|
||||||
|
</game>
|
||||||
|
</datafile>
|
||||||
@@ -3,9 +3,9 @@
|
|||||||
<datafile>
|
<datafile>
|
||||||
<header>
|
<header>
|
||||||
<name>Nintendo - GameCube</name>
|
<name>Nintendo - GameCube</name>
|
||||||
<description>Nintendo - GameCube - Discs (1989) (2024-02-13 01-56-25)</description>
|
<description>Nintendo - GameCube - Discs (1992) (2024-06-02 00-38-06)</description>
|
||||||
<version>2024-02-13 01-56-25</version>
|
<version>2024-06-02 00-38-06</version>
|
||||||
<date>2024-02-13 01-56-25</date>
|
<date>2024-06-02 00-38-06</date>
|
||||||
<author>redump.org</author>
|
<author>redump.org</author>
|
||||||
<homepage>redump.org</homepage>
|
<homepage>redump.org</homepage>
|
||||||
<url>http://redump.org/</url>
|
<url>http://redump.org/</url>
|
||||||
@@ -5376,7 +5376,7 @@
|
|||||||
<rom name="Ribbit King (USA) (En,Es).iso" size="1459978240" crc="e46d465d" md5="67b83d2ef427326b8f69e995fa104245" sha1="1d6cc36ec5ffa402d0d898b81d71fc778c34b34a"/>
|
<rom name="Ribbit King (USA) (En,Es).iso" size="1459978240" crc="e46d465d" md5="67b83d2ef427326b8f69e995fa104245" sha1="1d6cc36ec5ffa402d0d898b81d71fc778c34b34a"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Ribbit King Plus! (USA) (Bonus Disc)">
|
<game name="Ribbit King Plus! (USA) (Bonus Disc)">
|
||||||
<category>Games</category>
|
<category>Bonus Discs</category>
|
||||||
<description>Ribbit King Plus! (USA) (Bonus Disc)</description>
|
<description>Ribbit King Plus! (USA) (Bonus Disc)</description>
|
||||||
<rom name="Ribbit King Plus! (USA) (Bonus Disc).iso" size="1459978240" crc="e5e731eb" md5="a7c4d17e34bade211b797fd3c7130fc0" sha1="3d6c301bbc54b0939307aa8772e008ac467215dd"/>
|
<rom name="Ribbit King Plus! (USA) (Bonus Disc).iso" size="1459978240" crc="e5e731eb" md5="a7c4d17e34bade211b797fd3c7130fc0" sha1="3d6c301bbc54b0939307aa8772e008ac467215dd"/>
|
||||||
</game>
|
</game>
|
||||||
@@ -9100,10 +9100,10 @@
|
|||||||
<description>Action Replay for GameCube (Europe) (En,Fr,De,Es,It,Pt) (Unl) (v1.14b)</description>
|
<description>Action Replay for GameCube (Europe) (En,Fr,De,Es,It,Pt) (Unl) (v1.14b)</description>
|
||||||
<rom name="Action Replay for GameCube (Europe) (En,Fr,De,Es,It,Pt) (Unl) (v1.14b).iso" size="1459978240" crc="f61cf908" md5="bb59fa5ce23cde960da07150915b73b5" sha1="902309465c6f9a9933097f74aff0e4b6df338204"/>
|
<rom name="Action Replay for GameCube (Europe) (En,Fr,De,Es,It,Pt) (Unl) (v1.14b).iso" size="1459978240" crc="f61cf908" md5="bb59fa5ce23cde960da07150915b73b5" sha1="902309465c6f9a9933097f74aff0e4b6df338204"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 01 (20) (Europe) (Unl)">
|
<game name="Cube CD 01 (20) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 01 (20) (Europe) (Unl)</description>
|
<description>Cube CD 01 (20) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 01 (20) (Europe) (Unl).iso" size="1459978240" crc="3bda1560" md5="ba8dd80ae7c11b51c0a609d99c07a8b6" sha1="c7abf65ee74b15619afa8277f2ca59ed57d247df"/>
|
<rom name="Cube CD 01 (20) (UK) (Unl).iso" size="1459978240" crc="3bda1560" md5="ba8dd80ae7c11b51c0a609d99c07a8b6" sha1="c7abf65ee74b15619afa8277f2ca59ed57d247df"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Space Raiders (Korea)">
|
<game name="Space Raiders (Korea)">
|
||||||
<category>Games</category>
|
<category>Games</category>
|
||||||
@@ -9120,50 +9120,50 @@
|
|||||||
<description>Action Replay Ultimate Cheats fuer Pokemon Colosseum (Germany) (Unl)</description>
|
<description>Action Replay Ultimate Cheats fuer Pokemon Colosseum (Germany) (Unl)</description>
|
||||||
<rom name="Action Replay Ultimate Cheats fuer Pokemon Colosseum (Germany) (Unl).iso" size="1459978240" crc="371898c1" md5="57ce534db0a790b40691860b42b76cc3" sha1="6850df1182aadc8d50a9baa39b7f36982f10f18a"/>
|
<rom name="Action Replay Ultimate Cheats fuer Pokemon Colosseum (Germany) (Unl).iso" size="1459978240" crc="371898c1" md5="57ce534db0a790b40691860b42b76cc3" sha1="6850df1182aadc8d50a9baa39b7f36982f10f18a"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 02 (21) (Europe) (Unl)">
|
<game name="Cube CD 02 (21) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 02 (21) (Europe) (Unl)</description>
|
<description>Cube CD 02 (21) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 02 (21) (Europe) (Unl).iso" size="1459978240" crc="564bddf9" md5="e3e55b7ba681f9f0f9c107245df731d4" sha1="29f48aea1763f86760b2dafb9d528c435bfdfeed"/>
|
<rom name="Cube CD 02 (21) (UK) (Unl).iso" size="1459978240" crc="564bddf9" md5="e3e55b7ba681f9f0f9c107245df731d4" sha1="29f48aea1763f86760b2dafb9d528c435bfdfeed"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 03 (22) (Europe) (Unl)">
|
<game name="Cube CD 03 (22) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 03 (22) (Europe) (Unl)</description>
|
<description>Cube CD 03 (22) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 03 (22) (Europe) (Unl).iso" size="1459978240" crc="4d3bc980" md5="63183383a906a65cda29c30d35c8026a" sha1="9e0d0fc0c61e284542bde3c6c5fa9b04105df612"/>
|
<rom name="Cube CD 03 (22) (UK) (Unl).iso" size="1459978240" crc="4d3bc980" md5="63183383a906a65cda29c30d35c8026a" sha1="9e0d0fc0c61e284542bde3c6c5fa9b04105df612"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 04 (23) (Europe) (Unl)">
|
<game name="Cube CD 04 (23) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 04 (23) (Europe) (Unl)</description>
|
<description>Cube CD 04 (23) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 04 (23) (Europe) (Unl).iso" size="1459978240" crc="ceb11a37" md5="570491e09928e0214be8c2d074684a9d" sha1="b4f382b2d25ba4726af1a0754e600275445f6951"/>
|
<rom name="Cube CD 04 (23) (UK) (Unl).iso" size="1459978240" crc="ceb11a37" md5="570491e09928e0214be8c2d074684a9d" sha1="b4f382b2d25ba4726af1a0754e600275445f6951"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 05 (24) (Europe) (Unl)">
|
<game name="Cube CD 05 (24) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 05 (24) (Europe) (Unl)</description>
|
<description>Cube CD 05 (24) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 05 (24) (Europe) (Unl).iso" size="1459978240" crc="2188e0bf" md5="a6aa526a5d2556905d7a61d4b7e6610b" sha1="a1f4a282ffd9dbfaa22b76065404b8737ea9139e"/>
|
<rom name="Cube CD 05 (24) (UK) (Unl).iso" size="1459978240" crc="2188e0bf" md5="a6aa526a5d2556905d7a61d4b7e6610b" sha1="a1f4a282ffd9dbfaa22b76065404b8737ea9139e"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 06 (25) (Europe) (Unl)">
|
<game name="Cube CD 06 (25) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 06 (25) (Europe) (Unl)</description>
|
<description>Cube CD 06 (25) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 06 (25) (Europe) (Unl).iso" size="1459978240" crc="20843654" md5="2a91e8400172225f20c10fd2f6b2327d" sha1="28b59d6c1289655db9961bf10bacf81401ad6836"/>
|
<rom name="Cube CD 06 (25) (UK) (Unl).iso" size="1459978240" crc="20843654" md5="2a91e8400172225f20c10fd2f6b2327d" sha1="28b59d6c1289655db9961bf10bacf81401ad6836"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 07 (26) (Europe) (Unl)">
|
<game name="Cube CD 07 (26) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 07 (26) (Europe) (Unl)</description>
|
<description>Cube CD 07 (26) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 07 (26) (Europe) (Unl).iso" size="1459978240" crc="094e050d" md5="9ba9a23a6478773a1b51cf2619bbc498" sha1="902c20039d49000b43e0ed6da972aa2846461bfb"/>
|
<rom name="Cube CD 07 (26) (UK) (Unl).iso" size="1459978240" crc="094e050d" md5="9ba9a23a6478773a1b51cf2619bbc498" sha1="902c20039d49000b43e0ed6da972aa2846461bfb"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 08 (27) (Europe) (Unl)">
|
<game name="Cube CD 08 (27) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 08 (27) (Europe) (Unl)</description>
|
<description>Cube CD 08 (27) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 08 (27) (Europe) (Unl).iso" size="1459978240" crc="a7648498" md5="d11e4b0672880d9fdcae762eee4f919a" sha1="b06488214824a2e1eaf215eb792d2767f6472e3e"/>
|
<rom name="Cube CD 08 (27) (UK) (Unl).iso" size="1459978240" crc="a7648498" md5="d11e4b0672880d9fdcae762eee4f919a" sha1="b06488214824a2e1eaf215eb792d2767f6472e3e"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 09 (28) (Europe) (Unl)">
|
<game name="Cube CD 09 (28) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 09 (28) (Europe) (Unl)</description>
|
<description>Cube CD 09 (28) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 09 (28) (Europe) (Unl).iso" size="1459978240" crc="77a5a747" md5="d659ae6d451d6253ef1bd3cf6bcf8fe2" sha1="561511a150af7239e8b740d398315c626ecb8eb6"/>
|
<rom name="Cube CD 09 (28) (UK) (Unl).iso" size="1459978240" crc="77a5a747" md5="d659ae6d451d6253ef1bd3cf6bcf8fe2" sha1="561511a150af7239e8b740d398315c626ecb8eb6"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 10 (29) (Europe) (Unl)">
|
<game name="Cube CD 10 (29) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 10 (29) (Europe) (Unl)</description>
|
<description>Cube CD 10 (29) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 10 (29) (Europe) (Unl).iso" size="1459978240" crc="d58bb1d1" md5="7aa303a1ee2cca606eb7293d1e5d40e1" sha1="3643191bacbb49b3a1c10a302f36dd2ecd76ac70"/>
|
<rom name="Cube CD 10 (29) (UK) (Unl).iso" size="1459978240" crc="d58bb1d1" md5="7aa303a1ee2cca606eb7293d1e5d40e1" sha1="3643191bacbb49b3a1c10a302f36dd2ecd76ac70"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Action Replay for GameCube (Europe) (Unl) (v1.0E)">
|
<game name="Action Replay for GameCube (Europe) (Unl) (v1.0E)">
|
||||||
<category>Applications</category>
|
<category>Applications</category>
|
||||||
@@ -9175,25 +9175,25 @@
|
|||||||
<description>Nickelodeon SpongeBob SquarePants - Creatuur van de Krokante Krab (Netherlands)</description>
|
<description>Nickelodeon SpongeBob SquarePants - Creatuur van de Krokante Krab (Netherlands)</description>
|
||||||
<rom name="Nickelodeon SpongeBob SquarePants - Creatuur van de Krokante Krab (Netherlands).iso" size="1459978240" crc="58dc71d7" md5="45df2c017c82f4737ed154f3c53e0bfe" sha1="d1da9a9aede1c44063f066da35623ff9a92c3b8c"/>
|
<rom name="Nickelodeon SpongeBob SquarePants - Creatuur van de Krokante Krab (Netherlands).iso" size="1459978240" crc="58dc71d7" md5="45df2c017c82f4737ed154f3c53e0bfe" sha1="d1da9a9aede1c44063f066da35623ff9a92c3b8c"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 11 (30) (Europe) (Unl)">
|
<game name="Cube CD 11 (30) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 11 (30) (Europe) (Unl)</description>
|
<description>Cube CD 11 (30) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 11 (30) (Europe) (Unl).iso" size="1459978240" crc="de08bb29" md5="00a76920368c9719c6767b5d739eb5a9" sha1="9bcb7602cee82c533d950b9a424a5c793760a9ed"/>
|
<rom name="Cube CD 11 (30) (UK) (Unl).iso" size="1459978240" crc="de08bb29" md5="00a76920368c9719c6767b5d739eb5a9" sha1="9bcb7602cee82c533d950b9a424a5c793760a9ed"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 12 (31) (Europe) (Unl)">
|
<game name="Cube CD 12 (31) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 12 (31) (Europe) (Unl)</description>
|
<description>Cube CD 12 (31) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 12 (31) (Europe) (Unl).iso" size="1459978240" crc="67acea2c" md5="5d92c8e5057945c0944a0a4cbc5aa068" sha1="810c918a0469d1cd054cf37d2829ecfb25091c08"/>
|
<rom name="Cube CD 12 (31) (UK) (Unl).iso" size="1459978240" crc="67acea2c" md5="5d92c8e5057945c0944a0a4cbc5aa068" sha1="810c918a0469d1cd054cf37d2829ecfb25091c08"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 13 (32) (Europe) (Unl)">
|
<game name="Cube CD 13 (32) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 13 (32) (Europe) (Unl)</description>
|
<description>Cube CD 13 (32) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 13 (32) (Europe) (Unl).iso" size="1459978240" crc="4ee5dc34" md5="879a354177cbe51f602269480c423ecd" sha1="1961a864c80d92de323b710ca2125bf45806473f"/>
|
<rom name="Cube CD 13 (32) (UK) (Unl).iso" size="1459978240" crc="4ee5dc34" md5="879a354177cbe51f602269480c423ecd" sha1="1961a864c80d92de323b710ca2125bf45806473f"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 15 (34) (Europe) (Unl)">
|
<game name="Cube CD 15 (34) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 15 (34) (Europe) (Unl)</description>
|
<description>Cube CD 15 (34) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 15 (34) (Europe) (Unl).iso" size="1459978240" crc="4b9b91e6" md5="08522ad068345eca61ea22dc92f6cb45" sha1="2f362a1547d958e3d772fe9d8c400bc57e5d17f4"/>
|
<rom name="Cube CD 15 (34) (UK) (Unl).iso" size="1459978240" crc="4b9b91e6" md5="08522ad068345eca61ea22dc92f6cb45" sha1="2f362a1547d958e3d772fe9d8c400bc57e5d17f4"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="FreeLoader for GameCube (USA, Europe) (Unl) (v1.06b)">
|
<game name="FreeLoader for GameCube (USA, Europe) (Unl) (v1.06b)">
|
||||||
<category>Applications</category>
|
<category>Applications</category>
|
||||||
@@ -9225,30 +9225,30 @@
|
|||||||
<description>2002 FIFA World Cup (France)</description>
|
<description>2002 FIFA World Cup (France)</description>
|
||||||
<rom name="2002 FIFA World Cup (France).iso" size="1459978240" crc="f3de87a7" md5="d223250f71b82efe411d4710bd2c9d22" sha1="a88bd9f7d619df59558d2043b57730d3e23935b4"/>
|
<rom name="2002 FIFA World Cup (France).iso" size="1459978240" crc="f3de87a7" md5="d223250f71b82efe411d4710bd2c9d22" sha1="a88bd9f7d619df59558d2043b57730d3e23935b4"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 16 (35) (Europe) (Unl)">
|
<game name="Cube CD 16 (35) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 16 (35) (Europe) (Unl)</description>
|
<description>Cube CD 16 (35) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 16 (35) (Europe) (Unl).iso" size="1459978240" crc="e5c0156e" md5="ed3ba85d06eba0f60f84891e1f849d44" sha1="20e01588318a0aa88277f941b4e625bea34cf1ca"/>
|
<rom name="Cube CD 16 (35) (UK) (Unl).iso" size="1459978240" crc="e5c0156e" md5="ed3ba85d06eba0f60f84891e1f849d44" sha1="20e01588318a0aa88277f941b4e625bea34cf1ca"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 17 (36) (Europe) (Unl)">
|
<game name="Cube CD 17 (36) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 17 (36) (Europe) (Unl)</description>
|
<description>Cube CD 17 (36) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 17 (36) (Europe) (Unl).iso" size="1459978240" crc="9e7dc646" md5="5d381c783a736b73bbcb5133b39c181e" sha1="8cf84262a897d440fe7a18e2b85bada188534cad"/>
|
<rom name="Cube CD 17 (36) (UK) (Unl).iso" size="1459978240" crc="9e7dc646" md5="5d381c783a736b73bbcb5133b39c181e" sha1="8cf84262a897d440fe7a18e2b85bada188534cad"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 18 (37) (Europe) (Unl)">
|
<game name="Cube CD 18 (37) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 18 (37) (Europe) (Unl)</description>
|
<description>Cube CD 18 (37) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 18 (37) (Europe) (Unl).iso" size="1459978240" crc="1be165b7" md5="123af675aac82a2f6c4a51c297353336" sha1="ec1c5307e8a5c06c3181ca4125ba7e2b5abe8a2c"/>
|
<rom name="Cube CD 18 (37) (UK) (Unl).iso" size="1459978240" crc="1be165b7" md5="123af675aac82a2f6c4a51c297353336" sha1="ec1c5307e8a5c06c3181ca4125ba7e2b5abe8a2c"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 19 (38) (Europe) (Unl)">
|
<game name="Cube CD 19 (38) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 19 (38) (Europe) (Unl)</description>
|
<description>Cube CD 19 (38) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 19 (38) (Europe) (Unl).iso" size="1459978240" crc="1570e92e" md5="fd0dee6c5b4850e9ceab350721528314" sha1="b347fece4943897882e2a38b14c5691c36f2b023"/>
|
<rom name="Cube CD 19 (38) (UK) (Unl).iso" size="1459978240" crc="1570e92e" md5="fd0dee6c5b4850e9ceab350721528314" sha1="b347fece4943897882e2a38b14c5691c36f2b023"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 20 (40) (Europe) (Unl)">
|
<game name="Cube CD 20 (40) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 20 (40) (Europe) (Unl)</description>
|
<description>Cube CD 20 (40) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 20 (40) (Europe) (Unl).iso" size="1459978240" crc="eb7f7bc6" md5="1a4ba7a7d5bd2a195c0c4a4426940239" sha1="571dc6e8aa538e2501f89a5706b23b8f9e170e8f"/>
|
<rom name="Cube CD 20 (40) (UK) (Unl).iso" size="1459978240" crc="eb7f7bc6" md5="1a4ba7a7d5bd2a195c0c4a4426940239" sha1="571dc6e8aa538e2501f89a5706b23b8f9e170e8f"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="SRS - Street Racing Syndicate (Europe) (En,Fr,De,Es,It)">
|
<game name="SRS - Street Racing Syndicate (Europe) (En,Fr,De,Es,It)">
|
||||||
<category>Games</category>
|
<category>Games</category>
|
||||||
@@ -9475,10 +9475,10 @@
|
|||||||
<description>Gekkan Nintendo Tentou Demo 2003.10.1 (Japan) (Rev 1)</description>
|
<description>Gekkan Nintendo Tentou Demo 2003.10.1 (Japan) (Rev 1)</description>
|
||||||
<rom name="Gekkan Nintendo Tentou Demo 2003.10.1 (Japan) (Rev 1).iso" size="1459978240" crc="029014e4" md5="c7dcbdc2f69f048f10f31fdac1b5b785" sha1="0989d02c862580d52da060fd2f2de5e5d249dea3"/>
|
<rom name="Gekkan Nintendo Tentou Demo 2003.10.1 (Japan) (Rev 1).iso" size="1459978240" crc="029014e4" md5="c7dcbdc2f69f048f10f31fdac1b5b785" sha1="0989d02c862580d52da060fd2f2de5e5d249dea3"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 14 (33) (Europe) (Unl)">
|
<game name="Cube CD 14 (33) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 14 (33) (Europe) (Unl)</description>
|
<description>Cube CD 14 (33) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 14 (33) (Europe) (Unl).iso" size="1459978240" crc="b21fe659" md5="82109cff554d0ecadb0fffb7030dc5a8" sha1="884052c0eb3f0d515ca0c7b173e0a5dfd8071a35"/>
|
<rom name="Cube CD 14 (33) (UK) (Unl).iso" size="1459978240" crc="b21fe659" md5="82109cff554d0ecadb0fffb7030dc5a8" sha1="884052c0eb3f0d515ca0c7b173e0a5dfd8071a35"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Action Replay Max (Europe) (En,Fr,De,Es,It,Pt) (Unl)">
|
<game name="Action Replay Max (Europe) (En,Fr,De,Es,It,Pt) (Unl)">
|
||||||
<category>Applications</category>
|
<category>Applications</category>
|
||||||
@@ -9570,10 +9570,10 @@
|
|||||||
<description>Gekkan Nintendo Tentou Demo 2006.8.1 (Japan)</description>
|
<description>Gekkan Nintendo Tentou Demo 2006.8.1 (Japan)</description>
|
||||||
<rom name="Gekkan Nintendo Tentou Demo 2006.8.1 (Japan).iso" size="1459978240" crc="78927d2f" md5="cffa6161687fd723a32717c197d474bb" sha1="c537ecc5935cd9b284b43c230bb516bc9d3de54b"/>
|
<rom name="Gekkan Nintendo Tentou Demo 2006.8.1 (Japan).iso" size="1459978240" crc="78927d2f" md5="cffa6161687fd723a32717c197d474bb" sha1="c537ecc5935cd9b284b43c230bb516bc9d3de54b"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Cube CD 20 (39) (Europe) (Unl)">
|
<game name="Cube CD 20 (39) (UK) (Unl)">
|
||||||
<category>Coverdiscs</category>
|
<category>Coverdiscs</category>
|
||||||
<description>Cube CD 20 (39) (Europe) (Unl)</description>
|
<description>Cube CD 20 (39) (UK) (Unl)</description>
|
||||||
<rom name="Cube CD 20 (39) (Europe) (Unl).iso" size="1459978240" crc="06b90505" md5="574f91a0dad19815a494a79ba76a6c5d" sha1="bd4a3c28f4e2bcffd7305932a1b6548af455d794"/>
|
<rom name="Cube CD 20 (39) (UK) (Unl).iso" size="1459978240" crc="06b90505" md5="574f91a0dad19815a494a79ba76a6c5d" sha1="bd4a3c28f4e2bcffd7305932a1b6548af455d794"/>
|
||||||
</game>
|
</game>
|
||||||
<game name="Ultimate Codes for Use with Tom Clancy's Splinter Cell (USA) (Unl)">
|
<game name="Ultimate Codes for Use with Tom Clancy's Splinter Cell (USA) (Unl)">
|
||||||
<category>Applications</category>
|
<category>Applications</category>
|
||||||
@@ -9955,4 +9955,19 @@
|
|||||||
<description>WWE WrestleMania X8 (Japan) (Taikenban)</description>
|
<description>WWE WrestleMania X8 (Japan) (Taikenban)</description>
|
||||||
<rom name="WWE WrestleMania X8 (Japan) (Taikenban).iso" size="1459978240" crc="f676c652" md5="c001005e01e02fb02c40c562c7dc4d78" sha1="ace6cf324e04d35d008b12aa681c857d72353d25"/>
|
<rom name="WWE WrestleMania X8 (Japan) (Taikenban).iso" size="1459978240" crc="f676c652" md5="c001005e01e02fb02c40c562c7dc4d78" sha1="ace6cf324e04d35d008b12aa681c857d72353d25"/>
|
||||||
</game>
|
</game>
|
||||||
|
<game name="Karat GC-you Pro Action Replay - Best Price! Sokukouryaku GC-you Vol. 1 (Japan) (Unl)">
|
||||||
|
<category>Applications</category>
|
||||||
|
<description>Karat GC-you Pro Action Replay - Best Price! Sokukouryaku GC-you Vol. 1 (Japan) (Unl)</description>
|
||||||
|
<rom name="Karat GC-you Pro Action Replay - Best Price! Sokukouryaku GC-you Vol. 1 (Japan) (Unl).iso" size="1459978240" crc="1c41b917" md5="a941c5a462d1e90c1de5c9e169dc7237" sha1="c15db6b3d12ca21086bcd8c9404a4d143ccf1110"/>
|
||||||
|
</game>
|
||||||
|
<game name="Karat GC-you Pro Action Replay PAR GC-you (Japan) (Unl) (v1.07)">
|
||||||
|
<category>Applications</category>
|
||||||
|
<description>Karat GC-you Pro Action Replay PAR GC-you (Japan) (Unl) (v1.07)</description>
|
||||||
|
<rom name="Karat GC-you Pro Action Replay PAR GC-you (Japan) (Unl) (v1.07).iso" size="1459978240" crc="26649910" md5="7993ec33bfc482e29f23293c39c56fc3" sha1="402ee1cd9edf5f445c130bbd5a72b2967e673c22"/>
|
||||||
|
</game>
|
||||||
|
<game name="Evolution Worlds (USA) (Beta)">
|
||||||
|
<category>Preproduction</category>
|
||||||
|
<description>Evolution Worlds (USA) (Beta)</description>
|
||||||
|
<rom name="Evolution Worlds (USA) (Beta).iso" size="1459978240" crc="74e3fbee" md5="f5a5d5d02b8ce369b53e5efcaf2c5d71" sha1="061ba70fe611a7c36a3a99dc52839fc275724f19"/>
|
||||||
|
</game>
|
||||||
</datafile>
|
</datafile>
|
||||||
+43
-15
@@ -40,48 +40,71 @@ fn main() {
|
|||||||
|
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
let out_dir = env::var("OUT_DIR").unwrap();
|
||||||
let dest_path = Path::new(&out_dir).join("parsed-dats.bin");
|
let dest_path = Path::new(&out_dir).join("parsed-dats.bin");
|
||||||
let mut f = BufWriter::new(File::create(dest_path).unwrap());
|
let out_file = File::create(dest_path).expect("Failed to open out file");
|
||||||
|
let mut out = zstd::Encoder::new(BufWriter::new(out_file), zstd::zstd_safe::max_c_level())
|
||||||
|
.expect("Failed to create zstd encoder");
|
||||||
|
|
||||||
// Parse dat files
|
// Parse dat files
|
||||||
let mut entries = Vec::<(GameEntry, String)>::new();
|
let mut entries = Vec::<(GameEntry, String)>::new();
|
||||||
for path in ["assets/redump-gc.dat", "assets/redump-wii.dat"] {
|
for path in [
|
||||||
|
"assets/gc-non-redump.dat",
|
||||||
|
"assets/gc-npdp.dat",
|
||||||
|
"assets/gc-redump.dat",
|
||||||
|
"assets/wii-redump.dat",
|
||||||
|
] {
|
||||||
println!("cargo:rustc-rerun-if-changed={}", path);
|
println!("cargo:rustc-rerun-if-changed={}", path);
|
||||||
let file = BufReader::new(File::open(path).expect("Failed to open dat file"));
|
let file = BufReader::new(File::open(path).expect("Failed to open dat file"));
|
||||||
let dat: DatFile = quick_xml::de::from_reader(file).expect("Failed to parse dat file");
|
let dat: DatFile = quick_xml::de::from_reader(file).expect("Failed to parse dat file");
|
||||||
entries.extend(dat.games.into_iter().map(|game| {
|
entries.extend(dat.games.into_iter().filter_map(|game| {
|
||||||
(
|
if game.roms.len() != 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let rom = &game.roms[0];
|
||||||
|
Some((
|
||||||
GameEntry {
|
GameEntry {
|
||||||
string_table_offset: 0,
|
string_table_offset: 0,
|
||||||
crc32: u32::from_be_bytes(game.rom.crc32),
|
crc32: u32::from_be_bytes(rom.crc32),
|
||||||
md5: game.rom.md5,
|
md5: rom.md5,
|
||||||
sha1: game.rom.sha1,
|
sha1: rom.sha1,
|
||||||
sectors: game.rom.size.div_ceil(0x8000) as u32,
|
sectors: rom.size.div_ceil(0x8000) as u32,
|
||||||
},
|
},
|
||||||
game.name,
|
game.name,
|
||||||
)
|
))
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by CRC32
|
// Sort by CRC32
|
||||||
entries.sort_by_key(|(entry, _)| entry.crc32);
|
entries.sort_by_key(|(entry, _)| entry.crc32);
|
||||||
|
|
||||||
|
// Calculate total size and store in zstd header
|
||||||
|
let entries_size = entries.len() * size_of::<GameEntry>();
|
||||||
|
let string_table_size = entries.iter().map(|(_, name)| name.len() + 4).sum::<usize>();
|
||||||
|
let total_size = size_of::<Header>() + entries_size + string_table_size;
|
||||||
|
out.set_pledged_src_size(Some(total_size as u64)).unwrap();
|
||||||
|
out.include_contentsize(true).unwrap();
|
||||||
|
|
||||||
// Write game entries
|
// Write game entries
|
||||||
let header =
|
let header =
|
||||||
Header { entry_count: entries.len() as u32, entry_size: size_of::<GameEntry>() as u32 };
|
Header { entry_count: entries.len() as u32, entry_size: size_of::<GameEntry>() as u32 };
|
||||||
f.write_all(header.as_bytes()).unwrap();
|
out.write_all(header.as_bytes()).unwrap();
|
||||||
let mut string_table_offset = 0u32;
|
let mut string_table_offset = 0u32;
|
||||||
for (entry, name) in &mut entries {
|
for (entry, name) in &mut entries {
|
||||||
entry.string_table_offset = string_table_offset;
|
entry.string_table_offset = string_table_offset;
|
||||||
f.write_all(entry.as_bytes()).unwrap();
|
out.write_all(entry.as_bytes()).unwrap();
|
||||||
string_table_offset += name.as_bytes().len() as u32 + 4;
|
string_table_offset += name.as_bytes().len() as u32 + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write string table
|
// Write string table
|
||||||
for (_, name) in &entries {
|
for (_, name) in &entries {
|
||||||
f.write_all(&(name.len() as u32).to_le_bytes()).unwrap();
|
out.write_all(&(name.len() as u32).to_le_bytes()).unwrap();
|
||||||
f.write_all(name.as_bytes()).unwrap();
|
out.write_all(name.as_bytes()).unwrap();
|
||||||
}
|
}
|
||||||
f.flush().unwrap();
|
|
||||||
|
// Finalize
|
||||||
|
out.finish()
|
||||||
|
.expect("Failed to finish zstd encoder")
|
||||||
|
.flush()
|
||||||
|
.expect("Failed to flush output file");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
@@ -94,11 +117,16 @@ struct DatFile {
|
|||||||
struct DatGame {
|
struct DatGame {
|
||||||
#[serde(rename = "@name")]
|
#[serde(rename = "@name")]
|
||||||
name: String,
|
name: String,
|
||||||
rom: DatGameRom,
|
// #[serde(rename = "category", default)]
|
||||||
|
// categories: Vec<String>,
|
||||||
|
#[serde(rename = "rom")]
|
||||||
|
roms: Vec<DatGameRom>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
struct DatGameRom {
|
struct DatGameRom {
|
||||||
|
// #[serde(rename = "@name")]
|
||||||
|
// name: String,
|
||||||
#[serde(rename = "@size")]
|
#[serde(rename = "@size")]
|
||||||
size: u64,
|
size: u64,
|
||||||
#[serde(rename = "@crc", deserialize_with = "deserialize_hex")]
|
#[serde(rename = "@crc", deserialize_with = "deserialize_hex")]
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use argp::FromArgs;
|
use argp::FromArgs;
|
||||||
|
|
||||||
use crate::util::shared::convert_and_verify;
|
use crate::util::{redump, shared::convert_and_verify};
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(FromArgs, Debug)]
|
||||||
/// Converts a disc image to ISO.
|
/// Converts a disc image to ISO.
|
||||||
#[argp(subcommand, name = "convert")]
|
#[argp(subcommand, name = "convert")]
|
||||||
pub struct ConvertArgs {
|
pub struct Args {
|
||||||
#[argp(positional)]
|
#[argp(positional)]
|
||||||
/// path to disc image
|
/// path to disc image
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
@@ -17,8 +17,15 @@ pub struct ConvertArgs {
|
|||||||
#[argp(switch)]
|
#[argp(switch)]
|
||||||
/// enable MD5 hashing (slower)
|
/// enable MD5 hashing (slower)
|
||||||
md5: bool,
|
md5: bool,
|
||||||
|
#[argp(option, short = 'd')]
|
||||||
|
/// path to DAT file(s) for verification (optional)
|
||||||
|
dat: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn convert(args: ConvertArgs) -> nod::Result<()> {
|
pub fn run(args: Args) -> nod::Result<()> {
|
||||||
|
if !args.dat.is_empty() {
|
||||||
|
println!("Loading dat files...");
|
||||||
|
redump::load_dats(args.dat.iter().map(PathBuf::as_ref))?;
|
||||||
|
}
|
||||||
convert_and_verify(&args.file, Some(&args.out), args.md5)
|
convert_and_verify(&args.file, Some(&args.out), args.md5)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
use std::{
|
||||||
|
cmp::min,
|
||||||
|
collections::BTreeMap,
|
||||||
|
fmt,
|
||||||
|
io::Read,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::{mpsc::sync_channel, Arc},
|
||||||
|
thread,
|
||||||
|
};
|
||||||
|
|
||||||
|
use argp::FromArgs;
|
||||||
|
use indicatif::{ProgressBar, ProgressState, ProgressStyle};
|
||||||
|
use nod::{Disc, OpenOptions, Result, ResultContext};
|
||||||
|
use zerocopy::FromZeroes;
|
||||||
|
|
||||||
|
use crate::util::{
|
||||||
|
digest::{digest_thread, DigestResult},
|
||||||
|
redump,
|
||||||
|
redump::GameResult,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(FromArgs, Debug)]
|
||||||
|
/// Commands related to DAT files.
|
||||||
|
#[argp(subcommand, name = "dat")]
|
||||||
|
pub struct Args {
|
||||||
|
#[argp(subcommand)]
|
||||||
|
command: SubCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromArgs, Debug)]
|
||||||
|
#[argp(subcommand)]
|
||||||
|
pub enum SubCommand {
|
||||||
|
Check(CheckArgs),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(FromArgs, Debug)]
|
||||||
|
/// Verify a collection of disc images against DAT files.
|
||||||
|
#[argp(subcommand, name = "check")]
|
||||||
|
pub struct CheckArgs {
|
||||||
|
#[argp(positional)]
|
||||||
|
/// disc image directory
|
||||||
|
dir: PathBuf,
|
||||||
|
#[argp(option, short = 'd')]
|
||||||
|
/// path to DAT file(s)
|
||||||
|
dat: Vec<PathBuf>,
|
||||||
|
#[argp(switch)]
|
||||||
|
/// rename files to match DAT entries
|
||||||
|
rename: bool,
|
||||||
|
#[argp(switch)]
|
||||||
|
/// don't use embedded hashes if available
|
||||||
|
full_verify: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(args: Args) -> Result<()> {
|
||||||
|
match args.command {
|
||||||
|
SubCommand::Check(c_args) => check(c_args),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check(args: CheckArgs) -> Result<()> {
|
||||||
|
if !args.dat.is_empty() {
|
||||||
|
println!("Loading dat files...");
|
||||||
|
redump::load_dats(args.dat.iter().map(PathBuf::as_ref))?;
|
||||||
|
}
|
||||||
|
let mut disc_results = BTreeMap::<u32, DiscResult>::new();
|
||||||
|
let mut rename_map = BTreeMap::<PathBuf, PathBuf>::new();
|
||||||
|
for entry in std::fs::read_dir(&args.dir).context("Opening ROM directory")? {
|
||||||
|
let entry = entry.context("Reading ROM directory entry")?;
|
||||||
|
let path = entry.path();
|
||||||
|
if path.is_file() {
|
||||||
|
let name = entry.file_name().to_string_lossy().to_string();
|
||||||
|
match load_disc(&path, &name, args.full_verify) {
|
||||||
|
Ok(hashes) => {
|
||||||
|
let redump_entry = redump::find_by_crc32(hashes.crc32);
|
||||||
|
if let Some(entry) = &redump_entry {
|
||||||
|
let mut full_match = true;
|
||||||
|
if entry.sha1 != hashes.sha1 {
|
||||||
|
full_match = false;
|
||||||
|
}
|
||||||
|
if full_match {
|
||||||
|
println!("{}: ✅ {}", name, entry.name);
|
||||||
|
} else {
|
||||||
|
println!("{}: ❓ {} (partial match)", name, entry.name);
|
||||||
|
}
|
||||||
|
if entry.name != path.file_stem().unwrap() {
|
||||||
|
let file_name = if let Some(ext) = path.extension() {
|
||||||
|
format!("{}.{}", entry.name, ext.to_string_lossy())
|
||||||
|
} else {
|
||||||
|
entry.name.to_string()
|
||||||
|
};
|
||||||
|
rename_map.insert(path.clone(), path.with_file_name(file_name));
|
||||||
|
}
|
||||||
|
disc_results.insert(hashes.crc32, DiscResult {
|
||||||
|
name,
|
||||||
|
// hashes,
|
||||||
|
redump_entry: Some(entry.clone()),
|
||||||
|
matched: full_match,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
println!("{}: ❌ Not found", name);
|
||||||
|
disc_results.insert(hashes.crc32, DiscResult {
|
||||||
|
name,
|
||||||
|
// hashes,
|
||||||
|
redump_entry: None,
|
||||||
|
matched: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => println!("{}: ❌ Error: {}", name, e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!();
|
||||||
|
let mut matched_count = 0usize;
|
||||||
|
let mut missing_count = 0usize;
|
||||||
|
let mut mismatch_count = 0usize;
|
||||||
|
let mut total_count = 0usize;
|
||||||
|
let mut extra_count = 0usize;
|
||||||
|
for entry in redump::EntryIter::new() {
|
||||||
|
if let Some(result) = disc_results.get(&entry.crc32) {
|
||||||
|
if result.matched {
|
||||||
|
matched_count += 1;
|
||||||
|
} else {
|
||||||
|
println!("❓ Mismatched: {}", entry.name);
|
||||||
|
mismatch_count += 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("❌ Missing: {}", entry.name);
|
||||||
|
missing_count += 1;
|
||||||
|
}
|
||||||
|
total_count += 1;
|
||||||
|
}
|
||||||
|
for result in disc_results.values() {
|
||||||
|
if !result.matched && result.redump_entry.is_none() {
|
||||||
|
println!("❓ Unmatched: {}", result.name);
|
||||||
|
extra_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!(
|
||||||
|
"Matched: {}, Missing: {}, Mismatched: {}, Total: {}",
|
||||||
|
matched_count, missing_count, mismatch_count, total_count
|
||||||
|
);
|
||||||
|
println!("Unmatched: {}", extra_count);
|
||||||
|
|
||||||
|
if args.rename && !rename_map.is_empty() {
|
||||||
|
println!("\nRenaming files...");
|
||||||
|
for (old_path, new_path) in rename_map {
|
||||||
|
println!("{} -> {}", old_path.display(), new_path.display());
|
||||||
|
std::fs::rename(&old_path, &new_path).context("Renaming file")?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DiscResult {
|
||||||
|
pub name: String,
|
||||||
|
// pub hashes: DiscHashes,
|
||||||
|
pub redump_entry: Option<GameResult<'static>>,
|
||||||
|
pub matched: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DiscHashes {
|
||||||
|
pub crc32: u32,
|
||||||
|
pub sha1: [u8; 20],
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_disc(path: &Path, name: &str, full_verify: bool) -> Result<DiscHashes> {
|
||||||
|
let mut disc = Disc::new_with_options(path, &OpenOptions {
|
||||||
|
rebuild_encryption: true,
|
||||||
|
validate_hashes: false,
|
||||||
|
})?;
|
||||||
|
let disc_size = disc.disc_size();
|
||||||
|
if !full_verify {
|
||||||
|
let meta = disc.meta();
|
||||||
|
if let (Some(crc32), Some(sha1)) = (meta.crc32, meta.sha1) {
|
||||||
|
return Ok(DiscHashes { crc32, sha1 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let pb = ProgressBar::new(disc_size).with_message(format!("{}:", name));
|
||||||
|
pb.set_style(ProgressStyle::with_template("{msg} {spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({bytes_per_sec}, {eta})")
|
||||||
|
.unwrap()
|
||||||
|
.with_key("eta", |state: &ProgressState, w: &mut dyn fmt::Write| {
|
||||||
|
write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap()
|
||||||
|
})
|
||||||
|
.progress_chars("#>-"));
|
||||||
|
|
||||||
|
const BUFFER_SIZE: usize = 1015808; // LCM(0x8000, 0x7C00)
|
||||||
|
let digest_threads = [digest_thread::<crc32fast::Hasher>(), digest_thread::<sha1::Sha1>()];
|
||||||
|
|
||||||
|
let (w_tx, w_rx) = sync_channel::<Arc<[u8]>>(1);
|
||||||
|
let w_thread = thread::spawn(move || {
|
||||||
|
let mut total_written = 0u64;
|
||||||
|
while let Ok(data) = w_rx.recv() {
|
||||||
|
total_written += data.len() as u64;
|
||||||
|
pb.set_position(total_written);
|
||||||
|
}
|
||||||
|
pb.finish_and_clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut total_read = 0u64;
|
||||||
|
let mut buf = <u8>::new_box_slice_zeroed(BUFFER_SIZE);
|
||||||
|
while total_read < disc_size {
|
||||||
|
let read = min(BUFFER_SIZE as u64, disc_size - total_read) as usize;
|
||||||
|
disc.read_exact(&mut buf[..read]).with_context(|| {
|
||||||
|
format!("Reading {} bytes at disc offset {}", BUFFER_SIZE, total_read)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let arc = Arc::<[u8]>::from(&buf[..read]);
|
||||||
|
for (tx, _) in &digest_threads {
|
||||||
|
tx.send(arc.clone()).map_err(|_| "Sending data to hash thread")?;
|
||||||
|
}
|
||||||
|
w_tx.send(arc).map_err(|_| "Sending data to write thread")?;
|
||||||
|
total_read += read as u64;
|
||||||
|
}
|
||||||
|
drop(w_tx); // Close channel
|
||||||
|
w_thread.join().unwrap();
|
||||||
|
|
||||||
|
let mut crc32 = None;
|
||||||
|
let mut sha1 = None;
|
||||||
|
for (tx, handle) in digest_threads {
|
||||||
|
drop(tx); // Close channel
|
||||||
|
match handle.join().unwrap() {
|
||||||
|
DigestResult::Crc32(v) => crc32 = Some(v),
|
||||||
|
DigestResult::Sha1(v) => sha1 = Some(v),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(DiscHashes { crc32: crc32.unwrap(), sha1: sha1.unwrap() })
|
||||||
|
}
|
||||||
@@ -19,9 +19,9 @@ use zerocopy::AsBytes;
|
|||||||
use crate::util::{display, has_extension};
|
use crate::util::{display, has_extension};
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(FromArgs, Debug)]
|
||||||
/// Extract a disc image.
|
/// Extracts a disc image.
|
||||||
#[argp(subcommand, name = "extract")]
|
#[argp(subcommand, name = "extract")]
|
||||||
pub struct ExtractArgs {
|
pub struct Args {
|
||||||
#[argp(positional)]
|
#[argp(positional)]
|
||||||
/// Path to disc image
|
/// Path to disc image
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
@@ -40,7 +40,7 @@ pub struct ExtractArgs {
|
|||||||
partition: Option<String>,
|
partition: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn extract(args: ExtractArgs) -> nod::Result<()> {
|
pub fn run(args: Args) -> nod::Result<()> {
|
||||||
let output_dir: PathBuf;
|
let output_dir: PathBuf;
|
||||||
if let Some(dir) = args.out {
|
if let Some(dir) = args.out {
|
||||||
output_dir = dir;
|
output_dir = dir;
|
||||||
|
|||||||
@@ -9,13 +9,13 @@ use crate::util::{display, shared::print_header};
|
|||||||
#[derive(FromArgs, Debug)]
|
#[derive(FromArgs, Debug)]
|
||||||
/// Displays information about disc images.
|
/// Displays information about disc images.
|
||||||
#[argp(subcommand, name = "info")]
|
#[argp(subcommand, name = "info")]
|
||||||
pub struct InfoArgs {
|
pub struct Args {
|
||||||
#[argp(positional)]
|
#[argp(positional)]
|
||||||
/// Path to disc image(s)
|
/// Path to disc image(s)
|
||||||
file: Vec<PathBuf>,
|
file: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn info(args: InfoArgs) -> nod::Result<()> {
|
pub fn run(args: Args) -> nod::Result<()> {
|
||||||
for file in &args.file {
|
for file in &args.file {
|
||||||
info_file(file)?;
|
info_file(file)?;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
pub mod convert;
|
pub mod convert;
|
||||||
|
pub mod dat;
|
||||||
pub mod extract;
|
pub mod extract;
|
||||||
pub mod info;
|
pub mod info;
|
||||||
pub mod verify;
|
pub mod verify;
|
||||||
|
|||||||
@@ -2,21 +2,28 @@ use std::path::PathBuf;
|
|||||||
|
|
||||||
use argp::FromArgs;
|
use argp::FromArgs;
|
||||||
|
|
||||||
use crate::util::shared::convert_and_verify;
|
use crate::util::{redump, shared::convert_and_verify};
|
||||||
|
|
||||||
#[derive(FromArgs, Debug)]
|
#[derive(FromArgs, Debug)]
|
||||||
/// Verifies disc images.
|
/// Verifies disc images.
|
||||||
#[argp(subcommand, name = "verify")]
|
#[argp(subcommand, name = "verify")]
|
||||||
pub struct VerifyArgs {
|
pub struct Args {
|
||||||
#[argp(positional)]
|
#[argp(positional)]
|
||||||
/// path to disc image(s)
|
/// path to disc image(s)
|
||||||
file: Vec<PathBuf>,
|
file: Vec<PathBuf>,
|
||||||
#[argp(switch)]
|
#[argp(switch)]
|
||||||
/// enable MD5 hashing (slower)
|
/// enable MD5 hashing (slower)
|
||||||
md5: bool,
|
md5: bool,
|
||||||
|
#[argp(option, short = 'd')]
|
||||||
|
/// path to DAT file(s) for verification (optional)
|
||||||
|
dat: Vec<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify(args: VerifyArgs) -> nod::Result<()> {
|
pub fn run(args: Args) -> nod::Result<()> {
|
||||||
|
if !args.dat.is_empty() {
|
||||||
|
println!("Loading dat files...");
|
||||||
|
redump::load_dats(args.dat.iter().map(PathBuf::as_ref))?;
|
||||||
|
}
|
||||||
for file in &args.file {
|
for file in &args.file {
|
||||||
convert_and_verify(file, None, args.md5)?;
|
convert_and_verify(file, None, args.md5)?;
|
||||||
println!();
|
println!();
|
||||||
|
|||||||
+10
-8
@@ -6,17 +6,19 @@ pub(crate) mod util;
|
|||||||
#[derive(FromArgs, Debug)]
|
#[derive(FromArgs, Debug)]
|
||||||
#[argp(subcommand)]
|
#[argp(subcommand)]
|
||||||
pub enum SubCommand {
|
pub enum SubCommand {
|
||||||
Info(cmd::info::InfoArgs),
|
Dat(cmd::dat::Args),
|
||||||
Extract(cmd::extract::ExtractArgs),
|
Info(cmd::info::Args),
|
||||||
Convert(cmd::convert::ConvertArgs),
|
Extract(cmd::extract::Args),
|
||||||
Verify(cmd::verify::VerifyArgs),
|
Convert(cmd::convert::Args),
|
||||||
|
Verify(cmd::verify::Args),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(command: SubCommand) -> nod::Result<()> {
|
pub fn run(command: SubCommand) -> nod::Result<()> {
|
||||||
match command {
|
match command {
|
||||||
SubCommand::Info(c_args) => cmd::info::info(c_args),
|
SubCommand::Dat(c_args) => cmd::dat::run(c_args),
|
||||||
SubCommand::Convert(c_args) => cmd::convert::convert(c_args),
|
SubCommand::Info(c_args) => cmd::info::run(c_args),
|
||||||
SubCommand::Extract(c_args) => cmd::extract::extract(c_args),
|
SubCommand::Convert(c_args) => cmd::convert::run(c_args),
|
||||||
SubCommand::Verify(c_args) => cmd::verify::verify(c_args),
|
SubCommand::Extract(c_args) => cmd::extract::run(c_args),
|
||||||
|
SubCommand::Verify(c_args) => cmd::verify::run(c_args),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+158
-15
@@ -1,25 +1,70 @@
|
|||||||
use std::{mem::size_of, str};
|
use std::{
|
||||||
|
fs::File,
|
||||||
|
io::{BufReader, Cursor, Write},
|
||||||
|
mem::size_of,
|
||||||
|
path::Path,
|
||||||
|
str,
|
||||||
|
sync::OnceLock,
|
||||||
|
};
|
||||||
|
|
||||||
use nod::array_ref;
|
use hex::deserialize as deserialize_hex;
|
||||||
use zerocopy::{FromBytes, FromZeroes};
|
use nod::{array_ref, Result};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use zerocopy::{AsBytes, FromBytes, FromZeroes};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct GameResult {
|
pub struct GameResult<'a> {
|
||||||
pub name: &'static str,
|
pub name: &'a str,
|
||||||
pub crc32: u32,
|
pub crc32: u32,
|
||||||
pub md5: [u8; 16],
|
pub md5: [u8; 16],
|
||||||
pub sha1: [u8; 20],
|
pub sha1: [u8; 20],
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_by_crc32(crc32: u32) -> Option<GameResult> {
|
pub struct EntryIter<'a> {
|
||||||
let header: &Header = Header::ref_from_prefix(&DATA.0).unwrap();
|
data: &'a [u8],
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EntryIter<'static> {
|
||||||
|
pub fn new() -> EntryIter<'static> { Self { data: loaded_data(), index: 0 } }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for EntryIter<'a> {
|
||||||
|
type Item = GameResult<'a>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let header: &Header = Header::ref_from_prefix(self.data).unwrap();
|
||||||
|
assert_eq!(header.entry_size as usize, size_of::<GameEntry>());
|
||||||
|
if self.index >= header.entry_count as usize {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let entries_size = header.entry_count as usize * size_of::<GameEntry>();
|
||||||
|
let entries: &[GameEntry] = GameEntry::slice_from(
|
||||||
|
&self.data[size_of::<Header>()..size_of::<Header>() + entries_size],
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let string_table: &[u8] = &self.data[size_of::<Header>() + entries_size..];
|
||||||
|
|
||||||
|
let entry = &entries[self.index];
|
||||||
|
let offset = entry.string_table_offset as usize;
|
||||||
|
let name_size = u32::from_ne_bytes(*array_ref![string_table, offset, 4]) as usize;
|
||||||
|
let name = str::from_utf8(&string_table[offset + 4..offset + 4 + name_size]).unwrap();
|
||||||
|
self.index += 1;
|
||||||
|
Some(GameResult { name, crc32: entry.crc32, md5: entry.md5, sha1: entry.sha1 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn find_by_crc32(crc32: u32) -> Option<GameResult<'static>> {
|
||||||
|
let data = loaded_data();
|
||||||
|
let header: &Header = Header::ref_from_prefix(data).unwrap();
|
||||||
assert_eq!(header.entry_size as usize, size_of::<GameEntry>());
|
assert_eq!(header.entry_size as usize, size_of::<GameEntry>());
|
||||||
|
|
||||||
let entries_size = header.entry_count as usize * size_of::<GameEntry>();
|
let entries_size = header.entry_count as usize * size_of::<GameEntry>();
|
||||||
let entries: &[GameEntry] =
|
let entries: &[GameEntry] =
|
||||||
GameEntry::slice_from(&DATA.0[size_of::<Header>()..size_of::<Header>() + entries_size])
|
GameEntry::slice_from(&data[size_of::<Header>()..size_of::<Header>() + entries_size])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let string_table: &[u8] = &DATA.0[size_of::<Header>() + entries_size..];
|
let string_table: &[u8] = &data[size_of::<Header>() + entries_size..];
|
||||||
|
|
||||||
// Binary search by CRC32
|
// Binary search by CRC32
|
||||||
let index = entries.binary_search_by_key(&crc32, |entry| entry.crc32).ok()?;
|
let index = entries.binary_search_by_key(&crc32, |entry| entry.crc32).ok()?;
|
||||||
@@ -32,14 +77,82 @@ pub fn find_by_crc32(crc32: u32) -> Option<GameResult> {
|
|||||||
Some(GameResult { name, crc32: entry.crc32, md5: entry.md5, sha1: entry.sha1 })
|
Some(GameResult { name, crc32: entry.crc32, md5: entry.md5, sha1: entry.sha1 })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(C, align(4))]
|
const BUILTIN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/parsed-dats.bin"));
|
||||||
struct Aligned<T: ?Sized>(T);
|
static LOADED: OnceLock<Box<[u8]>> = OnceLock::new();
|
||||||
|
|
||||||
const DATA: &Aligned<[u8]> =
|
fn loaded_data() -> &'static [u8] {
|
||||||
&Aligned(*include_bytes!(concat!(env!("OUT_DIR"), "/parsed-dats.bin")));
|
LOADED
|
||||||
|
.get_or_init(|| {
|
||||||
|
let size = zstd::zstd_safe::get_frame_content_size(BUILTIN).unwrap().unwrap() as usize;
|
||||||
|
let mut out = <u8>::new_box_slice_zeroed(size);
|
||||||
|
let out_size = zstd::bulk::Decompressor::new()
|
||||||
|
.unwrap()
|
||||||
|
.decompress_to_buffer(BUILTIN, out.as_mut())
|
||||||
|
.unwrap();
|
||||||
|
debug_assert_eq!(out_size, size);
|
||||||
|
out
|
||||||
|
})
|
||||||
|
.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_dats<'a>(paths: impl Iterator<Item = &'a Path>) -> Result<()> {
|
||||||
|
// Parse dat files
|
||||||
|
let mut entries = Vec::<(GameEntry, String)>::new();
|
||||||
|
for path in paths {
|
||||||
|
let file = BufReader::new(File::open(path).expect("Failed to open dat file"));
|
||||||
|
let dat: DatFile = quick_xml::de::from_reader(file).expect("Failed to parse dat file");
|
||||||
|
entries.extend(dat.games.into_iter().filter_map(|game| {
|
||||||
|
if game.roms.len() != 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let rom = &game.roms[0];
|
||||||
|
Some((
|
||||||
|
GameEntry {
|
||||||
|
string_table_offset: 0,
|
||||||
|
crc32: u32::from_be_bytes(rom.crc32),
|
||||||
|
md5: rom.md5,
|
||||||
|
sha1: rom.sha1,
|
||||||
|
sectors: rom.size.div_ceil(0x8000) as u32,
|
||||||
|
},
|
||||||
|
game.name,
|
||||||
|
))
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort by CRC32
|
||||||
|
entries.sort_by_key(|(entry, _)| entry.crc32);
|
||||||
|
|
||||||
|
// Calculate total size
|
||||||
|
let entries_size = entries.len() * size_of::<GameEntry>();
|
||||||
|
let string_table_size = entries.iter().map(|(_, name)| name.len() + 4).sum::<usize>();
|
||||||
|
let total_size = size_of::<Header>() + entries_size + string_table_size;
|
||||||
|
let mut result = <u8>::new_box_slice_zeroed(total_size);
|
||||||
|
let mut out = Cursor::new(result.as_mut());
|
||||||
|
|
||||||
|
// Write game entries
|
||||||
|
let header =
|
||||||
|
Header { entry_count: entries.len() as u32, entry_size: size_of::<GameEntry>() as u32 };
|
||||||
|
out.write_all(header.as_bytes()).unwrap();
|
||||||
|
let mut string_table_offset = 0u32;
|
||||||
|
for (entry, name) in &mut entries {
|
||||||
|
entry.string_table_offset = string_table_offset;
|
||||||
|
out.write_all(entry.as_bytes()).unwrap();
|
||||||
|
string_table_offset += name.as_bytes().len() as u32 + 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write string table
|
||||||
|
for (_, name) in &entries {
|
||||||
|
out.write_all(&(name.len() as u32).to_le_bytes()).unwrap();
|
||||||
|
out.write_all(name.as_bytes()).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finalize
|
||||||
|
assert_eq!(out.position() as usize, total_size);
|
||||||
|
LOADED.set(result).map_err(|_| nod::Error::Other("dats already loaded".to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
// Keep in sync with build.rs
|
// Keep in sync with build.rs
|
||||||
#[derive(Clone, Debug, FromBytes, FromZeroes)]
|
#[derive(Clone, Debug, AsBytes, FromBytes, FromZeroes)]
|
||||||
#[repr(C, align(4))]
|
#[repr(C, align(4))]
|
||||||
struct Header {
|
struct Header {
|
||||||
entry_count: u32,
|
entry_count: u32,
|
||||||
@@ -47,7 +160,7 @@ struct Header {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Keep in sync with build.rs
|
// Keep in sync with build.rs
|
||||||
#[derive(Clone, Debug, FromBytes, FromZeroes)]
|
#[derive(Clone, Debug, AsBytes, FromBytes, FromZeroes)]
|
||||||
#[repr(C, align(4))]
|
#[repr(C, align(4))]
|
||||||
struct GameEntry {
|
struct GameEntry {
|
||||||
crc32: u32,
|
crc32: u32,
|
||||||
@@ -56,3 +169,33 @@ struct GameEntry {
|
|||||||
md5: [u8; 16],
|
md5: [u8; 16],
|
||||||
sha1: [u8; 20],
|
sha1: [u8; 20],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
struct DatFile {
|
||||||
|
#[serde(rename = "game")]
|
||||||
|
games: Vec<DatGame>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
struct DatGame {
|
||||||
|
#[serde(rename = "@name")]
|
||||||
|
name: String,
|
||||||
|
// #[serde(rename = "category", default)]
|
||||||
|
// categories: Vec<String>,
|
||||||
|
#[serde(rename = "rom")]
|
||||||
|
roms: Vec<DatGameRom>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
struct DatGameRom {
|
||||||
|
// #[serde(rename = "@name")]
|
||||||
|
// name: String,
|
||||||
|
#[serde(rename = "@size")]
|
||||||
|
size: u64,
|
||||||
|
#[serde(rename = "@crc", deserialize_with = "deserialize_hex")]
|
||||||
|
crc32: [u8; 4],
|
||||||
|
#[serde(rename = "@md5", deserialize_with = "deserialize_hex")]
|
||||||
|
md5: [u8; 16],
|
||||||
|
#[serde(rename = "@sha1", deserialize_with = "deserialize_hex")]
|
||||||
|
sha1: [u8; 20],
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user