Created
February 22, 2024 01:21
-
-
Save InvoxiPlayGames/2f280592ae21d8a665a97c176e6c6e70 to your computer and use it in GitHub Desktop.
uidsys-output.c - very basic C utility to output a list of all titles found in a Wii's uid.sys
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#ifndef SHOULD_BE_BE | |
#define BE16(i) ((((i) & 0xFF) << 8 | ((i) >> 8) & 0xFF) & 0xFFFF) | |
#define BE(i) (((i) & 0xff) << 24 | ((i) & 0xff00) << 8 | ((i) & 0xff0000) >> 8 | ((i) >> 24) & 0xff) | |
#define BE64(i) (BE((i) & 0xFFFFFFFF) << 32 | BE(((i) >> 32) & 0xFFFFFFFF)) | |
#else | |
#define BE16(i) i | |
#define BE(i) i | |
#define BE64(i) i | |
#endif | |
typedef struct _uid_entry { | |
union { | |
uint64_t title_id; | |
struct { | |
uint32_t title_type; | |
uint32_t title_code; | |
}; | |
}; | |
uint16_t padding; | |
uint16_t uid; | |
} __attribute__((__packed__)) uid_entry; | |
int a = sizeof(uid_entry); | |
char *get_title_type_name(uint32_t type) { | |
switch (type) { | |
case 0x00000001: | |
return "System Title"; | |
case 0x00010000: | |
return "Disc Game"; | |
case 0x00010001: | |
return "Channel"; | |
case 0x00010002: | |
return "System Channel"; | |
case 0x00010004: | |
return "Game w/ Channel"; | |
case 0x00010005: | |
return "DLC Title"; | |
case 0x00010008: | |
return "Hidden Title"; | |
default: | |
return "Unknown"; | |
} | |
} | |
char *sanitize_title_id_name(uint32_t title_type, uint32_t title_code, char *buf) { | |
if (BE(title_type) == 0x00000001) { | |
uint32_t version = BE(title_code); | |
if (version == 0x1) | |
sprintf(buf, "boot2"); | |
else if (version == 0x2) | |
sprintf(buf, "System Menu"); | |
else if (version == 0x100) | |
sprintf(buf, "BC"); | |
else if (version == 0x101) | |
sprintf(buf, "MIOS"); | |
else if (version < 0x100) | |
sprintf(buf, "IOS%i", version); | |
else | |
sprintf(buf, "?"); | |
} else { | |
for (int i = 0; i < 4; i++) { | |
uint8_t thischar = (title_code >> (i * 8)) & 0xFF; | |
char parsedchar = '.'; | |
if (thischar >= 0x20 && thischar < 0x7F) | |
parsedchar = (char)thischar; | |
buf[i] = parsedchar; | |
} | |
buf[4] = 0; | |
} | |
return buf; | |
} | |
int main(int argc, char **argv) { | |
if (argc < 2) { | |
printf("usage: %s uid.sys\n", argv[0]); | |
return -1; | |
} | |
FILE *fp = fopen(argv[1], "rb"); | |
if (fp == NULL) { | |
printf("can't open %s\n", argv[1]); | |
return -1; | |
} | |
fseek(fp, 0, SEEK_END); | |
int filesize = ftell(fp); | |
fseek(fp, 0, SEEK_SET); | |
uid_entry *buf = (uid_entry *)malloc(filesize); | |
if (buf == NULL) { | |
printf("failed to allocate buffer\n"); | |
fclose(fp); | |
return -1; | |
} | |
fread(buf, 1, filesize, fp); | |
fclose(fp); | |
int total = filesize / sizeof(uid_entry); | |
printf("%i entries in uid.sys:\n", total); | |
for(int i = 0; i < total; i++) { | |
char tid_name[16]; | |
uid_entry entry = buf[i]; | |
printf("%08x-%08x - %s - %s - UID: 0x%x\n", | |
BE(entry.title_type), BE(entry.title_code), | |
get_title_type_name(BE(entry.title_type)), sanitize_title_id_name(entry.title_type, entry.title_code, tid_name), | |
BE16(entry.uid)); | |
} | |
free(buf); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment