summaryrefslogtreecommitdiffstats
path: root/wii_wad.c
diff options
context:
space:
mode:
Diffstat (limited to 'wii_wad.c')
-rw-r--r--wii_wad.c137
1 files changed, 137 insertions, 0 deletions
diff --git a/wii_wad.c b/wii_wad.c
new file mode 100644
index 0000000..792c84c
--- /dev/null
+++ b/wii_wad.c
@@ -0,0 +1,137 @@
+/**
+ * wii_wad.c
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "wii_wad.h"
+#include "crypto.h"
+#include "ucs.h"
+
+void print_wad(wad_header *wad) {
+ printf("- wad_header\n");
+ printf("size : %1$08x (%1$d)\n", wad->size);
+ printf("type : %04x (%.2s)\n", wad->type, (char*)&wad->type);
+ printf("unknown : %04x\n", wad->unk0);
+ printf("cert_chain_size : %1$08x (%1$d)\n", wad->cert_chain_size);
+ printf("crl_size : %1$08x (%1$d)\n", wad->crl_size);
+ printf("ticket_size : %1$08x (%1$d)\n", wad->ticket_size);
+ printf("tmd_size : %1$08x (%1$d)\n", wad->tmd_size);
+ printf("data_size : %1$08x (%1$d)\n", wad->data_size);
+ printf("footer_size : %1$08x (%1$d)\n", wad->footer_size);
+}
+
+int wad_read(FILE *f, wad_header *wad) {
+ /* read head into struct */
+ fread(wad, sizeof(wad_header), 1, f);
+
+ /* convert to big endian */
+ wad->size = be32((u8*)&wad->size);
+ if (wad->size != 0x20)
+ return 0;
+
+ //wad->type = be16((u8*)&wad->type);
+ wad->unk0 = be16((u8*)&wad->unk0);
+ wad->cert_chain_size = be32((u8*)&wad->cert_chain_size);
+ wad->crl_size = be32((u8*)&wad->crl_size);
+ wad->ticket_size = be32((u8*)&wad->ticket_size);
+ wad->tmd_size = be32((u8*)&wad->tmd_size);
+ wad->data_size = be32((u8*)&wad->data_size);
+ wad->footer_size = be32((u8*)&wad->footer_size);
+
+ if (wad->ticket_size == 0)
+ return 0;
+
+ if (wad->tmd_size == 0)
+ return 0;
+
+ if (wad->data_size == 0)
+ return 0;
+
+ if (wad->footer_size == 0)
+ return 0;
+
+ return 1;
+}
+
+void wad_read_tmd(FILE *f, wad_header *wad, tmd_header *tmd) {
+ u32 rounded_len;
+ rounded_len = round_up(wad->size + wad->cert_chain_size + wad->ticket_size, 0x40);
+
+ /* seek to tmd start offset */
+ fseek(f, rounded_len, SEEK_SET);
+ tmd_read(f, tmd);
+}
+
+void wad_read_tik(FILE *f, wad_header *wad, tmd_header *tmd, wii_tik *tik) {
+ u32 rounded_len;
+ rounded_len = round_up(wad->size + wad->cert_chain_size, 0x40);
+
+ /* seek to tik start offset */
+ fseek(f, rounded_len, SEEK_SET);
+ tik_read(f, tik);
+}
+
+void wad_read_app_info(FILE *f, wad_header *wad, tmd_content_record *tmd_content, wii_tik *tik, wii_build_info *bi, wii_imet *imet) {
+ u8 title_key[16];
+ u8 iv[16];
+ u32 rounded_len;
+ u32 data_len;
+ u8 *data;
+ u16 i;
+
+ /* decrypt_title_key */
+ decrypt_title_key(tik, title_key);
+
+ /* read wad data chunk */
+ data_len = round_up(wad->data_size, 0x40);
+ data = malloc(data_len);
+ rounded_len = wad_get_section_offset(wad, SECTION_DATA);
+
+ fseek(f, rounded_len, SEEK_SET);
+ fread(data, data_len, 1, f);
+
+ rounded_len = round_up(tmd_content->size, 0x40);
+
+ i = be16((u8*)&tmd_content->index);
+
+ /* decrypt first content */
+ memset(iv, 0, sizeof(iv));
+ memcpy(iv, &i, 2);
+ aes_cbc_dec(title_key, iv, data, rounded_len, data);
+
+ /* read buildinfo */
+ memset(bi, 0, sizeof(wii_build_info));
+ memcpy((u8*)bi, data, sizeof(wii_build_info));
+
+ /*. parse first content's IMET tag */
+ memset(imet, 0, sizeof(wii_imet));
+ memcpy((u8*)imet, data + IMET_OFFSET, sizeof(wii_imet));
+
+ for (i = 0; i < IMET_NAME_COUNT; i++) {
+ beucs2(imet->name[i]);
+ }
+
+ free(data);
+}
+
+u32 wad_get_section_offset(wad_header *wad, u8 section) {
+ u32 ret = 0;
+
+ switch(section) {
+ case SECTION_FOOTER:
+ ret += round_up(wad->data_size, 0x40);
+ case SECTION_DATA:
+ ret += round_up(wad->tmd_size, 0x40);
+ case SECTION_TMD:
+ ret += round_up(wad->ticket_size, 0x40);
+ case SECTION_TICKET:
+ ret += round_up(wad->cert_chain_size, 0x40);
+ case SECTION_CERT_CHAIN:
+ ret += round_up(wad->size, 0x40);
+ case SECTION_WAD_HEADER:
+ break;
+ }
+
+ return ret;
+}