[nusresign, wadresign] Use TCHAR printf() functions where possible.

This lets us consolidate sets of fputs() and printf()-style functions
into a single printf(), which reduces code size. Note that it will
definitely increase the size on Windows due to more UTF-16 strings.

- Converted some more printf()-style functions to fputs()-style.
  gcc does this automatically if possible, but MSVC does not.

- Updated copyright years.

[nusresign] main.c: Remove a few extra leading spaces in print_help().

[nusresign] resign-nus.cpp:
- Removed a line of debugging code.
- Ticket type change from Disc to Installable should be on stdout,
  not stderr.

TODO: There's a few more functions that need TCHAR conversions, but they
require changing more code elsewhere.

Code size differences: (64-bit Gentoo Linux, gcc-12.1.0, release build, no LTO)
[NOTE: Windows builds will increase due to more TCHAR usage.]

   text    data     bss     dec     hex filename
   3151     160       0    3311     cef main.c.o [wadresign, before]
   3132     160       0    3292     cdc main.c.o [wadresign, after]
    -19       0       0     -19     -13 Difference

   text    data     bss     dec     hex filename
   6581       0       0    6581    19b5 print-info.c.o [wadresign, before]
   6146       0       0    6146    1802 print-info.c.o [wadresign, after]
   -435       0       0    -435    -1b3 Difference

   text    data     bss     dec     hex filename
  14164       8       0   14172    375c resign-wad.cpp.o [wadresign, before]
  11888       8       0   11896    2e78 resign-wad.cpp.o [wadresign, after]
  -2276       0       0   -2276    -8e4 Difference

   text    data     bss     dec     hex filename
   2561      96       0    2657     a61 main.c.o [nusresign, before]
   2526      96       0    2622     a3e main.c.o [nusresign, after]
    -35       0       0     -35     -23 Difference

   text    data     bss     dec     hex filename
   8787       8       0    8795    225b print-info.cpp.o [nusresign, before]
   8574       8       0    8582    2186 print-info.cpp.o [nusresign, after]
   -213       0       0    -213     -d5 Difference

   text    data     bss     dec     hex filename
   5374       8       0    5382    1506 resign-nus.cpp.o [nusresign, before]
   5341       8       0    5349    14e5 resign-nus.cpp.o [nusresign, after]
    -33       0       0     -33     -21 Difference
This commit is contained in:
David Korth 2022-07-14 01:33:32 -04:00
parent 6eafbf3ff4
commit 37833e42e9
7 changed files with 301 additions and 362 deletions

View File

@ -65,34 +65,30 @@ static void ATTR_PRINTF(2, 3) print_error(const TCHAR *argv0, const TCHAR *fmt,
*/
static void print_help(const TCHAR *argv0)
{
fputs("This program is licensed under the GNU GPL v2.\n"
"For more information, visit: http://www.gnu.org/licenses/\n"
"\n", stdout);
_fputts(_T("This program is licensed under the GNU GPL v2.\n")
_T("For more information, visit: http://www.gnu.org/licenses/\n")
_T("\n"), stdout);
fputs("Syntax: ", stdout);
_fputts(argv0, stdout);
fputs(" [options] [command]\n"
"\n"
"Supported commands:\n"
"\n"
"info nusdir/\n"
"- Print information about the specified NUS directory.\n"
"\n"
"resign nusdir/\n"
" - Resigns the specified NUS directory in place.\n"
" Default converts Retail NUS to Debug, and Debug NUS to retail.\n"
"\n"
"verify nusdir/\n"
" - Verify the content hashes.\n"
"\n"
"Options:\n"
"\n"
" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n"
" default, retail, debug\n"
" Recrypting to retail will blank out the signatures.\n"
" -h, --help Display this help and exit.\n"
"\n"
, stdout);
_tprintf(_T("Syntax: %s [options] [command]\n\n"), argv0);
_fputts(_T("Supported commands:\n")
_T("\n")
_T("info nusdir/\n")
_T("- Print information about the specified NUS directory.\n")
_T("\n")
_T("resign nusdir/\n")
_T("- Resigns the specified NUS directory in place.\n")
_T(" Default converts Retail NUS to Debug, and Debug NUS to retail.\n")
_T("\n")
_T("verify nusdir/\n")
_T(" - Verify the content hashes.\n")
_T("\n")
_T("Options:\n")
_T("\n")
_T(" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n")
_T(" default, retail, debug\n")
_T(" Recrypting to retail will blank out the signatures.\n")
_T(" -h, --help Display this help and exit.\n")
_T("\n"), stdout);
}
/**
@ -133,15 +129,15 @@ int RVTH_CDECL _tmain(int argc, TCHAR *argv[])
// Set the C locale.
setlocale(LC_ALL, "");
puts("NUS Resigner v" VERSION_STRING "\n"
"Copyright (c) 2018-2020 by David Korth.");
_fputts(_T("NUS Resigner v") _T(VERSION_STRING) _T("\n")
_T("Copyright (c) 2018-2022 by David Korth.\n")
#ifdef RP_GIT_VERSION
puts(RP_GIT_VERSION);
# ifdef RP_GIT_DESCRIBE
puts(RP_GIT_DESCRIBE);
# endif
_T(RP_GIT_VERSION) _T("\n")
# ifdef RP_GIT_DESCRIBE
_T(RP_GIT_DESCRIBE) _T("\n")
# endif
#endif
putchar('\n');
_T("\n"), stdout);
// Using Unicode getopt() for Windows:
// - https://www.codeproject.com/Articles/157001/Full-getopt-Port-for-Unicode-and-Multibyte-Microso

View File

@ -2,7 +2,7 @@
* RVT-H Tool: WAD Resigner *
* print-info.c: Print WAD information. *
* *
* Copyright (c) 2018-2020 by David Korth. *
* Copyright (c) 2018-2022 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/
@ -19,14 +19,14 @@
#include <nettle/sha1.h>
#include <nettle/sha2.h>
// C includes.
// C includes
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// C++ includes.
// C++ includes
#include <memory>
#include <string>
using std::tstring;
@ -107,11 +107,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
if (err == 0) {
err = EIO;
}
fputs("- *** ERROR opening ", stderr);
_fputts(cidbuf, stderr);
fputs(".app: ", stderr);
_fputts(_tcserror(err), stderr);
putchar('\n');
_ftprintf(stderr, _T("- *** ERROR opening %s.app: %s\n"), cidbuf, _tcserror(err));
return -err;
}
@ -128,11 +124,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
if (err == 0) {
err = EIO;
}
fputs("- *** ERROR opening ", stderr);
_fputts(cidbuf, stderr);
fputs(".h3: ", stderr);
_fputts(_tcserror(err), stderr);
putchar('\n');
_ftprintf(stderr, _T("- *** ERROR opening %s.h3: %s\n"), cidbuf, _tcserror(err));
return -err;
}
@ -145,9 +137,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
// Invalid size.
fclose(f_h3);
fclose(f_content);
fputs("- *** ERROR opening ", stderr);
_fputts(cidbuf, stderr);
fputs(".h3: Size is incorrect\n", stderr);
_ftprintf(stderr, _T("- *** ERROR opening %s.h3: Size is incorrect\n"), cidbuf);
return -EIO;
}
@ -162,11 +152,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
err = EIO;
}
fclose(f_content);
fputs("- *** ERROR opening ", stderr);
_fputts(cidbuf, stderr);
fputs(".h3: ", stderr);
_fputts(_tcserror(err), stderr);
putchar('\n');
_ftprintf(stderr, _T("- *** ERROR opening %s.h3: %s\n"), cidbuf, _tcserror(err));
return -err;
}
}
@ -244,19 +230,19 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
// Finalize the SHA-1 and compare it.
uint8_t digest[SHA1_DIGEST_SIZE];
sha1_digest(&sha1, sizeof(digest), digest);
fputs("- Expected SHA-1: ", stdout);
_fputts(_T("- Expected SHA-1: "), stdout);
for (size_t size = 0; size < sizeof(entry->sha1_hash); size++) {
printf("%02x", entry->sha1_hash[size]);
_tprintf(_T("%02x"), entry->sha1_hash[size]);
}
putchar('\n');
printf("- Actual SHA-1: ");
_fputtc(_T('\n'), stdout);
_fputts(_T("- Actual SHA-1: "), stdout);
for (size_t size = 0; size < sizeof(digest); size++) {
printf("%02x", digest[size]);
_tprintf(_T("%02x"), digest[size]);
}
if (!memcmp(digest, entry->sha1_hash, SHA1_DIGEST_SIZE)) {
fputs(" [OK]\n", stdout);
_fputts(_T(" [OK]\n"), stdout);
} else {
fputs(" [ERROR]\n", stdout);
_fputts(_T(" [ERROR]\n"), stdout);
ret = 1;
}
} else {
@ -384,7 +370,7 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
bool showH4status = true;
for (unsigned int i = 0; i < 3; i++) {
if (bad_hash[i] != 0) {
printf("- ERROR: %u H%u hash(es) were incorrect.\n", bad_hash[i], i);
_tprintf(_T("- ERROR: %u H%u hash(es) were incorrect.\n"), bad_hash[i], i);
showH4status = false;
ret = 1;
}
@ -396,24 +382,24 @@ static int verify_content(const TCHAR *nus_dir, const uint8_t title_key[16], con
sha1_init(&sha1_h4);
sha1_update(&sha1_h4, hash_h3_len, hash_h3.get());
sha1_digest(&sha1_h4, sizeof(digest), digest);
fputs("- Expected SHA-1: ", stdout);
_fputts(_T("- Expected SHA-1: "), stdout);
for (size_t size = 0; size < sizeof(entry->sha1_hash); size++) {
printf("%02x", entry->sha1_hash[size]);
_tprintf(_T("%02x"), entry->sha1_hash[size]);
}
fputs(" (H4)\n", stdout);
printf("- Actual SHA-1: ");
_fputts(_T(" (H4)\n"), stdout);
_fputts(_T("- Actual SHA-1: "), stdout);
for (size_t size = 0; size < sizeof(digest); size++) {
printf("%02x", digest[size]);
}
if (showH4status) {
if (!memcmp(digest, entry->sha1_hash, SHA1_DIGEST_SIZE)) {
fputs(" [OK] (H4)\n", stdout);
_fputts(_T(" [OK] (H4)\n"), stdout);
} else {
fputs(" [ERROR] (H4)\n", stdout);
_fputts(_T(" [ERROR] (H4)\n"), stdout);
ret = 1;
}
} else {
fputs(" (H4)\n", stdout);
_fputts(_T(" (H4)\n"), stdout);
}
}
@ -447,7 +433,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR opening ticket file: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR opening ticket file: %s\n"), _tcserror(err));
return -err;
}
@ -459,7 +445,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR opening TMD file: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR opening TMD file: %s\n"), _tcserror(err));
return -err;
}
@ -469,12 +455,12 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
if (tik_size < sizeof(WUP_Ticket)) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading ticket file: Too small.\n");
_fputts(_T("*** ERROR reading ticket file: Too small.\n"), stderr);
return -EIO;
} else if (tik_size > (64*1024)) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading ticket file: Too big.\n");
_fputts(_T("*** ERROR reading ticket file: Too big.\n"), stderr);
return -EIO;
}
fseeko(f_tmd, 0, SEEK_END);
@ -482,12 +468,12 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
if (tmd_size < (sizeof(WUP_TMD_Header) + sizeof(WUP_TMD_ContentInfoTable))) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading TMD file: Too small.\n");
_fputts(_T("*** ERROR reading TMD file: Too small.\n"), stderr);
return -EIO;
} else if (tmd_size > (128*1024)) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading TMD file: Too big.\n");
_fputts(_T("*** ERROR reading TMD file: Too big.\n"), stderr);
return -EIO;
}
rewind(f_tik);
@ -509,13 +495,13 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
_tprintf(_T("%s:\n"), nus_dir);
// FIXME: Get the actual Wii U application type.
//printf("Type: %08x\n", be32_to_cpu(pTmdHeader->rvl.title_type));
printf("- Title ID: %08X-%08X\n", be32_to_cpu(pTmdHeader->rvl.title_id.hi), be32_to_cpu(pTmdHeader->rvl.title_id.lo));
_tprintf(_T("- Title ID: %08X-%08X\n"), be32_to_cpu(pTmdHeader->rvl.title_id.hi), be32_to_cpu(pTmdHeader->rvl.title_id.lo));
// TODO: Figure out where the game ID is stored.
// Title version (TODO: Wii U changes?)
uint16_t title_version = be16_to_cpu(pTmdHeader->rvl.title_version);
printf("- Title version: %u.%u (v%u)\n",
_tprintf(_T("- Title version: %u.%u (v%u)\n"),
title_version >> 8, title_version & 0xFF, title_version);
// OS version
@ -528,29 +514,30 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
os_version = (uint8_t)ios_tid_lo;
}
}
printf("- OS version: OSv%u\n", os_version);
_tprintf(_T("- OS version: OSv%u\n"), os_version);
// Determine the encryption key in use.
// NOTE: May use CTR since CTR and WUP have the same certificates.
RVL_Cert_Issuer issuer_ticket = cert_get_issuer_from_name(pTicket->issuer);
RVL_AES_Keys_e encKey;
const char *s_encKey;
const TCHAR *s_encKey;
switch (issuer_ticket) {
default: // TODO: Show an error instead?
case CTR_CERT_ISSUER_PPKI_TICKET:
case WUP_CERT_ISSUER_PPKI_TICKET:
encKey = WUP_KEY_RETAIL;
s_encKey = "Retail";
s_encKey = _T("Retail");
break;
case CTR_CERT_ISSUER_DPKI_TICKET:
case WUP_CERT_ISSUER_DPKI_TICKET:
encKey = WUP_KEY_DEBUG;
s_encKey = "Debug";
s_encKey = _T("Debug");
break;
}
printf("- Encryption: %s\n", s_encKey);
_tprintf(_T("- Encryption: %s\n"), s_encKey);
// Check the ticket issuer and signature.
// FIXME: TCHAR version.
// NOTE: The ticket might have a certificate chain appended,
// so we'll only check the actual ticket data.
const char *const s_issuer_ticket = issuer_type(issuer_ticket);
@ -559,6 +546,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
s_issuer_ticket, RVL_SigStatus_toString_stsAppend(sig_status_ticket));
// Check the TMD issuer and signature.
// FIXME: TCHAR version.
// NOTE: TMD signature only covers the TMD header.
// We'll need to check the content info hash afterwards.
const char *const s_issuer_tmd = issuer_type(cert_get_issuer_from_name(pTmdHeader->rvl.issuer));
@ -617,7 +605,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
printf("- TMD Signature: %s%s\n",
s_issuer_tmd, RVL_SigStatus_toString_stsAppend(sig_status_tmd));
putchar('\n');
_fputtc(_T('\n'), stdout);
// Decrypted title key for contents verification.
uint8_t title_key[16];
@ -674,15 +662,15 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
// TODO: Show the actual table index, or just the
// index field in the entry?
uint16_t content_index = be16_to_cpu(p->index);
printf("#%d: ID=%08x, type=%04X, size=%u",
_tprintf(_T("#%d: ID=%08x, type=%04X, size=%u"),
be16_to_cpu(p->index),
be32_to_cpu(p->content_id),
be16_to_cpu(p->type),
(uint32_t)be64_to_cpu(p->size));
if (content_index == boot_index) {
fputs(", bootable", stdout);
_fputts(_T(", bootable"), stdout);
}
putchar('\n');
_fputtc(_T('\n'), stdout);
if (verify) {
// Verify the content.
@ -695,7 +683,7 @@ int print_nus_info(const TCHAR *nus_dir, bool verify)
}
}
}
putchar('\n');
_fputtc(_T('\n'), stdout);
return ret;
}

View File

@ -2,7 +2,7 @@
* RVT-H Tool: NUS Resigner *
* resign-nus.cpp: Re-sign an NUS directory. (Wii U) *
* *
* Copyright (c) 2018-2020 by David Korth. *
* Copyright (c) 2018-2022 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/
@ -17,7 +17,7 @@
#include "libwiicrypto/sig_tools.h"
#include "libwiicrypto/wiiu_structs.h"
// C includes.
// C includes
#include <assert.h>
#include <errno.h>
#include <stdint.h>
@ -25,7 +25,7 @@
#include <stdlib.h>
#include <string.h>
// C++ includes.
// C++ includes
#include <memory>
#include <string>
using std::tstring;
@ -154,7 +154,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR opening ticket file: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR opening ticket file: %s\n"), _tcserror(err));
return -err;
}
@ -166,7 +166,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR opening TMD file: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR opening TMD file: %s\n"), _tcserror(err));
return -err;
}
@ -176,12 +176,12 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
if (tik_size < sizeof(WUP_Ticket)) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading ticket file: Too small.\n");
_fputts(_T("*** ERROR reading ticket file: Too small.\n"), stderr);
return -EIO;
} else if (tik_size > (64*1024)) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading ticket file: Too big.\n");
_fputts(_T("*** ERROR reading ticket file: Too big.\n"), stderr);
return -EIO;
}
fseeko(f_tmd, 0, SEEK_END);
@ -189,12 +189,12 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
if (tmd_size < (sizeof(WUP_TMD_Header) + sizeof(WUP_TMD_ContentInfoTable))) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading TMD file: Too small.\n");
_fputts(_T("*** ERROR reading TMD file: Too small.\n"), stderr);
return -EIO;
} else if (tmd_size > (128*1024)) {
fclose(f_tik);
fclose(f_tmd);
fprintf(stderr, "*** ERROR reading TMD file: Too big.\n");
_fputts(_T("*** ERROR reading TMD file: Too big.\n"), stderr);
return -EIO;
}
rewind(f_tik);
@ -214,21 +214,20 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
// NOTE: Not checking the TMD key. Assuming it's the same as Ticket.
// NOTE: Need to check for 3DS
RVL_CryptoType_e src_key; // TODO: WUP constants?
const char *s_fromKey;
const TCHAR *s_fromKey;
switch (cert_get_issuer_from_name(pTicket->issuer)) {
case CTR_CERT_ISSUER_PPKI_TICKET:
case WUP_CERT_ISSUER_PPKI_TICKET:
src_key = RVL_CryptoType_Retail;
s_fromKey = "retail";
s_fromKey = _T("retail");
break;
case CTR_CERT_ISSUER_DPKI_TICKET:
case WUP_CERT_ISSUER_DPKI_TICKET:
src_key = RVL_CryptoType_Debug;
s_fromKey = "debug";
s_fromKey = _T("debug");
break;
default:
fputs("*** ERROR: NUS ticket has an unknown issuer.\n", stderr);
printf("issuer: %s == %d\n", pTicket->issuer, cert_get_issuer_from_name(pTicket->issuer));
_fputts(_T("*** ERROR: NUS ticket has an unknown issuer.\n"), stderr);
return 1;
}
@ -241,7 +240,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
} else {
// If the specified key matches the current key, fail.
if (recrypt_key == src_key) {
fputs("*** ERROR: Cannot recrypt to the same key.\n", stderr);
_fputts(_T("*** ERROR: Cannot recrypt to the same key.\n"), stderr);
return 2;
}
}
@ -249,7 +248,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
// Determine the new issuers.
RVL_Cert_Issuer issuer_ca, issuer_xs, issuer_cp, issuer_sp;
const char *s_issuer_xs, *s_issuer_cp;
const char *s_toKey;
const TCHAR *s_toKey;
RVL_AES_Keys_e toKey;
RVL_PKI toPki;
switch (recrypt_key) {
@ -258,7 +257,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
issuer_xs = WUP_CERT_ISSUER_PPKI_TICKET;
issuer_cp = WUP_CERT_ISSUER_PPKI_TMD;
issuer_sp = RVL_CERT_ISSUER_UNKNOWN;
s_toKey = "retail";
s_toKey = _T("retail");
toKey = WUP_KEY_RETAIL;
toPki = WUP_PKI_PPKI;
break;
@ -267,7 +266,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
issuer_xs = WUP_CERT_ISSUER_DPKI_TICKET;
issuer_cp = WUP_CERT_ISSUER_DPKI_TMD;
issuer_sp = WUP_CERT_ISSUER_DPKI_SP;
s_toKey = "debug";
s_toKey = _T("debug");
toKey = WUP_KEY_DEBUG;
toPki = WUP_PKI_DPKI;
break;
@ -279,7 +278,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
s_issuer_xs = RVL_Cert_Issuers[issuer_xs];
s_issuer_cp = RVL_Cert_Issuers[issuer_cp];
printf("Converting NUS from %s to %s...\n", s_fromKey, s_toKey);
_tprintf(_T("Converting NUS from %s to %s...\n"), s_fromKey, s_toKey);
/** Ticket fixups **/
@ -289,11 +288,11 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
case 0x10004:
break;
case 0x30004:
fprintf(stderr, "*** Changing ticket signature type from Disc to Installable.\n");
_fputts(_T("*** Changing ticket signature type from Disc to Installable.\n"), stdout);
pTicket->signature_type = cpu_to_be32(0x10004);
break;
default:
fprintf(stderr, "*** ERROR: Ticket has unsupported signature type: 0x%08X\n",
_ftprintf(stderr, _T("*** ERROR: Ticket has unsupported signature type: 0x%08X\n"),
be32_to_cpu(pTicket->signature_type));
fclose(f_tik);
fclose(f_tmd);
@ -303,11 +302,11 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
case 0x10004:
break;
case 0x30004:
fprintf(stderr, "*** Changing TMD signature type from Disc to Installable.\n");
_fputts(_T("*** Changing TMD signature type from Disc to Installable.\n"), stdout);
pTmdHeader->rvl.signature_type = cpu_to_be32(0x10004);
break;
default:
fprintf(stderr, "*** ERROR: TMD has unsupported signature type: 0x%08X\n",
_ftprintf(stderr, _T("*** ERROR: TMD has unsupported signature type: 0x%08X\n"),
be32_to_cpu(pTmdHeader->rvl.signature_type));
fclose(f_tik);
fclose(f_tmd);
@ -395,7 +394,7 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR: Unable to write title.cert: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR: Unable to write title.cert: %s\n"), _tcserror(err));
return -err;
}
@ -420,6 +419,6 @@ int resign_nus(const TCHAR *nus_dir, int recrypt_key)
fclose(f_cert);
printf("NUS resigning complete.\n");
_fputts(_T("NUS resigning complete.\n"), stdout);
return 0;
}

View File

@ -9,7 +9,7 @@
#include "config.version.h"
#include "git.h"
// C includes.
// C includes
#include <locale.h>
#include <stdarg.h>
#include <stdio.h>
@ -20,16 +20,16 @@
#include "libwiicrypto/sig_tools.h"
#ifdef _WIN32
# include "libwiicrypto/win32/secoptions.h"
# include "libwiicrypto/win32/secoptions.h"
#endif /* _WIN32 */
#include "print-info.h"
#include "resign-wad.hpp"
#ifdef __GNUC__
# define ATTR_PRINTF(fmt, args) __attribute__ ((format (printf, (fmt), (args))))
# define ATTR_PRINTF(fmt, args) __attribute__ ((format (printf, (fmt), (args))))
#else
# define ATTR_PRINTF(fmt, args)
# define ATTR_PRINTF(fmt, args)
#endif
/**
@ -59,38 +59,34 @@ static void ATTR_PRINTF(2, 3) print_error(const TCHAR *argv0, const TCHAR *fmt,
*/
static void print_help(const TCHAR *argv0)
{
fputs("This program is licensed under the GNU GPL v2.\n"
"For more information, visit: http://www.gnu.org/licenses/\n"
"\n", stdout);
_fputts(_T("This program is licensed under the GNU GPL v2.\n")
_T("For more information, visit: http://www.gnu.org/licenses/\n")
_T("\n"), stdout);
fputs("Syntax: ", stdout);
_fputts(argv0, stdout);
fputs(" [options] [command]\n"
"\n"
"Supported commands:\n"
"\n"
"info file.wad\n"
"- Print information about the specified WAD file.\n"
"\n"
"resign source.wad dest.wad\n"
"- Resigns source.wad and creates dest.wad using the new key.\n"
" Default converts Retail/Korean WADs to Debug, and\n"
" Debug WADs to Retail. The format isn't changed unless\n"
" the --format parameter is specified.\n"
"\n"
"verify file.wad\n"
"- Verify the content hashes.\n"
"\n"
"Options:\n"
"\n"
" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n"
" default, retail, korean, vWii, debug\n"
" Recrypting to retail will use fakesigning.\n"
" -f, --format=FMT Use the specified format FMT:\n"
" default, wad, bwf\n"
" -h, --help Display this help and exit.\n"
"\n"
, stdout);
_tprintf(_T("Syntax: %s [options] [command]\n\n"), argv0);
_fputts(_T("Supported commands:\n")
_T("\n")
_T("info file.wad\n")
_T("- Print information about the specified WAD file.\n")
_T("\n")
_T("resign source.wad dest.wad\n")
_T("- Resigns source.wad and creates dest.wad using the new key.\n")
_T(" Default converts Retail/Korean WADs to Debug, and\n")
_T(" Debug WADs to Retail. The format isn't changed unless\n")
_T(" the --format parameter is specified.\n")
_T("\n")
_T("verify file.wad\n")
_T("- Verify the content hashes.\n")
_T("\n")
_T("Options:\n")
_T("\n")
_T(" -k, --recrypt=KEY Recrypt the WAD using the specified KEY:\n")
_T(" default, retail, korean, vWii, debug\n")
_T(" Recrypting to retail will use fakesigning.\n")
_T(" -f, --format=FMT Use the specified format FMT:\n")
_T(" default, wad, bwf\n")
_T(" -h, --help Display this help and exit.\n")
_T("\n"), stdout);
}
int RVTH_CDECL _tmain(int argc, TCHAR *argv[])
@ -118,15 +114,15 @@ int RVTH_CDECL _tmain(int argc, TCHAR *argv[])
// Set the C locale.
setlocale(LC_ALL, "");
puts("WAD Resigner v" VERSION_STRING "\n"
"Copyright (c) 2018-2019 by David Korth.");
_fputts(_T("WAD Resigner v") _T(VERSION_STRING) _T("\n")
_T("Copyright (c) 2018-2022 by David Korth.\n")
#ifdef RP_GIT_VERSION
puts(RP_GIT_VERSION);
# ifdef RP_GIT_DESCRIBE
puts(RP_GIT_DESCRIBE);
# endif
_T(RP_GIT_VERSION) _T("\n")
# ifdef RP_GIT_DESCRIBE
_T(RP_GIT_DESCRIBE) _T("\n")
# endif
#endif
putchar('\n');
_T("\n"), stdout);
// Using Unicode getopt() for Windows:
// - https://www.codeproject.com/Articles/157001/Full-getopt-Port-for-Unicode-and-Multibyte-Microso

View File

@ -2,7 +2,7 @@
* RVT-H Tool: WAD Resigner *
* print-info.c: Print WAD information. *
* *
* Copyright (c) 2018-2020 by David Korth. *
* Copyright (c) 2018-2022 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/
@ -22,7 +22,7 @@
// Nettle SHA-1
#include <nettle/sha1.h>
// C includes.
// C includes
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
@ -74,9 +74,9 @@ static const char *issuer_type(RVL_Cert_Issuer issuer)
* @param pIsBWF [out] `bool` to store if the WAD file is a BroadOn WAD file or not.
* @return WAD file type as a string, or NULL on error.
*/
const char *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF)
const TCHAR *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF)
{
const char *s_wad_type = NULL;
const TCHAR *s_wad_type = NULL;
const WAD_Header *const header = (const WAD_Header*)buf;
if (buf_len < sizeof(Wii_WAD_Header)) {
// Not enough data...
@ -94,17 +94,17 @@ const char *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF)
*pIsBWF = false;
if (header->wad.type == cpu_to_be32(WII_WAD_TYPE_Is)) {
s_wad_type = "Installable";
s_wad_type = _T("Installable");
} else if (header->wad.type == cpu_to_be32(WII_WAD_TYPE_ib)) {
s_wad_type = "Boot2";
s_wad_type = _T("Boot2");
} else if (header->wad.type == cpu_to_be32(WII_WAD_TYPE_Bk)) {
s_wad_type = "Backup";
s_wad_type = _T("Backup");
} else {
// This might be a BroadOn WAD.
if (header->bwf.ticket_size == cpu_to_be32(sizeof(RVL_Ticket))) {
// Ticket size is correct.
// This is probably a BroadOn WAD.
s_wad_type = "BroadOn WAD Format";
s_wad_type = _T("BroadOn WAD Format");
*pIsBWF = true;
}
}
@ -225,19 +225,19 @@ static int verify_content(FILE *f_wad, RVL_AES_Keys_e encKey,
// Finalize the SHA-1 and compare it.
sha1_digest(&sha1, sizeof(digest), digest);
fputs("- Expected SHA-1: ", stdout);
_fputts(_T("- Expected SHA-1: "), stdout);
for (size = 0; size < sizeof(content->sha1_hash); size++) {
printf("%02x", content->sha1_hash[size]);
_tprintf(_T("%02x"), content->sha1_hash[size]);
}
putchar('\n');
printf("- Actual SHA-1: ");
_fputtc(_T('\n'), stdout);
_fputts(_T("- Actual SHA-1: "), stdout);
for (size = 0; size < sizeof(digest); size++) {
printf("%02x", digest[size]);
_tprintf(_T("%02x"), digest[size]);
}
if (!memcmp(digest, content->sha1_hash, SHA1_DIGEST_SIZE)) {
fputs(" [OK]\n", stdout);
_fputts(_T(" [OK]\n"), stdout);
} else {
fputs(" [ERROR]\n", stdout);
_fputts(_T(" [ERROR]\n"), stdout);
ret = 1;
}
@ -258,7 +258,7 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
{
int ret;
size_t size;
const char *s_wad_type = NULL;
const TCHAR *s_wad_type = NULL;
bool isBWF = false;
WAD_Header header;
WAD_Info_t wadInfo;
@ -281,8 +281,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
// Encryption key
RVL_AES_Keys_e encKey;
const char *s_encKey;
const char *s_invalidKey = NULL;
const TCHAR *s_encKey;
const TCHAR *s_invalidKey = NULL;
// Contents
unsigned int nbr_cont, nbr_cont_actual;
@ -295,9 +295,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
size = fread(&header, 1, sizeof(header), f_wad);
if (size != sizeof(header)) {
int err = errno;
fputs("*** ERROR reading WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "': %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR reading WAD file '%s': %s\n"),
wad_filename, _tcserror(err));
ret = -err;
goto end;
}
@ -307,9 +306,7 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
s_wad_type = identify_wad_type((const uint8_t*)&header, sizeof(header), &isBWF);
if (!s_wad_type) {
// Unrecognized WAD type.
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "' is not valid.\n");
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid.\n"), wad_filename);
ret = 1;
goto end;
}
@ -322,41 +319,31 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
}
if (ret != 0) {
// Unable to get WAD information.
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "' is not valid.");
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid.\n"), wad_filename);
ret = 2;
goto end;
}
// Verify the ticket and TMD sizes.
if (wadInfo.ticket_size < sizeof(RVL_Ticket)) {
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "' ticket size is too small. (%u; should be %u)\n",
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too small. (%u; should be %u)\n"),
wad_filename, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
ret = 3;
goto end;
} else if (wadInfo.ticket_size > WAD_TICKET_SIZE_MAX) {
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "' ticket size is too big. (%u; should be %u)\n",
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too big. (%u; should be %u)\n"),
wad_filename, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
ret = 4;
goto end;
} else if (wadInfo.tmd_size < sizeof(RVL_TMD_Header)) {
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "' TMD size is too small. (%u; should be at least %u)\n",
wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too small. (%u; should be at least %u)\n"),
wad_filename, wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
ret = 5;
goto end;
} else if (wadInfo.tmd_size > WAD_TMD_SIZE_MAX) {
// Too big.
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "' TMD size is too big. (%u; should be less than 1 MB)\n",
wadInfo.tmd_size);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too big. (%u; should be less than 1 MiB)\n"),
wad_filename, wadInfo.tmd_size);
ret = 6;
goto end;
}
@ -364,7 +351,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
// Load the ticket and TMD.
ticket_u8 = malloc(wadInfo.ticket_size);
if (!ticket_u8) {
fprintf(stderr, "*** ERROR: Unable to allocate %u bytes for the ticket.\n", wadInfo.ticket_size);
_ftprintf(stderr, _T("*** ERROR: Unable to allocate %u bytes for the ticket.\n"),
wadInfo.ticket_size);
ret = 7;
goto end;
}
@ -372,9 +360,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
size = fread(ticket_u8, 1, wadInfo.ticket_size, f_wad);
if (size != wadInfo.ticket_size) {
// Read error.
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fputs("': Unable to read the ticket.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unable to read the ticket.\n"),
wad_filename);
ret = 8;
goto end;
}
@ -382,7 +369,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
tmd_u8 = malloc(wadInfo.tmd_size);
if (!tmd_u8) {
fprintf(stderr, "*** ERROR: Unable to allocate %u bytes for the TMD.\n", wadInfo.tmd_size);
_ftprintf(stderr, _T("*** ERROR: Unable to allocate %u bytes for the TMD.\n"),
wadInfo.tmd_size);
ret = 9;
goto end;
}
@ -390,9 +378,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
size = fread(tmd_u8, 1, wadInfo.tmd_size, f_wad);
if (size != wadInfo.tmd_size) {
// Read error.
fputs("*** ERROR: WAD file '", stderr);
_fputts(wad_filename, stderr);
fputs("': Unable to read the TMD.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unable to read the TMD.\n"),
wad_filename);
ret = 10;
goto end;
}
@ -400,8 +387,10 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
// NOTE: Using TMD for most information.
_tprintf(_T("%s:\n"), wad_filename);
printf("Type: %s\n", s_wad_type);
printf("- Title ID: %08X-%08X\n", be32_to_cpu(tmdHeader->title_id.hi), be32_to_cpu(tmdHeader->title_id.lo));
_tprintf(_T("Type: %s\n"), s_wad_type);
_tprintf(_T("- Title ID: %08X-%08X\n"),
be32_to_cpu(tmdHeader->title_id.hi),
be32_to_cpu(tmdHeader->title_id.lo));
// Game ID, but only if all characters are alphanumeric.
if (ISALNUM(tmdHeader->title_id.u8[4]) &&
@ -409,13 +398,14 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
ISALNUM(tmdHeader->title_id.u8[6]) &&
ISALNUM(tmdHeader->title_id.u8[7]))
{
// TODO: _tprintf()?
printf("- Game ID: %.4s\n",
(const char*)&tmdHeader->title_id.u8[4]);
}
// Title version
title_version = be16_to_cpu(tmdHeader->title_version);
printf("- Title version: %u.%u (v%u)\n",
_tprintf(_T("- Title version: %u.%u (v%u)\n"),
(unsigned int)(title_version >> 8),
(unsigned int)(title_version & 0xFF),
title_version);
@ -428,7 +418,7 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
ios_version = (uint8_t)ios_tid_lo;
}
}
printf("- IOS version: %u\n", ios_version);
_tprintf(_T("- IOS version: %u\n"), ios_version);
// Determine the encryption key in use.
issuer_ticket = cert_get_issuer_from_name(ticket->issuer);
@ -439,26 +429,26 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
switch (ticket->common_key_index) {
case 0:
encKey = RVL_KEY_RETAIL;
s_encKey = "Retail";
s_encKey = _T("Retail");
break;
case 1:
encKey = RVL_KEY_KOREAN;
s_encKey = "Korean";
s_encKey = _T("Korean");
break;
case 2:
encKey = vWii_KEY_RETAIL;
s_encKey = "vWii";
s_encKey = _T("vWii");
break;
default: {
// NOTE: A good number of retail WADs have an
// incorrect common key index for some reason.
if (ticket->title_id.u8[7] == 'K') {
s_invalidKey = "Korean";
s_encKey = "Korean";
s_invalidKey = _T("Korean");
s_encKey = _T("Korean");
encKey = RVL_KEY_KOREAN;
} else {
s_invalidKey = "retail";
s_encKey = "Retail";
s_invalidKey = _T("retail");
s_encKey = _T("Retail");
encKey = RVL_KEY_RETAIL;
}
break;
@ -472,50 +462,48 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
// FIXME: How to handle invalid indexes?
// For now, assume it's the same as debug.
encKey = RVL_KEY_DEBUG;
s_encKey = "Debug";
s_encKey = _T("Debug");
break;
case 1:
encKey = RVL_KEY_KOREAN_DEBUG;
s_encKey = "Korean (Debug)";
s_encKey = _T("Korean (Debug)");
break;
case 2:
encKey = vWii_KEY_DEBUG;
s_encKey = "vWii (Debug)";
s_encKey = _T("vWii (Debug)");
break;
}
break;
}
printf("- Encryption: %s\n", s_encKey);
_tprintf(_T("- Encryption: %s\n"), s_encKey);
// Check the ticket issuer and signature.
// FIXME: TCHAR version.
s_issuer_ticket = issuer_type(issuer_ticket);
sig_status_ticket = sig_verify(ticket_u8, wadInfo.ticket_size);
printf("- Ticket Signature: %s%s\n",
s_issuer_ticket, RVL_SigStatus_toString_stsAppend(sig_status_ticket));
// Check the TMD issuer and signature.
// FIXME: TCHAR version.
s_issuer_tmd = issuer_type(cert_get_issuer_from_name(tmdHeader->issuer));
sig_status_tmd = sig_verify(tmd_u8, wadInfo.tmd_size);
printf("- TMD Signature: %s%s\n",
s_issuer_tmd, RVL_SigStatus_toString_stsAppend(sig_status_tmd));
putchar('\n');
_fputtc(_T('\n'), stdout);
if (wadInfo.ticket_size > sizeof(RVL_Ticket)) {
fputs("*** WARNING: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "' ticket size is too big. (%u; should be %u)\n\n",
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
_ftprintf(stderr, _T("*** WARNING: WAD file '%s' ticket size is too big. (%u; should be %u)\n\n"),
wad_filename, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
}
if (s_invalidKey) {
// Invalid common key index for retail.
// NOTE: A good number of retail WADs have an
// incorrect common key index for some reason.
fputs("*** WARNING: WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "': Invalid common key index %u.\n",
ticket->common_key_index);
fprintf(stderr, "*** Assuming %s common key based on game ID.\n\n", s_invalidKey);
_ftprintf(stderr, _T("*** WARNING: WAD file '%s': Invalid common key index %u.\n"),
wad_filename, ticket->common_key_index);
_ftprintf(stderr, _T("*** Assuming %s common key based on game ID.\n\n"), s_invalidKey);
}
// Print the contents.
@ -539,15 +527,15 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
// index field in the entry?
const uint32_t content_size = (uint32_t)be64_to_cpu(content->size);
uint16_t content_index = be16_to_cpu(content->index);
printf("#%d: ID=%08x, type=%04X, size=%u",
_tprintf(_T("#%d: ID=%08x, type=%04X, size=%u"),
content_index,
be32_to_cpu(content->content_id),
be16_to_cpu(content->type),
content_size);
if (content_index == boot_index) {
fputs(", bootable", stdout);
_fputts(_T(", bootable"), stdout);
}
putchar('\n');
_fputtc(_T('\n'), stdout);
if (verify) {
// Verify the content.
@ -555,9 +543,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
int vret = verify_content(f_wad, encKey, ticket, content, content_addr);
if (vret < 0) {
// Read error.
fprintf(stderr, "*** ERROR reading content #%d: ", content_index);
_fputts(_tcserror(-vret), stderr);
putchar('\n');
_ftprintf(stderr, _T("*** ERROR reading content #%d: %s\n"),
content_index, _tcserror(-vret));
ret = 1;
} else if (vret > 0) {
if (ret == 0 && encKey == vWii_KEY_RETAIL) {
@ -565,9 +552,8 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
vret = verify_content(f_wad, RVL_KEY_RETAIL, ticket, content, content_addr);
if (vret < 0) {
// Read error.
fprintf(stderr, "*** ERROR reading content #%d: ", content_index);
_fputts(_tcserror(-vret), stderr);
putchar('\n');
_ftprintf(stderr, _T("*** ERROR reading content #%d: %s\n"),
content_index, _tcserror(-vret));
} else if (vret == 0) {
vWii_crypt_error = true;
}
@ -601,9 +587,10 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
}
if (vWii_crypt_error) {
putchar('\n');
printf("*** WARNING: This WAD file should be encrypted using the vWii common\n"
" key, but it's actually encrypted with the retail common key.\n");
_fputtc(_T('\n'), stdout);
_fputts(_T("*** WARNING: This WAD file should be encrypted using the vWii common\n")
_T(" key, but it's actually encrypted with the retail common key.\n"),
stdout);
// FIXME: Add a way to fix this and indicate how to fix it.
}
@ -611,12 +598,12 @@ int print_wad_info_FILE(FILE *f_wad, const TCHAR *wad_filename, bool verify)
{
const int diff = (int)(data_size_actual - wadInfo.data_size);
if (diff != 0) {
putchar('\n');
printf("*** WARNING: The data size in the WAD header does not match the\n"
" actual content data size.\n"
" Expected: 0x%08X, actual: 0x%08X (difference: %c0x%0X)\n",
wadInfo.data_size, data_size_actual,
(diff < 0 ? '-' : '+'), (unsigned int)abs(diff));
_fputtc(_T('\n'), stdout);
_tprintf(_T("*** WARNING: The data size in the WAD header does not match the\n")
_T(" actual content data size.\n")
_T(" Expected: 0x%08X, actual: 0x%08X (difference: %c0x%0X)\n"),
wadInfo.data_size, data_size_actual,
(diff < 0 ? '-' : '+'), (unsigned int)abs(diff));
// FIXME: Add a way to fix this and indicate how to fix it.
}
}
@ -641,9 +628,8 @@ int print_wad_info(const TCHAR *wad_filename, bool verify)
FILE *f_wad = _tfopen(wad_filename, _T("rb"));
if (!f_wad) {
int err = errno;
fputs("*** ERROR opening WAD file '", stderr);
_fputts(wad_filename, stderr);
fprintf(stderr, "': %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR opening WAD file '%s': %s"),
wad_filename, _tcserror(err));
return -err;
}

View File

@ -2,7 +2,7 @@
* RVT-H Tool: WAD Resigner *
* print-info.h: Print WAD information. *
* *
* Copyright (c) 2018-2020 by David Korth. *
* Copyright (c) 2018-2022 by David Korth. *
* SPDX-License-Identifier: GPL-2.0-or-later *
***************************************************************************/
@ -32,7 +32,7 @@ extern "C" {
* @param pIsBWF [out] `bool` to store if the WAD file is a BroadOn WAD file or not.
* @return WAD file type as a string, or NULL on error.
*/
const char *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF);
const TCHAR *identify_wad_type(const uint8_t *buf, size_t buf_len, bool *pIsBWF);
/**
* 'info' command. (internal function)

View File

@ -88,7 +88,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
RVL_TMD_Header *tmdHeader;
// Key names
const char *s_fromKey, *s_toKey;
const TCHAR *s_fromKey, *s_toKey;
// Files
FILE *f_src_wad = NULL, *f_dest_wad = NULL;
@ -141,9 +141,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fputs("*** ERROR reading WAD file '", stderr);
_fputts(src_wad, stderr);
fprintf(stderr, "': %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR reading WAD file '%s': %s\n"),
src_wad, _tcserror(err));
ret = -err;
goto end;
}
@ -154,9 +153,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
// it's a BroadOn WAD or not.
if (identify_wad_type((const uint8_t*)&srcHeader, sizeof(srcHeader), &isSrcBwf) == NULL) {
// Unrecognized WAD type.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fputs("' is not valid.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid."), src_wad);
ret = 1;
goto end;
}
@ -169,49 +166,37 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
}
if (ret != 0) {
// Unable to get WAD information.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fputs("' is not valid.", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' is not valid."), src_wad);
ret = 2;
goto end;
}
// Verify the various sizes.
if (wadInfo.ticket_size < sizeof(RVL_Ticket)) {
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fprintf(stderr, "' ticket size is too small. (%u; should be %u)\n",
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too small. (%u; should be %u)\n"),
src_wad, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
ret = 3;
goto end;
} else if (wadInfo.ticket_size > WAD_TICKET_SIZE_MAX) {
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fprintf(stderr, "' ticket size is too big. (%u; should be %u)\n",
wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ticket size is too big. (%u; should be %u)\n"),
src_wad, wadInfo.ticket_size, (uint32_t)sizeof(RVL_Ticket));
ret = 4;
goto end;
} else if (wadInfo.tmd_size < sizeof(RVL_TMD_Header)) {
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fprintf(stderr, "' TMD size is too small. (%u; should be at least %u)\n",
wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too small. (%u; should be at least %u)\n"),
src_wad, wadInfo.tmd_size, (uint32_t)sizeof(RVL_TMD_Header));
ret = 5;
goto end;
} else if (wadInfo.tmd_size > WAD_TMD_SIZE_MAX) {
// Too big.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fprintf(stderr, "' TMD size is too big. (%u; should be less than 1 MB)\n",
wadInfo.tmd_size);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' TMD size is too big. (%u; should be less than 1 MiB)\n"),
src_wad, wadInfo.tmd_size);
ret = 6;
goto end;
} else if (wadInfo.meta_size > WAD_META_SIZE_MAX) {
// Too big.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fprintf(stderr, "' metadata size is too big. (%u; should be less than 1 MB)\n",
wadInfo.meta_size);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' ' metadata size is too big. (%u; should be less than 1 MB)\n"),
src_wad, wadInfo.meta_size);
ret = 7;
goto end;
}
@ -223,9 +208,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
// Data size is the rest of the file.
if (src_file_size < wadInfo.data_address) {
// Not valid...
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fputs("' data size is invalid.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data size is invalid.\n"), src_wad);
ret = 8;
goto end;
}
@ -234,16 +217,12 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
// Verify the data size.
if (src_file_size < wadInfo.data_address) {
// File is too small.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fputs("' data address is invalid.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data address is invalid.\n"), src_wad);
ret = 9;
goto end;
} else if (src_file_size - wadInfo.data_address < wadInfo.data_size) {
// Data size is too small.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fputs("' data size is invalid.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data size is invalid.\n"), src_wad);
ret = 10;
goto end;
}
@ -253,10 +232,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (wadInfo.data_size > WAD_DATA_SIZE_MAX) {
// Maximum of 128 MB.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fprintf(stderr, "' data size is too big. (%u; should be less than 128 MB)\n",
wadInfo.data_size);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s' data size is too big. (%u; should be less than 128 MiB)\n"),
src_wad, wadInfo.data_size);
ret = 11;
goto end;
}
@ -266,9 +243,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
size = fread(buf->u8, 1, wadInfo.ticket_size, f_src_wad);
if (size != wadInfo.ticket_size) {
// Read error.
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fputs("': Unable to read the ticket.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unable to read the ticket.\n"), src_wad);
ret = 13;
goto end;
}
@ -280,15 +255,15 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
switch (buf->ticket.common_key_index) {
case 0:
src_key = RVL_CryptoType_Retail;
s_fromKey = "retail";
s_fromKey = _T("retail");
break;
case 1:
src_key = RVL_CryptoType_Korean;
s_fromKey = "Korean";
s_fromKey = _T("Korean");
break;
case 2:
src_key = RVL_CryptoType_vWii;
s_fromKey = "vWii";
s_fromKey = _T("vWii");
break;
default: {
// NOTE: A good number of retail WADs have an
@ -297,10 +272,10 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
// print_wad_info(), so don't print one here.
if (buf->ticket.title_id.u8[7] == 'K') {
src_key = RVL_CryptoType_Korean;
s_fromKey = "Korean";
s_fromKey = _T("Korean");
} else {
src_key = RVL_CryptoType_Retail;
s_fromKey = "retail";
s_fromKey = _T("retail");
}
break;
}
@ -308,12 +283,10 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
break;
case RVL_CERT_ISSUER_DPKI_TICKET:
src_key = RVL_CryptoType_Debug;
s_fromKey = "debug";
s_fromKey = _T("debug");
break;
default:
fputs("*** ERROR: WAD file '", stderr);
_fputts(src_wad, stderr);
fputs("': Unknown issuer.\n", stderr);
_ftprintf(stderr, _T("*** ERROR: WAD file '%s': Unknown issuer.\n"), src_wad);
ret = 14;
goto end;
}
@ -335,7 +308,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
default:
// Should not happen...
assert(!"src_key: Invalid cryptoType.");
fputs("*** ERROR: Unable to select encryption key.\n", stderr);
_fputts(_T("*** ERROR: Unable to select encryption key.\n"), stderr);
ret = 15;
goto end;
}
@ -362,7 +335,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
// Allow the same key only if converting to a different format.
if (isSrcBwf == isDestBwf) {
// No point in recrypting to the same key and format...
fputs("*** ERROR: Cannot recrypt to the same key and format.\n", stderr);
_fputts(_T("*** ERROR: Cannot recrypt to the same key and format.\n"), stderr);
ret = 16;
goto end;
}
@ -372,37 +345,36 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
switch (recrypt_key) {
case RVL_CryptoType_Debug:
toKey = RVL_KEY_DEBUG;
s_toKey = "debug (realsigned)";
s_toKey = _T("debug (realsigned)");
break;
case RVL_CryptoType_Retail:
toKey = RVL_KEY_RETAIL;
s_toKey = "retail (fakesigned)";
s_toKey = _T("retail (fakesigned)");
break;
case RVL_CryptoType_Korean:
// TODO: Add RVL_CryptoType_Korean_Debug?
toKey = RVL_KEY_KOREAN;
s_toKey = "Korean (fakesigned)";
s_toKey = _T("Korean (fakesigned)");
break;
case RVL_CryptoType_vWii:
// TODO: Add RVL_CryptoType_vWii_Debug?
toKey = vWii_KEY_RETAIL;
s_toKey = "vWii (fakesigned)";
s_toKey = _T("vWii (fakesigned)");
break;
default:
// Invalid key index.
// This should not happen...
assert(!"recrypt_key: Invalid key index.");
fputs("*** ERROR: Invalid recrypt_key value.\n", stderr);
_fputts(_T("*** ERROR: Invalid recrypt_key value.\n"), stderr);
ret = 17;
goto end;
}
putchar('\n');
printf("Converting from %s to %s [", s_fromKey, s_toKey);
fputs(isSrcBwf ? "bwf" : "wad", stdout);
fputs("->", stdout);
fputs(isDestBwf ? "bwf" : "wad", stdout);
fputs("]...\n", stdout);
_fputtc(_T('\n'), stdout);
_tprintf(_T("Converting from %s to %s [%s->%s]...\n"),
s_fromKey, s_toKey,
isSrcBwf ? _T("bwf") : _T("wad"),
isDestBwf ? _T("bwf") : _T("wad"));
// Open the destination WAD file.
errno = 0;
@ -412,9 +384,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fputs("*** ERROR opening destination WAD file '", stderr);
_fputts(dest_wad, stderr);
fprintf(stderr, "' for write: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR opening destination WAD file '%s' for write: %s\n"),
dest_wad, _tcserror(err));
ret = -err;
goto end;
}
@ -459,7 +430,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (isSrcBwf) {
if (!isDestBwf) {
// bwf->wad
printf("Converting the BroadOn WAD header to standard WAD format...\n");
_tprintf(_T("Converting the BroadOn WAD header to standard WAD format...\n"));
data_offset = 0;
// Type is 'Is' for most WADs, 'ib' for boot2.
@ -493,7 +464,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
} else /*if (!isSrcBwf)*/ {
if (isDestBwf) {
// wad->bwf
printf("Converting the standard WAD header to BroadOn WAD format...\n");
_tprintf(_T("Converting the standard WAD header to BroadOn WAD format...\n"));
outHeader.bwf.header_size = cpu_to_be32(sizeof(outHeader));
outHeader.bwf.data_offset = cpu_to_be32(data_offset);
@ -519,7 +490,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing initial destination WAD header: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing initial destination WAD header: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -530,7 +502,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
}
// Write the certificates.
printf("Writing certificate chain...\n");
_tprintf(_T("Writing certificate chain...\n"));
errno = 0;
size = fwrite(cert_CA, 1, sizeof(*cert_CA), f_dest_wad);
if (size != sizeof(*cert_CA)) {
@ -538,7 +510,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -549,7 +522,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -560,7 +534,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -572,7 +547,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing destination WAD certificate chain: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing destination WAD certificate chain: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -588,7 +564,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
assert(wadInfo.crl_size == 0);
// Recrypt the ticket and TMD.
printf("Recrypting the ticket and TMD...\n");
_tprintf(_T("Recrypting the ticket and TMD...\n"));
// Ticket is already loaded, so recrypt and resign it.
errno = 0;
@ -599,7 +575,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR recrypting the ticket: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR recrypting the ticket: %s\n"), _tcserror(err));
ret = -err;
goto end;
}
@ -623,7 +599,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing destination WAD ticket: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing destination WAD ticket: %s\n"), _tcserror(err));
ret = -err;
goto end;
}
@ -643,7 +619,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR reading source WAD TMD: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR reading source WAD TMD: %s\n"), _tcserror(err));
ret = -err;
goto end;
}
@ -684,7 +660,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing destination WAD TMD: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing destination WAD TMD: %s\n"), _tcserror(err));
ret = -err;
goto end;
}
@ -702,7 +678,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR seeking in destination WAD: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR seeking in destination WAD: %s\n"), _tcserror(err));
ret = -err;
goto end;
}
@ -719,7 +695,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
const uint32_t content_size = (uint32_t)be64_to_cpu(content->size);
uint32_t size_to_copy = ALIGN_BYTES(16, content_size);
uint16_t content_index = be16_to_cpu(content->index);
printf("Copying WAD content #%d...\n", content_index);
_tprintf(_T("Copying WAD content #%d...\n"), content_index);
// Contents are always physically AES-aligned (16 bytes), but the
// data size in the header does not include extra bytes at the end
@ -750,7 +726,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR reading source WAD data: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR reading source WAD data: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -762,7 +739,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR writing destination WAD data: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR writing destination WAD data: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -777,7 +755,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fprintf(stderr, "*** ERROR reading source WAD data: %s\n", strerror(err));
_ftprintf(stderr, _T("*** ERROR reading source WAD data: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -789,9 +768,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fputs("*** ERROR writing destination WAD data: ", stderr);
_fputts(_tcserror(err), stderr);
fputc('\n', stderr);
_ftprintf(stderr, _T("*** ERROR writing destination WAD data: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -801,7 +779,7 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
// Copy the metadata.
// FIXME: Copy before the data if the output format is BWF.
if (wadInfo.meta_size != 0) {
printf("Copying the WAD metadata...\n");
_tprintf(_T("Copying the WAD metadata...\n"));
fseeko(f_src_wad, wadInfo.meta_address, SEEK_SET);
errno = 0;
@ -811,9 +789,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fputs("*** ERROR reading source WAD metadata: ", stderr);
_fputts(_tcserror(err), stderr);
fputc('\n', stderr);
_ftprintf(stderr, _T("*** ERROR reading source WAD metadata: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -830,9 +807,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fputs("*** ERROR writing destination WAD metadata: ", stderr);
_fputts(_tcserror(err), stderr);
fputc('\n', stderr);
_ftprintf(stderr, _T("*** ERROR writing destination WAD metadata: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -858,9 +834,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fputs("*** ERROR writing destination WAD padding: ", stderr);
_fputts(_tcserror(err), stderr);
fputc('\n', stderr);
_ftprintf(stderr, _T("*** ERROR writing destination WAD padding: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
@ -869,8 +844,8 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
// Do we need to update the data size?
if (likely(!isDestBwf) && unlikely(wadInfo.data_size != data_size_actual)) {
fprintf(stderr, "*** Fixing WAD header's data size field:\n"
" Old: 0x%08X, New: 0x%08X\n",
_ftprintf(stderr, _T("*** Fixing WAD header's data size field:\n")
_T(" Old: 0x%08X, New: 0x%08X\n"),
wadInfo.data_size, data_size_actual);
outHeader.wad.data_size = cpu_to_be32(data_size_actual);
}
@ -884,14 +859,13 @@ int resign_wad(const TCHAR *src_wad, const TCHAR *dest_wad, int recrypt_key, int
if (err == 0) {
err = EIO;
}
fputs("*** ERROR writing destination WAD header: ", stderr);
_fputts(_tcserror(err), stderr);
fputc('\n', stderr);
_ftprintf(stderr, _T("*** ERROR writing destination WAD header: %s\n"),
_tcserror(err));
ret = -err;
goto end;
}
printf("WAD resigning complete.\n");
_tprintf(_T("WAD resigning complete.\n"));
ret = 0;
end: