Title Lister

From WiiBrew
Jump to navigation Jump to search

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;
}