Revolution OS

From WiiBrew
Jump to navigation Jump to search

Revolution OS is a part of the SDK that is always included. It does not handle security; IOS is responsible for that.


OSInit calls a function called OSGetConsoleType that logs platform information. The name is misleading, as it does not actually return any platform info.

Console types include:

  • Retail
  • NDEV 2.1
  • NDEV 2.0
  • NDEV 1.2
  • NDEV 1.1
  • NDEV 1.0
  • Revolution Emulator

Information about the emulation environment is also printed if the platform is Revolution Emulator.


There is a string saying Installing OSDBIntegrator. OSDBIntegrator seems to be a debug stub installed at 0x80000060 that branches to the address stored at 0x80000048. It is not known how this code is reached, as it is not jumped to by any retail code.

The code itself seems to be printing DBExceptionDestination, printing the current OSContext, and hanging the Broadway.


There appear to be different functions to log debug, info, and error messages; the logging level is controlled by the version of the SDK used, not a global variable. On retail SDKs, info and error are logged, but debug is a dummy function.

It is not known where the logs go.


With the exception of a system call, all exceptions have the same handler, which loads the appropriate exception-specific handler from the array at 0x80003000, or the default handler if the is no specific handler or the exception is not recoverable. Exception types are given IDs by Revolution OS; these numbers are used when setting an exception handler.

Type ID Handler location
System Reset 0 80000100
Machine Check 1 80000200
DSI 2 80000300
ISI 3 80000400
External (IRQ) 4 80000500
Alignment 5 80000600
Program 6 80000700
FP unavailable 7 80000800
Decrementer 8 80000900
System call 9 80000C00
Trace 10 80000D00
Performance Monitor 11 80000F00
IABR 12 80001300
Reserved 13 80001400
Thermal 14 80001700


IRQs are processed by handlers in the __OSInterrupt table; the bit index of the each source is the same as the index in the table; integers built from these bits are used for functions that mask interrupts.

Index Source
0 MEM0
1 MEM1
2 MEM2
3 MEM3
4 All MI
8 AI
9 EXI EXTINT low (channel 0)
10 EXI TCINT (channel 0)
11 EXI EXTINT high (channel 0)
12 EXI EXTINT low (channel 1)
13 EXI TCINT (channel 1)
14 EXI EXTINT high (channel 1)
15 EXI EXTINT low (channel 2)
16 EXI TCINT (channel 2)
26 HSP
24 VI
21 Serial
22 DVD
23 Reset switch
27 GP Runtime Error

Context saving

When a non-syscall exception occurs, the current state is stored in a struct called OSContext; the struct is 0x2c8 bytes long.

struct OSContext {
	u32 gprs[0x20]; // r0-r31
	u32 cr; // 0x80
	u32 lr; // 0x84
	u32 ctr; // 0x88
	u32 xer; // 0x8c
	u64 fprs[0x20]; // f0-f31
	u32 unknown; // 0x190
	u32 fpscr; // 0x194
	u32 pc; // 0x198
	u32 msr; // 0x19c
	u16 unknown2; // 0x1a0; possibly padding
	u16 state; // 0x1a2; last bit means OSSaveContext was called, second last bit means the GPRs were saved by the exception handler
	u32 unknown3; // 0x1a4
	u32 gqrs[7]; // 0x1a8
	u32 unknown4; // 0x1c4
	u64 pairedSingles[0x20]; // starting at 0x1c8

Most OSContext instances belong to threads, and are at the beginning of the OSThread struct. However, there are also some standalone OSContext instances, such as the one used while waiting for an available thread.


Threads are stored in the OSThread struct.

struct OSThread {
	struct OSContext ctx;
	u16 state; // 0x2c8; 0 = stopped, 1 = inactive, 2 = active, 4 = sleeping, 8 = returned result?
	u16 detached; // 0x2ca; zero = false, nonzero = true
	u32 suspend; // seems to be a balancing counter. 0 = active, 1 = suspended
	u32 priority; // 0x2d0; can range from 0-31
	u32 basePriority; // 0x2d4
	u32 returnValue; // 0x2d8
	struct OSThreadQueue *queue; // 0x2dc
	struct OSThreadLink linkQueue; // 0x2e0
	struct OSThreadQueue queueJoin; // 0x2e8
	struct OSMutexQueue queueMutex; // 0x2f0
	struct OSThreadLink linkActive; // 0x2fc
	void *stackStart; // 0x304
	void *stackEnd; // 0x308
	u32 unknown; // 0x30c
	u32 threadSpecifics[2]; // 0x310

struct OSThreadQueue {
	struct OSThread *head;
	struct OSThread *tail;

struct OSThreadLink {
	struct OSThread *next;
	struct OSThread *prev;

struct OSMutex {
	struct OSThreadQueue waitingQueue;
	struct OSThread *holder;
	u32 timesLocked; // used if a mutex is locked multiple times by the same thread
	struct OSMutex *next;
	struct OSMutex *prev;

struct OSMutexQueue {
	struct OSMutex *waiting; // used for deadlock detection
	struct OSMutex *head;
	struct OSMutex *tail;

struct OSThreadInfo { // fields are sometimes directly accessed
	struct OSThread initialThread;
	struct OSMutexQueue RunQueue[0x20];
	struct OSContext idleCtx;