Skip to content

Instantly share code, notes, and snippets.

@InvoxiPlayGames
Created February 22, 2024 01:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save InvoxiPlayGames/2f280592ae21d8a665a97c176e6c6e70 to your computer and use it in GitHub Desktop.
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
#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