Title Lister
From WiiBrew
(Redirected from Homebrew Apps/Title Lister)
This simple utility is meant as an example to show how calls to /dev/es may be used to query the state of your Wii. It can answer such questions as what versions of IOS you have installed, and what software will use each version.
A compiled binary and source is available here.
Feel free to enhance this code as you please.
/*------------------------------------------------------------- title_lister.c -- displays contents of Wii NAND flash FS Copyright (C) 2008 bushing This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1.The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2.Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3.This notice may not be removed or altered from any source distribution. -------------------------------------------------------------*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <malloc.h> #include <ogcsys.h> #include <gccore.h> #include <ogc/ipc.h> #include <stdarg.h> #include <ctype.h> #include <unistd.h> #include <assert.h> char ascii(char s) { if(s < 0x20) return '.'; if(s > 0x7E) return '.'; return s; } static void *xfb = NULL; static GXRModeObj *rmode = NULL; typedef void (*Loader_Entry)(void); Loader_Entry loader = (Loader_Entry)0x80001800; void checkAndReload(void) { PAD_ScanPads(); int buttonsDown = PAD_ButtonsHeld(0); if( (buttonsDown & PAD_TRIGGER_Z) && (buttonsDown & PAD_BUTTON_START)) { loader(); } } void waita(void) { while(1) { VIDEO_WaitVSync(); PAD_ScanPads(); int buttonsDown = PAD_ButtonsDown(0); if(buttonsDown & PAD_BUTTON_A) return; if( (buttonsDown & PAD_TRIGGER_Z) && (buttonsDown & PAD_BUTTON_START)) { loader(); } } } void printvers(void) { printf("IOS Version: %08x\n", *((u32*)0xC0003140)); } s32 __STM_Init(); void console_setup(void) { VIDEO_Init(); PAD_Init(); switch(VIDEO_GetCurrentTvMode()) { case VI_NTSC: rmode = &TVNtsc480IntDf; break; case VI_PAL: rmode = &TVPal528IntDf; break; case VI_MPAL: rmode = &TVMpal480IntDf; break; default: rmode = &TVNtsc480IntDf; break; } xfb = MEM_K0_TO_K1(SYS_AllocateFramebuffer(rmode)); console_init(xfb,20,20,rmode->fbWidth,rmode->xfbHeight,rmode->fbWidth*VI_DISPLAY_PIX_SZ); VIDEO_Configure(rmode); VIDEO_SetNextFramebuffer(xfb); VIDEO_SetBlack(FALSE); VIDEO_Flush(); VIDEO_WaitVSync(); if(rmode->viTVMode&VI_NON_INTERLACE) VIDEO_WaitVSync(); } char * display_tmd_info(const tmd *t) { static char desc[256]; u32 kind = t->title_id >> 32; u32 title_l = t->title_id & 0xFFFFFFFF; char title_ascii[5]; u32 i; memcpy(title_ascii, &title_l, 4); for (i=0; i<4; i++) title_ascii[i]=ascii(title_ascii[i]); title_ascii[4]='\0'; switch (kind) { case 1: // IOS, MIOS, BC, System Menu snprintf(desc, sizeof(desc), "Title=1-%x (", title_l); switch(title_l) { case 2: strlcat(desc, "System Menu) ", sizeof(desc)); break; case 0x100: strlcat(desc, "BC) ", sizeof(desc)); break; case 0x101: strlcat(desc, "MIOS) ", sizeof(desc)); break; default: sprintf(desc + strlen(desc), "IOS%d) ", title_l); break; } break; case 0x10000: // TMD installed by running a disc snprintf(desc, sizeof(desc), "Title=10000-%08x (savedata for '%s')", title_l, title_ascii); break; case 0x10001: // Normal channels / VC snprintf(desc, sizeof(desc), "Title=10001-%08x (downloaded channel '%s')", title_l, title_ascii); break; case 0x10002: // "System channels" -- News, Weather, etc. snprintf(desc, sizeof(desc), "Title=10002-%08x (system channel '%s')", title_l, title_ascii); break; case 0x10004: // "Hidden channels" -- WiiFit channel snprintf(desc, sizeof(desc), "Title=10004-%08x (game channel '%s')", title_l, title_ascii); break; case 0x10008: // "Hidden channels" -- EULA, rgnsel snprintf(desc, sizeof(desc), "Title=10008-%08x (hidden? channel '%s')", title_l, title_ascii); break; default: printf("Unknown title type %x %08x\n", kind, title_l); break; } if (t->title_version) snprintf(desc, sizeof(desc), "%s vers: %d.%d (%d)", desc, t->title_version >> 8, t->title_version & 0xFF, t->title_version); if (t->sys_version) snprintf(desc, sizeof(desc), "%s FW: IOS%llu ", desc, t->sys_version & 0xff); return desc; } int main(int argc, char **argv) { console_setup(); // printvers(); __STM_Init(); SYS_SetResetCallback(loader); s32 ret; u32 count; ret = ES_GetNumTitles(&count); if (ret) { printf("ES_GetNumTitles=%d, count=%08x\n", ret, count); return ret; } printf("Found %d titles:\n", count); static u64 title_list[256] ATTRIBUTE_ALIGN(32); ret = ES_GetTitles(title_list, count); if (ret) { printf("ES_GetTitles=%d\n", ret); return ret; } int i; for (i=0; i < count; i++) { u32 tmd_size; ret = ES_GetStoredTMDSize(title_list[i], &tmd_size); static u8 tmd_buf[MAX_SIGNED_TMD_SIZE] ATTRIBUTE_ALIGN(32); signed_blob *s_tmd = (signed_blob *)tmd_buf; ret = ES_GetStoredTMD(title_list[i], s_tmd, tmd_size); printf("%d: %s\n", i+1, display_tmd_info(SIGNATURE_PAYLOAD(s_tmd))); if((i%10)==9) sleep(10); } return 0; }