/** * Wii WAD Tool */ #include #include #include #include #include #include "types.h" #include "patcher.h" #include "wii_wad.h" #include "ucs.h" #define VERSION "1.0.0" void print_usage(int argc, char **argv) { printf("Usage: %s [OPTIONS] FILE\n", argv[0]); printf("Modify/show information about Wii WAD FILE.\n\n"); printf(" -d, --dump\t\tprint detailed information about WAD file\n"); printf(" -r, --region\t\tchange the region code of the WAD file\n"); printf(" -v, --version\t\toutput version information and exit\n"); printf(" -h, --help\t\tprints usage information\n"); printf("\n"); } enum mode_type { INFO = 0, DUMP = 1, CHANGE_REGION = 2 }; char *basename(char *name) { return strrchr(name, '/')+1; }; int main(int argc, char **argv) { FILE *f; wad_header wad; tmd_header tmd; wii_tik tik; wii_imet imet; wii_build_info bi; int i; char mode = INFO; char *wad_filename = NULL; if (argc < 2) { print_usage(argc, argv); return 0; } setlocale(LC_ALL,""); /* parse cmdline args */ for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-v") || !strcmp(argv[i], "--version")) { printf("Wii WAD Tool %s\n", VERSION); return 0; } else if (!strcmp(argv[i], "-d") || !strcmp(argv[i], "--dump")) { mode = DUMP; continue; } else if (!strcmp(argv[i], "-r") || !strcmp(argv[i], "--region")) { mode = CHANGE_REGION; continue; } else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) { print_usage(argc, argv); return 0; } else { if(wad_filename != NULL) { print_usage(argc, argv); return 0; } wad_filename = argv[i]; } } if (wad_filename == NULL) { print_usage(argc, argv); return 0; } f = fopen(wad_filename, "r+"); if (f == NULL) { fprintf(stderr, "Failed to open file %s\n", basename(wad_filename)); return 0; } if(wad_read(f, &wad) == 0) { fprintf(stderr, "Invalid WAD file %s\n", basename(wad_filename)); return 0; }; wad_read_tmd(f, &wad, &tmd); tmd_content_record tmd_content[tmd.num_contents+1]; switch(mode) { case INFO: tmd_read_content_records(f, &tmd, tmd_content); wad_read_tik(f, &wad, &tmd, &tik); if(tmd.title_category != TITLE_CATEGORY_SYSTEM) { wad_read_app_info(f, &wad, &tmd_content[0], &tik, &bi, &imet); } printf("- information\n"); printf("File : %s\n", basename(wad_filename)); if(tmd.title_category != TITLE_CATEGORY_SYSTEM) { printf("System : %s\n", tmd_lookup_system_code_name(tmd.title_id)); printf("Title : "); print_ucs2_as_utf8(imet.name[IMET_LANG_EN]); printf("\n"); } printf("Category : %s (%08x)\n", tmd_lookup_title_category_name(tmd.title_category), tmd.title_category); if(tmd.title_category == TITLE_CATEGORY_SYSTEM) { printf("System : %s\n", "Firmware"); char name[12]; tmd_get_system_title_name(be32((u8*)&tmd.title_id), name); printf("Title ID : %s (%08x)\n", name, tmd.title_id); } else { printf("Title ID : %.4s\n", (char*)&tmd.title_id); } printf("Region Code : %s (%d)\n", region_names[tmd.region_code], tmd.region_code); printf("Blocks : %d\n", tmd_get_block_size(&tmd, tmd_content)); printf("Publisher ID: %s (%04x)\n", tmd_lookup_group_name(tmd.group_id), tmd.group_id); if(tmd.sys_version) printf("Firmware : IOS%llu\n", tmd.sys_version & 0xff); printf("Version : %d\n", tmd.title_version); break; case CHANGE_REGION: change_region_code(f, wad.tmd_size); break; case DUMP: /* dump all information we can parse */ print_wad(&wad); print_tmd(&tmd); tmd_read_content_records(f, &tmd, tmd_content); print_tmd_content_records(&tmd, tmd_content); /* read ticket */ wad_read_tik(f, &wad, &tmd, &tik); print_tik(&tik); if(tmd.title_category != TITLE_CATEGORY_SYSTEM) { /* read imet tag from first app content */ printf("- application info\n"); printf("Blocks : %d\n", tmd_get_block_size(&tmd, tmd_content)); wad_read_app_info(f, &wad, &tmd_content[0], &tik, &bi, &imet); printf("Dirname : %s\n", bi.dirname); printf("Build Host : %s\n", bi.host); printf("Unknown Flag 0: %04x\n", bi.unk_flag0); printf("Unknown Flag 1: %04x\n", bi.unk_flag1); for (i = 0; i < IMET_NAME_COUNT; i++) { printf("Name[%d] : ", i); print_ucs2_as_utf8(imet.name[i]); printf("\n"); } } break; } fclose(f); return 0; }