Add dat check command for verifying collections

This commit is contained in:
Luke Street
2024-06-18 21:04:59 -06:00
parent 03b83484cb
commit 44580b0d71
16 changed files with 1368 additions and 128 deletions
Generated
+7 -6
View File
@@ -457,6 +457,7 @@ dependencies = [
"tracing-subscriber",
"xxhash-rust",
"zerocopy",
"zstd",
]
[[package]]
@@ -1006,27 +1007,27 @@ dependencies = [
[[package]]
name = "zstd"
version = "0.13.0"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.0.0"
version = "7.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a"
dependencies = [
"zstd-sys",
]
[[package]]
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"
checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
checksum = "75652c55c0b6f3e6f12eb786fe1bc960396bf05a1eb3bf1f3691c3610ac2e6d4"
dependencies = [
"cc",
"pkg-config",
+6 -6
View File
@@ -161,7 +161,7 @@ pub struct WIADisc {
///
/// RVZ only:
/// > 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,
/// The size of the chunks that data is divided into.
///
@@ -170,13 +170,13 @@ pub struct WIADisc {
///
/// RVZ only:
/// > 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,
/// 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.)
/// > 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.)
/// > - 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
/// current chunk, not the first hash of the full 2 MiB of data.
/// > 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.
pub chunk_size: U32,
/// The first 0x80 bytes of the disc image.
pub disc_head: [u8; DISC_HEAD_SIZE],
+5
View File
@@ -25,11 +25,14 @@ base16ct = "0.2.0"
crc32fast = "1.4.0"
digest = "0.10.7"
enable-ansi-support = "0.2.1"
hex = { version = "0.4.3", features = ["serde"] }
indicatif = "0.17.8"
itertools = "0.12.1"
log = "0.4.20"
md-5 = "0.10.6"
nod = { path = "../nod" }
quick-xml = { version = "0.31.0", features = ["serialize"] }
serde = { version = "1.0.197", features = ["derive"] }
sha1 = "0.10.6"
size = "0.4.1"
supports-color = "3.0.0"
@@ -38,9 +41,11 @@ tracing-attributes = "0.1.27"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
xxhash-rust = { version = "0.8.10", features = ["xxh64"] }
zerocopy = { version = "0.7.32", features = ["alloc", "derive"] }
zstd = "0.13.1"
[build-dependencies]
hex = { version = "0.4.3", features = ["serde"] }
quick-xml = { version = "0.31.0", features = ["serialize"] }
serde = { version = "1.0.197", features = ["derive"] }
zerocopy = { version = "0.7.32", features = ["alloc", "derive"] }
zstd = "0.13.1"
File diff suppressed because it is too large Load Diff
+155
View File
@@ -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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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 &amp; 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>
<header>
<name>Nintendo - GameCube</name>
<description>Nintendo - GameCube - Discs (1989) (2024-02-13 01-56-25)</description>
<version>2024-02-13 01-56-25</version>
<date>2024-02-13 01-56-25</date>
<description>Nintendo - GameCube - Discs (1992) (2024-06-02 00-38-06)</description>
<version>2024-06-02 00-38-06</version>
<date>2024-06-02 00-38-06</date>
<author>redump.org</author>
<homepage>redump.org</homepage>
<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"/>
</game>
<game name="Ribbit King Plus! (USA) (Bonus Disc)">
<category>Games</category>
<category>Bonus Discs</category>
<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"/>
</game>
@@ -9100,10 +9100,10 @@
<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"/>
</game>
<game name="Cube CD 01 (20) (Europe) (Unl)">
<game name="Cube CD 01 (20) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 01 (20) (Europe) (Unl)</description>
<rom name="Cube CD 01 (20) (Europe) (Unl).iso" size="1459978240" crc="3bda1560" md5="ba8dd80ae7c11b51c0a609d99c07a8b6" sha1="c7abf65ee74b15619afa8277f2ca59ed57d247df"/>
<description>Cube CD 01 (20) (UK) (Unl)</description>
<rom name="Cube CD 01 (20) (UK) (Unl).iso" size="1459978240" crc="3bda1560" md5="ba8dd80ae7c11b51c0a609d99c07a8b6" sha1="c7abf65ee74b15619afa8277f2ca59ed57d247df"/>
</game>
<game name="Space Raiders (Korea)">
<category>Games</category>
@@ -9120,50 +9120,50 @@
<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"/>
</game>
<game name="Cube CD 02 (21) (Europe) (Unl)">
<game name="Cube CD 02 (21) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 02 (21) (Europe) (Unl)</description>
<rom name="Cube CD 02 (21) (Europe) (Unl).iso" size="1459978240" crc="564bddf9" md5="e3e55b7ba681f9f0f9c107245df731d4" sha1="29f48aea1763f86760b2dafb9d528c435bfdfeed"/>
<description>Cube CD 02 (21) (UK) (Unl)</description>
<rom name="Cube CD 02 (21) (UK) (Unl).iso" size="1459978240" crc="564bddf9" md5="e3e55b7ba681f9f0f9c107245df731d4" sha1="29f48aea1763f86760b2dafb9d528c435bfdfeed"/>
</game>
<game name="Cube CD 03 (22) (Europe) (Unl)">
<game name="Cube CD 03 (22) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 03 (22) (Europe) (Unl)</description>
<rom name="Cube CD 03 (22) (Europe) (Unl).iso" size="1459978240" crc="4d3bc980" md5="63183383a906a65cda29c30d35c8026a" sha1="9e0d0fc0c61e284542bde3c6c5fa9b04105df612"/>
<description>Cube CD 03 (22) (UK) (Unl)</description>
<rom name="Cube CD 03 (22) (UK) (Unl).iso" size="1459978240" crc="4d3bc980" md5="63183383a906a65cda29c30d35c8026a" sha1="9e0d0fc0c61e284542bde3c6c5fa9b04105df612"/>
</game>
<game name="Cube CD 04 (23) (Europe) (Unl)">
<game name="Cube CD 04 (23) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 04 (23) (Europe) (Unl)</description>
<rom name="Cube CD 04 (23) (Europe) (Unl).iso" size="1459978240" crc="ceb11a37" md5="570491e09928e0214be8c2d074684a9d" sha1="b4f382b2d25ba4726af1a0754e600275445f6951"/>
<description>Cube CD 04 (23) (UK) (Unl)</description>
<rom name="Cube CD 04 (23) (UK) (Unl).iso" size="1459978240" crc="ceb11a37" md5="570491e09928e0214be8c2d074684a9d" sha1="b4f382b2d25ba4726af1a0754e600275445f6951"/>
</game>
<game name="Cube CD 05 (24) (Europe) (Unl)">
<game name="Cube CD 05 (24) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 05 (24) (Europe) (Unl)</description>
<rom name="Cube CD 05 (24) (Europe) (Unl).iso" size="1459978240" crc="2188e0bf" md5="a6aa526a5d2556905d7a61d4b7e6610b" sha1="a1f4a282ffd9dbfaa22b76065404b8737ea9139e"/>
<description>Cube CD 05 (24) (UK) (Unl)</description>
<rom name="Cube CD 05 (24) (UK) (Unl).iso" size="1459978240" crc="2188e0bf" md5="a6aa526a5d2556905d7a61d4b7e6610b" sha1="a1f4a282ffd9dbfaa22b76065404b8737ea9139e"/>
</game>
<game name="Cube CD 06 (25) (Europe) (Unl)">
<game name="Cube CD 06 (25) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 06 (25) (Europe) (Unl)</description>
<rom name="Cube CD 06 (25) (Europe) (Unl).iso" size="1459978240" crc="20843654" md5="2a91e8400172225f20c10fd2f6b2327d" sha1="28b59d6c1289655db9961bf10bacf81401ad6836"/>
<description>Cube CD 06 (25) (UK) (Unl)</description>
<rom name="Cube CD 06 (25) (UK) (Unl).iso" size="1459978240" crc="20843654" md5="2a91e8400172225f20c10fd2f6b2327d" sha1="28b59d6c1289655db9961bf10bacf81401ad6836"/>
</game>
<game name="Cube CD 07 (26) (Europe) (Unl)">
<game name="Cube CD 07 (26) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 07 (26) (Europe) (Unl)</description>
<rom name="Cube CD 07 (26) (Europe) (Unl).iso" size="1459978240" crc="094e050d" md5="9ba9a23a6478773a1b51cf2619bbc498" sha1="902c20039d49000b43e0ed6da972aa2846461bfb"/>
<description>Cube CD 07 (26) (UK) (Unl)</description>
<rom name="Cube CD 07 (26) (UK) (Unl).iso" size="1459978240" crc="094e050d" md5="9ba9a23a6478773a1b51cf2619bbc498" sha1="902c20039d49000b43e0ed6da972aa2846461bfb"/>
</game>
<game name="Cube CD 08 (27) (Europe) (Unl)">
<game name="Cube CD 08 (27) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 08 (27) (Europe) (Unl)</description>
<rom name="Cube CD 08 (27) (Europe) (Unl).iso" size="1459978240" crc="a7648498" md5="d11e4b0672880d9fdcae762eee4f919a" sha1="b06488214824a2e1eaf215eb792d2767f6472e3e"/>
<description>Cube CD 08 (27) (UK) (Unl)</description>
<rom name="Cube CD 08 (27) (UK) (Unl).iso" size="1459978240" crc="a7648498" md5="d11e4b0672880d9fdcae762eee4f919a" sha1="b06488214824a2e1eaf215eb792d2767f6472e3e"/>
</game>
<game name="Cube CD 09 (28) (Europe) (Unl)">
<game name="Cube CD 09 (28) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 09 (28) (Europe) (Unl)</description>
<rom name="Cube CD 09 (28) (Europe) (Unl).iso" size="1459978240" crc="77a5a747" md5="d659ae6d451d6253ef1bd3cf6bcf8fe2" sha1="561511a150af7239e8b740d398315c626ecb8eb6"/>
<description>Cube CD 09 (28) (UK) (Unl)</description>
<rom name="Cube CD 09 (28) (UK) (Unl).iso" size="1459978240" crc="77a5a747" md5="d659ae6d451d6253ef1bd3cf6bcf8fe2" sha1="561511a150af7239e8b740d398315c626ecb8eb6"/>
</game>
<game name="Cube CD 10 (29) (Europe) (Unl)">
<game name="Cube CD 10 (29) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 10 (29) (Europe) (Unl)</description>
<rom name="Cube CD 10 (29) (Europe) (Unl).iso" size="1459978240" crc="d58bb1d1" md5="7aa303a1ee2cca606eb7293d1e5d40e1" sha1="3643191bacbb49b3a1c10a302f36dd2ecd76ac70"/>
<description>Cube CD 10 (29) (UK) (Unl)</description>
<rom name="Cube CD 10 (29) (UK) (Unl).iso" size="1459978240" crc="d58bb1d1" md5="7aa303a1ee2cca606eb7293d1e5d40e1" sha1="3643191bacbb49b3a1c10a302f36dd2ecd76ac70"/>
</game>
<game name="Action Replay for GameCube (Europe) (Unl) (v1.0E)">
<category>Applications</category>
@@ -9175,25 +9175,25 @@
<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"/>
</game>
<game name="Cube CD 11 (30) (Europe) (Unl)">
<game name="Cube CD 11 (30) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 11 (30) (Europe) (Unl)</description>
<rom name="Cube CD 11 (30) (Europe) (Unl).iso" size="1459978240" crc="de08bb29" md5="00a76920368c9719c6767b5d739eb5a9" sha1="9bcb7602cee82c533d950b9a424a5c793760a9ed"/>
<description>Cube CD 11 (30) (UK) (Unl)</description>
<rom name="Cube CD 11 (30) (UK) (Unl).iso" size="1459978240" crc="de08bb29" md5="00a76920368c9719c6767b5d739eb5a9" sha1="9bcb7602cee82c533d950b9a424a5c793760a9ed"/>
</game>
<game name="Cube CD 12 (31) (Europe) (Unl)">
<game name="Cube CD 12 (31) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 12 (31) (Europe) (Unl)</description>
<rom name="Cube CD 12 (31) (Europe) (Unl).iso" size="1459978240" crc="67acea2c" md5="5d92c8e5057945c0944a0a4cbc5aa068" sha1="810c918a0469d1cd054cf37d2829ecfb25091c08"/>
<description>Cube CD 12 (31) (UK) (Unl)</description>
<rom name="Cube CD 12 (31) (UK) (Unl).iso" size="1459978240" crc="67acea2c" md5="5d92c8e5057945c0944a0a4cbc5aa068" sha1="810c918a0469d1cd054cf37d2829ecfb25091c08"/>
</game>
<game name="Cube CD 13 (32) (Europe) (Unl)">
<game name="Cube CD 13 (32) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 13 (32) (Europe) (Unl)</description>
<rom name="Cube CD 13 (32) (Europe) (Unl).iso" size="1459978240" crc="4ee5dc34" md5="879a354177cbe51f602269480c423ecd" sha1="1961a864c80d92de323b710ca2125bf45806473f"/>
<description>Cube CD 13 (32) (UK) (Unl)</description>
<rom name="Cube CD 13 (32) (UK) (Unl).iso" size="1459978240" crc="4ee5dc34" md5="879a354177cbe51f602269480c423ecd" sha1="1961a864c80d92de323b710ca2125bf45806473f"/>
</game>
<game name="Cube CD 15 (34) (Europe) (Unl)">
<game name="Cube CD 15 (34) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 15 (34) (Europe) (Unl)</description>
<rom name="Cube CD 15 (34) (Europe) (Unl).iso" size="1459978240" crc="4b9b91e6" md5="08522ad068345eca61ea22dc92f6cb45" sha1="2f362a1547d958e3d772fe9d8c400bc57e5d17f4"/>
<description>Cube CD 15 (34) (UK) (Unl)</description>
<rom name="Cube CD 15 (34) (UK) (Unl).iso" size="1459978240" crc="4b9b91e6" md5="08522ad068345eca61ea22dc92f6cb45" sha1="2f362a1547d958e3d772fe9d8c400bc57e5d17f4"/>
</game>
<game name="FreeLoader for GameCube (USA, Europe) (Unl) (v1.06b)">
<category>Applications</category>
@@ -9225,30 +9225,30 @@
<description>2002 FIFA World Cup (France)</description>
<rom name="2002 FIFA World Cup (France).iso" size="1459978240" crc="f3de87a7" md5="d223250f71b82efe411d4710bd2c9d22" sha1="a88bd9f7d619df59558d2043b57730d3e23935b4"/>
</game>
<game name="Cube CD 16 (35) (Europe) (Unl)">
<game name="Cube CD 16 (35) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 16 (35) (Europe) (Unl)</description>
<rom name="Cube CD 16 (35) (Europe) (Unl).iso" size="1459978240" crc="e5c0156e" md5="ed3ba85d06eba0f60f84891e1f849d44" sha1="20e01588318a0aa88277f941b4e625bea34cf1ca"/>
<description>Cube CD 16 (35) (UK) (Unl)</description>
<rom name="Cube CD 16 (35) (UK) (Unl).iso" size="1459978240" crc="e5c0156e" md5="ed3ba85d06eba0f60f84891e1f849d44" sha1="20e01588318a0aa88277f941b4e625bea34cf1ca"/>
</game>
<game name="Cube CD 17 (36) (Europe) (Unl)">
<game name="Cube CD 17 (36) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 17 (36) (Europe) (Unl)</description>
<rom name="Cube CD 17 (36) (Europe) (Unl).iso" size="1459978240" crc="9e7dc646" md5="5d381c783a736b73bbcb5133b39c181e" sha1="8cf84262a897d440fe7a18e2b85bada188534cad"/>
<description>Cube CD 17 (36) (UK) (Unl)</description>
<rom name="Cube CD 17 (36) (UK) (Unl).iso" size="1459978240" crc="9e7dc646" md5="5d381c783a736b73bbcb5133b39c181e" sha1="8cf84262a897d440fe7a18e2b85bada188534cad"/>
</game>
<game name="Cube CD 18 (37) (Europe) (Unl)">
<game name="Cube CD 18 (37) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 18 (37) (Europe) (Unl)</description>
<rom name="Cube CD 18 (37) (Europe) (Unl).iso" size="1459978240" crc="1be165b7" md5="123af675aac82a2f6c4a51c297353336" sha1="ec1c5307e8a5c06c3181ca4125ba7e2b5abe8a2c"/>
<description>Cube CD 18 (37) (UK) (Unl)</description>
<rom name="Cube CD 18 (37) (UK) (Unl).iso" size="1459978240" crc="1be165b7" md5="123af675aac82a2f6c4a51c297353336" sha1="ec1c5307e8a5c06c3181ca4125ba7e2b5abe8a2c"/>
</game>
<game name="Cube CD 19 (38) (Europe) (Unl)">
<game name="Cube CD 19 (38) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 19 (38) (Europe) (Unl)</description>
<rom name="Cube CD 19 (38) (Europe) (Unl).iso" size="1459978240" crc="1570e92e" md5="fd0dee6c5b4850e9ceab350721528314" sha1="b347fece4943897882e2a38b14c5691c36f2b023"/>
<description>Cube CD 19 (38) (UK) (Unl)</description>
<rom name="Cube CD 19 (38) (UK) (Unl).iso" size="1459978240" crc="1570e92e" md5="fd0dee6c5b4850e9ceab350721528314" sha1="b347fece4943897882e2a38b14c5691c36f2b023"/>
</game>
<game name="Cube CD 20 (40) (Europe) (Unl)">
<game name="Cube CD 20 (40) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 20 (40) (Europe) (Unl)</description>
<rom name="Cube CD 20 (40) (Europe) (Unl).iso" size="1459978240" crc="eb7f7bc6" md5="1a4ba7a7d5bd2a195c0c4a4426940239" sha1="571dc6e8aa538e2501f89a5706b23b8f9e170e8f"/>
<description>Cube CD 20 (40) (UK) (Unl)</description>
<rom name="Cube CD 20 (40) (UK) (Unl).iso" size="1459978240" crc="eb7f7bc6" md5="1a4ba7a7d5bd2a195c0c4a4426940239" sha1="571dc6e8aa538e2501f89a5706b23b8f9e170e8f"/>
</game>
<game name="SRS - Street Racing Syndicate (Europe) (En,Fr,De,Es,It)">
<category>Games</category>
@@ -9475,10 +9475,10 @@
<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"/>
</game>
<game name="Cube CD 14 (33) (Europe) (Unl)">
<game name="Cube CD 14 (33) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 14 (33) (Europe) (Unl)</description>
<rom name="Cube CD 14 (33) (Europe) (Unl).iso" size="1459978240" crc="b21fe659" md5="82109cff554d0ecadb0fffb7030dc5a8" sha1="884052c0eb3f0d515ca0c7b173e0a5dfd8071a35"/>
<description>Cube CD 14 (33) (UK) (Unl)</description>
<rom name="Cube CD 14 (33) (UK) (Unl).iso" size="1459978240" crc="b21fe659" md5="82109cff554d0ecadb0fffb7030dc5a8" sha1="884052c0eb3f0d515ca0c7b173e0a5dfd8071a35"/>
</game>
<game name="Action Replay Max (Europe) (En,Fr,De,Es,It,Pt) (Unl)">
<category>Applications</category>
@@ -9570,10 +9570,10 @@
<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"/>
</game>
<game name="Cube CD 20 (39) (Europe) (Unl)">
<game name="Cube CD 20 (39) (UK) (Unl)">
<category>Coverdiscs</category>
<description>Cube CD 20 (39) (Europe) (Unl)</description>
<rom name="Cube CD 20 (39) (Europe) (Unl).iso" size="1459978240" crc="06b90505" md5="574f91a0dad19815a494a79ba76a6c5d" sha1="bd4a3c28f4e2bcffd7305932a1b6548af455d794"/>
<description>Cube CD 20 (39) (UK) (Unl)</description>
<rom name="Cube CD 20 (39) (UK) (Unl).iso" size="1459978240" crc="06b90505" md5="574f91a0dad19815a494a79ba76a6c5d" sha1="bd4a3c28f4e2bcffd7305932a1b6548af455d794"/>
</game>
<game name="Ultimate Codes for Use with Tom Clancy's Splinter Cell (USA) (Unl)">
<category>Applications</category>
@@ -9955,4 +9955,19 @@
<description>WWE WrestleMania X8 (Japan) (Taikenban)</description>
<rom name="WWE WrestleMania X8 (Japan) (Taikenban).iso" size="1459978240" crc="f676c652" md5="c001005e01e02fb02c40c562c7dc4d78" sha1="ace6cf324e04d35d008b12aa681c857d72353d25"/>
</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>
+43 -15
View File
@@ -40,48 +40,71 @@ fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
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
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);
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().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 {
string_table_offset: 0,
crc32: u32::from_be_bytes(game.rom.crc32),
md5: game.rom.md5,
sha1: game.rom.sha1,
sectors: game.rom.size.div_ceil(0x8000) as u32,
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 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
let header =
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;
for (entry, name) in &mut entries {
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;
}
// Write string table
for (_, name) in &entries {
f.write_all(&(name.len() as u32).to_le_bytes()).unwrap();
f.write_all(name.as_bytes()).unwrap();
out.write_all(&(name.len() as u32).to_le_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)]
@@ -94,11 +117,16 @@ struct DatFile {
struct DatGame {
#[serde(rename = "@name")]
name: String,
rom: DatGameRom,
// #[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")]
+10 -3
View File
@@ -2,12 +2,12 @@ use std::path::PathBuf;
use argp::FromArgs;
use crate::util::shared::convert_and_verify;
use crate::util::{redump, shared::convert_and_verify};
#[derive(FromArgs, Debug)]
/// Converts a disc image to ISO.
#[argp(subcommand, name = "convert")]
pub struct ConvertArgs {
pub struct Args {
#[argp(positional)]
/// path to disc image
file: PathBuf,
@@ -17,8 +17,15 @@ pub struct ConvertArgs {
#[argp(switch)]
/// enable MD5 hashing (slower)
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)
}
+231
View File
@@ -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() })
}
+3 -3
View File
@@ -19,9 +19,9 @@ use zerocopy::AsBytes;
use crate::util::{display, has_extension};
#[derive(FromArgs, Debug)]
/// Extract a disc image.
/// Extracts a disc image.
#[argp(subcommand, name = "extract")]
pub struct ExtractArgs {
pub struct Args {
#[argp(positional)]
/// Path to disc image
file: PathBuf,
@@ -40,7 +40,7 @@ pub struct ExtractArgs {
partition: Option<String>,
}
pub fn extract(args: ExtractArgs) -> nod::Result<()> {
pub fn run(args: Args) -> nod::Result<()> {
let output_dir: PathBuf;
if let Some(dir) = args.out {
output_dir = dir;
+2 -2
View File
@@ -9,13 +9,13 @@ use crate::util::{display, shared::print_header};
#[derive(FromArgs, Debug)]
/// Displays information about disc images.
#[argp(subcommand, name = "info")]
pub struct InfoArgs {
pub struct Args {
#[argp(positional)]
/// Path to disc image(s)
file: Vec<PathBuf>,
}
pub fn info(args: InfoArgs) -> nod::Result<()> {
pub fn run(args: Args) -> nod::Result<()> {
for file in &args.file {
info_file(file)?;
}
+1
View File
@@ -1,4 +1,5 @@
pub mod convert;
pub mod dat;
pub mod extract;
pub mod info;
pub mod verify;
+10 -3
View File
@@ -2,21 +2,28 @@ use std::path::PathBuf;
use argp::FromArgs;
use crate::util::shared::convert_and_verify;
use crate::util::{redump, shared::convert_and_verify};
#[derive(FromArgs, Debug)]
/// Verifies disc images.
#[argp(subcommand, name = "verify")]
pub struct VerifyArgs {
pub struct Args {
#[argp(positional)]
/// path to disc image(s)
file: Vec<PathBuf>,
#[argp(switch)]
/// enable MD5 hashing (slower)
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 {
convert_and_verify(file, None, args.md5)?;
println!();
+10 -8
View File
@@ -6,17 +6,19 @@ pub(crate) mod util;
#[derive(FromArgs, Debug)]
#[argp(subcommand)]
pub enum SubCommand {
Info(cmd::info::InfoArgs),
Extract(cmd::extract::ExtractArgs),
Convert(cmd::convert::ConvertArgs),
Verify(cmd::verify::VerifyArgs),
Dat(cmd::dat::Args),
Info(cmd::info::Args),
Extract(cmd::extract::Args),
Convert(cmd::convert::Args),
Verify(cmd::verify::Args),
}
pub fn run(command: SubCommand) -> nod::Result<()> {
match command {
SubCommand::Info(c_args) => cmd::info::info(c_args),
SubCommand::Convert(c_args) => cmd::convert::convert(c_args),
SubCommand::Extract(c_args) => cmd::extract::extract(c_args),
SubCommand::Verify(c_args) => cmd::verify::verify(c_args),
SubCommand::Dat(c_args) => cmd::dat::run(c_args),
SubCommand::Info(c_args) => cmd::info::run(c_args),
SubCommand::Convert(c_args) => cmd::convert::run(c_args),
SubCommand::Extract(c_args) => cmd::extract::run(c_args),
SubCommand::Verify(c_args) => cmd::verify::run(c_args),
}
}
+158 -15
View File
@@ -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 zerocopy::{FromBytes, FromZeroes};
use hex::deserialize as deserialize_hex;
use nod::{array_ref, Result};
use serde::Deserialize;
use zerocopy::{AsBytes, FromBytes, FromZeroes};
#[derive(Clone, Debug)]
pub struct GameResult {
pub name: &'static str,
pub struct GameResult<'a> {
pub name: &'a str,
pub crc32: u32,
pub md5: [u8; 16],
pub sha1: [u8; 20],
}
pub fn find_by_crc32(crc32: u32) -> Option<GameResult> {
let header: &Header = Header::ref_from_prefix(&DATA.0).unwrap();
pub struct EntryIter<'a> {
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>());
let entries_size = header.entry_count as usize * size_of::<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();
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
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 })
}
#[repr(C, align(4))]
struct Aligned<T: ?Sized>(T);
const BUILTIN: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/parsed-dats.bin"));
static LOADED: OnceLock<Box<[u8]>> = OnceLock::new();
const DATA: &Aligned<[u8]> =
&Aligned(*include_bytes!(concat!(env!("OUT_DIR"), "/parsed-dats.bin")));
fn loaded_data() -> &'static [u8] {
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
#[derive(Clone, Debug, FromBytes, FromZeroes)]
#[derive(Clone, Debug, AsBytes, FromBytes, FromZeroes)]
#[repr(C, align(4))]
struct Header {
entry_count: u32,
@@ -47,7 +160,7 @@ struct Header {
}
// Keep in sync with build.rs
#[derive(Clone, Debug, FromBytes, FromZeroes)]
#[derive(Clone, Debug, AsBytes, FromBytes, FromZeroes)]
#[repr(C, align(4))]
struct GameEntry {
crc32: u32,
@@ -56,3 +169,33 @@ struct GameEntry {
md5: [u8; 16],
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],
}