Skip to content

Commit 82dab10

Browse files
Update to v0.7.
1 parent 74710f1 commit 82dab10

File tree

4 files changed

+88
-27
lines changed

4 files changed

+88
-27
lines changed

README.md

+40-8
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,21 @@ Usage:
66
--------------
77

88
```
9-
Usage: %s <keys file> <device.cert> <input WAD> <output dir> [parent title ID]
9+
wad2bin v0.7 (c) DarkMatterCore.
10+
Built: 16:57:46 Jul 1 2020.
1011
11-
Paths must not exceed 1023 characters. Relative paths are supported.
12+
Usage: wad2bin <keys.txt> <device.cert> <input WAD> <output dir> [<parent title ID> [--nullkey]]
13+
14+
Paths must not exceed 259 characters. Relative paths are supported.
1215
The required directory tree for the *.bin file(s) will be created at the output directory.
1316
You can set your SD card root directory as the output directory.
14-
Parent title ID is only required if the input WAD is a DLC. A 16 character long hex string is expected.
17+
18+
Notes about DLC support:
19+
* Parent title ID is only required if the input WAD is a DLC. A 16 character long hex string is expected.
20+
* If "--nullkey" is set after the parent title ID, a null key will be used to encrypt DLC content data.
21+
Some older games (like Rock Band 2) depend on this to properly load DLC data when launched via the Disc Channel.
22+
23+
For more information, please visit: https://github.com/DarkMatterCore/wad2bin.
1524
```
1625

1726
Building instructions:
@@ -43,12 +52,20 @@ Guidelines:
4352
* Both ticket and TMD for each converted WAD package must be installed on the target Wii console in order for this to work.
4453
* For this matter, the program generates a bogus WAD package at the provided output directory, using the `<title_id>_bogus.wad` naming convention. It can be used with regular WAD Managers to install both ticket and TMD if needed.
4554
* Bogus WAD packages don't have any encrypted content data, thus they're expected to return errors like `-1022` during installation with regular WAD Managers - this is expected behaviour, so don't panic.
46-
* If you can't get your converted WAD package to work, try "uninstalling" the bogus WAD before installing it. It fixes the problem most of the time.
47-
* If the WAD ticket wasn't issued for the target console, or if the WAD isn't legit (e.g. homebrew WAD), the IOS used by the System Menu must be patched to enable the [signing bug](https://wiibrew.org/wiki/Signing_bug) on it.
48-
* Regular Wii consoles: use [Simple IOS Patcher](https://gbatemp.net/download/simple-ios-patcher.25749) to install a patched System Menu IOS (IOS60 for 4.0 and 4.1, IOS70 for 4.2 and IOS80 for 4.3).
49-
* Wii U consoles (vWii): use [Patched IOS80 Installer for vWii](https://gbatemp.net/threads/patched-ios80-installer-for-vwii-allows-sd-menu-custom-channels.344882) to install a patched IOS80.
55+
* If you can't get your converted WAD package to work, try uninstalling the bogus WAD before installing it (for real). This fixes the problem most of the time.
5056
* Channel WADs get converted to `content.bin` files, while DLC WADs get converted to `<index>.bin` files.
5157
* If a DLC WAD is provided, it doesn't matter if it's an uncomplete WAD with missing contents, a WAD with a tampered TMD that only references the packaged contents or a full WAD with all contents: all cases are supported by wad2bin. There's no need to provide any content indexes.
58+
* DLCs can use a parent title ID that's different from the title ID from the game they belong if other games are capable of using them. That's why a parent title ID is required to convert DLCs.
59+
* Converted DLC data can be encrypted using either a null key (used by older games) or the console-specific PRNG key (used by newer games, and also old games when launched with a cIOS).
60+
* If the WAD ticket wasn't issued for the target console, or if the WAD isn't legit (e.g. homebrew WAD), a patched IOS must be installed and used. This varies depending on the converted WAD type:
61+
* **Channels:** the IOS used by the System Menu must be patched to enable the [signing bug](https://wiibrew.org/wiki/Signing_bug) on it:
62+
* **Regular Wii consoles:** use [Simple IOS Patcher](https://gbatemp.net/download/simple-ios-patcher.25749) to install a patched System Menu IOS (IOS60 for 4.0 and 4.1, IOS70 for 4.2 and IOS80 for 4.3).
63+
* **Wii U consoles (vWii):** use [Patched IOS80 Installer for vWii](https://gbatemp.net/threads/patched-ios80-installer-for-vwii-allows-sd-menu-custom-channels.344882) to install a patched IOS80.
64+
* **DLCs:** the game must be launched using a cIOS, or its required IOS version must be patched to enable the [signing bug](https://wiibrew.org/wiki/Signing_bug) on it. This greatly depends on:
65+
* **How old the game is:** if it enforces the usage of a null key when launched through the Disc Channel.
66+
* **The used launch method:** cIOS enforce the usage of the PRNG key, even on older games.
67+
* **Ticket/TMD signature validity:** if it's not valid, or if the ticket wasn't issued for the target console, a patched IOS or a cIOS will always be necessary.
68+
* Because of all these reasons, it's difficult to establish a clear procedure that works for every single case. Further trial and error by the user is encouraged.
5269

5370
Supported DLCs:
5471
--------------
@@ -65,7 +82,7 @@ The title ID from the parent game must be provided as an additional command line
6582
* `00010005-735A45xx` (`sZEx`).
6683
* `00010005-735A46xx` (`sZFx`).
6784

68-
* The Beatles Rock Band (`00010000-52394Axx`) (`R9Jx`):
85+
* The Beatles: Rock Band (`00010000-52394Axx`) (`R9Jx`):
6986
* `00010005-72394Axx` (`r9Jx`).
7087

7188
* Rock Band 3 (`00010000-535A42xx`) (`SZBx`):
@@ -133,6 +150,21 @@ wad2bin is licensed under GPLv3 or (at your option) any later version.
133150
Changelog:
134151
--------------
135152

153+
**v0.7:**
154+
155+
* Removed parent title ID generation for DLC WADs. This doesn't work properly with games that are capable of using DLCs from other games.
156+
* The hardcoded DLC title ID list is still being used as a filter to know if any converted DLCs will work or not.
157+
* Added support for encrypting converted DLC data with a null key. Fixes issues with older games launched through the Disc Channel, such as `Rock Band 2`.
158+
* Please read the guidelines from the readme! Even if a null key is used, a patched IOS is still needed if the DLC ticket wasn't issued for the target console and you intend to launch the game through the Disc Channel.
159+
* Added `The Beatles: Rock Band` DLC to the hardcoded DLC title ID list.
160+
* Written content padding is now encrypted as well.
161+
* Several fixes to the U8 archive parsing code.
162+
* Fixed a silly `ECSDA` -> `ECDSA` typo.
163+
* Reworked certificate chain, ticket and TMD handling.
164+
* Implemented RSA signature verification in certificates, tickets and TMDs.
165+
* Fixes a bug where the ticket would have been fakesigned even if it was perfectly valid.
166+
* Useful info is now displayed at the end of the conversion process. Please read it.
167+
136168
**v0.6:**
137169

138170
* Added a hardcoded list with title IDs from DLCs that can be converted to the `<index>.bin` format. Any other DLCs will return an error. Thanks to this, it's no longer necessary to input a parent title ID.

source/bin.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ bool binGenerateContentBinFromUnpackedInstallableWadPackage(os_char_t *unpacked_
507507
return success;
508508
}
509509

510-
bool binGenerateIndexedPackagesFromUnpackedInstallableWadPackage(os_char_t *unpacked_wad_path, os_char_t *out_path, TitleMetadata *tmd, u64 parent_tid)
510+
bool binGenerateIndexedPackagesFromUnpackedInstallableWadPackage(os_char_t *unpacked_wad_path, os_char_t *out_path, TitleMetadata *tmd, u64 parent_tid, bool use_null_key)
511511
{
512512
size_t unpacked_wad_path_len = 0;
513513
size_t out_path_len = 0, new_out_path_len = 0;
@@ -639,7 +639,7 @@ bool binGenerateIndexedPackagesFromUnpackedInstallableWadPackage(os_char_t *unpa
639639
}
640640

641641
/* Write encrypted content file. */
642-
write_res = wadWriteUnpackedContentToPackage(indexed_bin, prng_key, cnt_iv, NULL, cnt_fd, cnt_idx, cnt_size, &aligned_cnt_size);
642+
write_res = wadWriteUnpackedContentToPackage(indexed_bin, (use_null_key ? null_key : prng_key), cnt_iv, NULL, cnt_fd, cnt_idx, cnt_size, &aligned_cnt_size);
643643
if (!write_res) ERROR_MSG("Failed to write content file \"" OS_PRINT_STR "\" to \"" OS_PRINT_STR "\"!", unpacked_wad_path, out_path);
644644

645645
/* Close files. */

source/bin.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,6 @@ bool binIsDlcTitleConvertible(u64 tid);
8989
bool binGenerateContentBinFromUnpackedInstallableWadPackage(os_char_t *unpacked_wad_path, os_char_t *out_path, TitleMetadata *tmd);
9090

9191
/// Generates <index>.bin file(s) using an unpacked WAD data directory, TMD data loaded into memory and a parent title ID.
92-
bool binGenerateIndexedPackagesFromUnpackedInstallableWadPackage(os_char_t *unpacked_wad_path, os_char_t *out_path, TitleMetadata *tmd, u64 parent_tid);
92+
bool binGenerateIndexedPackagesFromUnpackedInstallableWadPackage(os_char_t *unpacked_wad_path, os_char_t *out_path, TitleMetadata *tmd, u64 parent_tid, bool use_null_key);
9393

9494
#endif /* __BIN_H__ */

source/main.c

+45-16
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,15 @@
2323
#include "keys.h"
2424
#include "bin.h"
2525

26-
#define ARG_COUNT 4
26+
#define PATH_COUNT 4
27+
#define NULL_KEY_ARG "--nullkey"
2728

2829
int main(int argc, char **argv)
2930
{
3031
int ret = 0;
3132

3233
/* Reserve memory for an extra temporary path. */
33-
os_char_t *paths[ARG_COUNT + 1] = {0};
34+
os_char_t *paths[PATH_COUNT + 1] = {0};
3435

3536
CertificateChain *cert_chain = NULL;
3637

@@ -41,18 +42,23 @@ int main(int argc, char **argv)
4142

4243
u64 title_id = 0, parent_tid = 0;
4344
u32 required_ios = 0, tid_upper = 0;
45+
bool use_null_key = false;
4446

4547
printf("\nwad2bin v%s (c) DarkMatterCore.\n", VERSION);
4648
printf("Built: %s %s.\n\n", __TIME__, __DATE__);
4749

48-
if (argc < (ARG_COUNT + 1) || argc > (ARG_COUNT + 2) || strlen(argv[1]) >= MAX_PATH || strlen(argv[2]) >= MAX_PATH || strlen(argv[3]) >= MAX_PATH || \
49-
(strlen(argv[4]) + SD_CONTENT_PATH_MAX_LENGTH) >= MAX_PATH || (argc == (ARG_COUNT + 2) && strlen(argv[5]) != 16))
50+
if (argc < (PATH_COUNT + 1) || argc > (PATH_COUNT + 3) || strlen(argv[1]) >= MAX_PATH || strlen(argv[2]) >= MAX_PATH || strlen(argv[3]) >= MAX_PATH || \
51+
(strlen(argv[4]) + SD_CONTENT_PATH_MAX_LENGTH) >= MAX_PATH || (argc >= (PATH_COUNT + 2) && strlen(argv[5]) != 16) || (argc == (PATH_COUNT + 3) && (strlen(argv[6]) != strlen(NULL_KEY_ARG) || \
52+
strcmp(argv[6], NULL_KEY_ARG) != 0)))
5053
{
51-
printf("Usage: %s <keys file> <device.cert> <input WAD> <output dir> [parent title ID]\n\n", argv[0]);
54+
printf("Usage: %s <keys.txt> <device.cert> <input WAD> <output dir> [<parent title ID> [" NULL_KEY_ARG "]]\n\n", argv[0]);
5255
printf("Paths must not exceed %u characters. Relative paths are supported.\n", MAX_PATH - 1);
5356
printf("The required directory tree for the *.bin file(s) will be created at the output directory.\n");
54-
printf("You can set your SD card root directory as the output directory.\n");
55-
printf("Parent title ID is only required if the input WAD is a DLC. A 16 character long hex string is expected.\n\n");
57+
printf("You can set your SD card root directory as the output directory.\n\n");
58+
printf("Notes about DLC support:\n");
59+
printf("* Parent title ID is only required if the input WAD is a DLC. A 16 character long hex string is expected.\n");
60+
printf("* If \"" NULL_KEY_ARG "\" is set after the parent title ID, a null key will be used to encrypt DLC content data.\n");
61+
printf(" Some older games (like Rock Band 2) depend on this to properly load DLC data when launched via the Disc Channel.\n\n");
5662
printf("For more information, please visit: https://github.com/DarkMatterCore/wad2bin.\n\n");
5763
ret = -1;
5864
goto out;
@@ -70,7 +76,7 @@ int main(int argc, char **argv)
7076
}
7177

7278
/* Generate path buffers. */
73-
for(u32 i = 0; i <= ARG_COUNT; i++)
79+
for(u32 i = 0; i <= PATH_COUNT; i++)
7480
{
7581
/* Allocate memory for the current path. */
7682
paths[i] = (os_char_t*)calloc(MAX_PATH, sizeof(os_char_t));
@@ -81,7 +87,7 @@ int main(int argc, char **argv)
8187
goto out;
8288
}
8389

84-
if (i == ARG_COUNT)
90+
if (i == PATH_COUNT)
8591
{
8692
/* Save temporary path and create it. */
8793
os_snprintf(paths[i], MAX_PATH, "." OS_PATH_SEPARATOR "wad2bin_wad_data");
@@ -104,12 +110,12 @@ int main(int argc, char **argv)
104110
/* Check if the output directory string ends with a path separator. */
105111
/* If so, remove it. */
106112
u64 path_len = strlen(argv[i + 1]);
107-
if (i == (ARG_COUNT - 1) && argv[i + 1][path_len - 1] == *((u8*)OS_PATH_SEPARATOR)) paths[i][path_len - 1] = (os_char_t)0;
113+
if (i == (PATH_COUNT - 1) && argv[i + 1][path_len - 1] == *((u8*)OS_PATH_SEPARATOR)) paths[i][path_len - 1] = (os_char_t)0;
108114
}
109115
}
110116

111117
/* Check if the user provided a parent title ID. */
112-
if (argc == (ARG_COUNT + 2))
118+
if (argc >= (PATH_COUNT + 2))
113119
{
114120
/* Parse parent title ID. */
115121
if (!keysParseHexKey((u8*)&parent_tid, NULL, argv[5], 8, false))
@@ -130,6 +136,9 @@ int main(int argc, char **argv)
130136
ret = -6;
131137
goto out;
132138
}
139+
140+
/* Enable null key usage if needed. */
141+
use_null_key = (argc == (PATH_COUNT + 3));
133142
}
134143

135144
/* Load keydata and device certificate. */
@@ -160,7 +169,7 @@ int main(int argc, char **argv)
160169
if (tid_upper == TITLE_TYPE_DLC)
161170
{
162171
/* Check if a parent title ID was provided. */
163-
if (argc != (ARG_COUNT + 2))
172+
if (argc < (PATH_COUNT + 2))
164173
{
165174
ERROR_MSG("Error: parent title ID not provided! This is required for DLC titles.\n");
166175
ret = -9;
@@ -176,7 +185,7 @@ int main(int argc, char **argv)
176185
}
177186

178187
/* Generate <index>.bin file(s). */
179-
if (!binGenerateIndexedPackagesFromUnpackedInstallableWadPackage(paths[4], paths[3], tmd, parent_tid))
188+
if (!binGenerateIndexedPackagesFromUnpackedInstallableWadPackage(paths[4], paths[3], tmd, parent_tid, use_null_key))
180189
{
181190
ret = -11;
182191
goto out;
@@ -206,13 +215,33 @@ int main(int argc, char **argv)
206215

207216
if (tid_upper == TITLE_TYPE_DLC)
208217
{
209-
printf("In order to use the converted DLC package, you'll either need to launch the game using a cIOS (NeoGamma, USB Loader),\n");
210-
printf("or install a patched IOS%u (if you wish to use the disc channel).\n\n", required_ios);
218+
if (use_null_key)
219+
{
220+
printf("In order to use the converted DLC, you'll need to install a patched IOS%u and launch the game via the Disc Channel.\n", required_ios);
221+
printf("The converted DLC won't work if you launch the game using a cIOS (e.g. NeoGamma, USB Loader).\n");
222+
} else {
223+
printf("In order to use the converted DLC, you'll need to launch the game using a cIOS (NeoGamma, USB Loader),\n");
224+
printf("or install a patched IOS%u (if you wish to use the Disc Channel).\n", required_ios);
225+
}
211226
} else {
212227
printf("You'll need to install a patched System Menu IOS in order to run this channel from the SD card menu.\n\n");
213228
}
229+
} else {
230+
printf("Both ticket/TMD signatures are valid.\n");
231+
232+
if (tid_upper == TITLE_TYPE_DLC)
233+
{
234+
printf("This DLC should work right away on your console without having to launch the game using a cIOS, nor having to\n");
235+
printf("install a patched IOS%u.\n", required_ios);
236+
} else {
237+
printf("This channel should work right away on your console without having to install a patched System Menu IOS.\n\n");
238+
}
214239
}
215240

241+
if (tid_upper == TITLE_TYPE_DLC) printf("If it doesn't work anyway, try converting the DLC %s \"" NULL_KEY_ARG "\".\n\n", (use_null_key ? "without" : "with"));
242+
243+
printf("Remember to install the generated bogus WAD file! If it doesn't work, try uninstalling it first (for real).\n\n");
244+
216245
out:
217246
if (ret < 0 && ret != -1) printf("Process failed!\n\n");
218247

@@ -237,7 +266,7 @@ int main(int argc, char **argv)
237266
/* Remove unpacked WAD directory. */
238267
if (paths[4]) utilsRemoveDirectoryRecursively(paths[4]);
239268

240-
for(u32 i = 0; i <= ARG_COUNT; i++)
269+
for(u32 i = 0; i <= PATH_COUNT; i++)
241270
{
242271
if (paths[i]) free(paths[i]);
243272
}

0 commit comments

Comments
 (0)