/* Utils for PSP v2.0 exploit (w) 24/09/2005 by Groepaz/Hitmen additions 28/9/05 by Fanjita http://www.fanjita.org */ #include #include #include #include #include #define USE_MISSING_NIDS 0 #define SCREEN_HEIGHT 272 #define SCREEN_WIDTH 512 typedef unsigned char BOOL; #define TRUE 1 #define FALSE 0 #define NULL 0 typedef unsigned int UINT; typedef void VOID; typedef struct { UINT left; UINT right; UINT top; UINT bottom; } RECT; typedef struct { UINT cx; UINT cy; } SIZE; typedef struct { UINT x; UINT y; } POINT; void Main(void); void _start(void) __attribute__ ((section (".text.start"))); // this is our "crt0". not real, very fake. but enough for now :=P void _start(void) { initial_setup(0x08800000L, 0x01800000L); Main(); while(1){}; // wait forever } void flashscreen(int cola, int colb) { /***************************************************************************/ /* Flash screen 10 times */ /***************************************************************************/ { int i; for (i=0; i<10; i++) { { long *lptr = 0x44000000; while (lptr < 0x44200000) { *lptr++ = cola; } lptr = 0x44000000; while (lptr < 0x44200000) { *lptr++ = colb; } } } } } void memcpy(char *dest, char *src, int size) { while (size--) { *dest++ = *src++; } } // font data const unsigned char font[]={ // much better charset, by eddie! // this is actually the 8x8 neuromancer // vga/ega mode font :) 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x20 0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00, // 0x21 0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00, // 0x22 0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00, // 0x23 0x30,0x7C,0xC0,0x78,0x0C,0xF8,0x30,0x00, // 0x24 0x00,0xC6,0xCC,0x18,0x30,0x66,0xC6,0x00, // 0x25 0x38,0x6C,0x38,0x76,0xDC,0xCC,0x76,0x00, // 0x26 0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00, // 0x27 0x18,0x30,0x60,0x60,0x60,0x30,0x18,0x00, // 0x28 0x60,0x30,0x18,0x18,0x18,0x30,0x60,0x00, // 0x29 0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00, // 0x2A 0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00, // 0x2B 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60, // 0x2C 0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00, // 0x2D 0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00, // 0x2E 0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00, // 0x2F 0x7C,0xC6,0xCE,0xDE,0xF6,0xE6,0x7C,0x00, // 0x30 0x30,0x70,0x30,0x30,0x30,0x30,0xFC,0x00, // 0x31 0x78,0xCC,0x0C,0x38,0x60,0xCC,0xFC,0x00, // 0x32 0x78,0xCC,0x0C,0x38,0x0C,0xCC,0x78,0x00, // 0x33 0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x1E,0x00, // 0x34 0xFC,0xC0,0xF8,0x0C,0x0C,0xCC,0x78,0x00, // 0x35 0x38,0x60,0xC0,0xF8,0xCC,0xCC,0x78,0x00, // 0x36 0xFC,0xCC,0x0C,0x18,0x30,0x30,0x30,0x00, // 0x37 0x78,0xCC,0xCC,0x78,0xCC,0xCC,0x78,0x00, // 0x38 0x78,0xCC,0xCC,0x7C,0x0C,0x18,0x70,0x00, // 0x39 0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x00, // 0x3A 0x00,0x30,0x30,0x00,0x00,0x30,0x30,0x60, // 0x3B 0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x00, // 0x3C 0x00,0x00,0xFC,0x00,0x00,0xFC,0x00,0x00, // 0x3D 0x60,0x30,0x18,0x0C,0x18,0x30,0x60,0x00, // 0x3E 0x78,0xCC,0x0C,0x18,0x30,0x00,0x30,0x00, // 0x3F 0x7C,0xC6,0xDE,0xDE,0xDE,0xC0,0x78,0x00, // 0x40 0x30,0x78,0xCC,0xCC,0xFC,0xCC,0xCC,0x00, // 0x41 0xFC,0x66,0x66,0x7C,0x66,0x66,0xFC,0x00, // 0x42 0x3C,0x66,0xC0,0xC0,0xC0,0x66,0x3C,0x00, // 0x43 0xF8,0x6C,0x66,0x66,0x66,0x6C,0xF8,0x00, // 0x44 0xFE,0x62,0x68,0x78,0x68,0x62,0xFE,0x00, // 0x45 0xFE,0x62,0x68,0x78,0x68,0x60,0xF0,0x00, // 0x46 0x3C,0x66,0xC0,0xC0,0xCE,0x66,0x3E,0x00, // 0x47 0xCC,0xCC,0xCC,0xFC,0xCC,0xCC,0xCC,0x00, // 0x48 0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00, // 0x49 0x1E,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00, // 0x4A 0xE6,0x66,0x6C,0x78,0x6C,0x66,0xE6,0x00, // 0x4B 0xF0,0x60,0x60,0x60,0x62,0x66,0xFE,0x00, // 0x4C 0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0x00, // 0x4D 0xC6,0xE6,0xF6,0xDE,0xCE,0xC6,0xC6,0x00, // 0x4E 0x38,0x6C,0xC6,0xC6,0xC6,0x6C,0x38,0x00, // 0x4F 0xFC,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00, // 0x50 0x78,0xCC,0xCC,0xCC,0xDC,0x78,0x1C,0x00, // 0x51 0xFC,0x66,0x66,0x7C,0x6C,0x66,0xE6,0x00, // 0x52 0x78,0xCC,0xE0,0x70,0x1C,0xCC,0x78,0x00, // 0x53 0xFC,0xB4,0x30,0x30,0x30,0x30,0x78,0x00, // 0x54 0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xFC,0x00, // 0x55 0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00, // 0x56 0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00, // 0x57 0xC6,0xC6,0x6C,0x38,0x38,0x6C,0xC6,0x00, // 0x58 0xCC,0xCC,0xCC,0x78,0x30,0x30,0x78,0x00, // 0x59 0xFE,0xC6,0x8C,0x18,0x32,0x66,0xFE,0x00, // 0x5A 0x78,0x60,0x60,0x60,0x60,0x60,0x78,0x00, // 0x5B 0xC0,0x60,0x30,0x18,0x0C,0x06,0x02,0x00, // 0x5C 0x78,0x18,0x18,0x18,0x18,0x18,0x78,0x00, // 0x5D 0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00, // 0x5E 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF, // 0x5F 0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00, // 0x60 0x00,0x00,0x78,0x0C,0x7C,0xCC,0x76,0x00, // 0x61 0xE0,0x60,0x60,0x7C,0x66,0x66,0xDC,0x00, // 0x62 0x00,0x00,0x78,0xCC,0xC0,0xCC,0x78,0x00, // 0x63 0x1C,0x0C,0x0C,0x7C,0xCC,0xCC,0x76,0x00, // 0x64 0x00,0x00,0x78,0xCC,0xFC,0xC0,0x78,0x00, // 0x65 0x38,0x6C,0x60,0xF0,0x60,0x60,0xF0,0x00, // 0x66 0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0xF8, // 0x67 0xE0,0x60,0x6C,0x76,0x66,0x66,0xE6,0x00, // 0x68 0x30,0x00,0x70,0x30,0x30,0x30,0x78,0x00, // 0x69 0x0C,0x00,0x0C,0x0C,0x0C,0xCC,0xCC,0x78, // 0x6A 0xE0,0x60,0x66,0x6C,0x78,0x6C,0xE6,0x00, // 0x6B 0x70,0x30,0x30,0x30,0x30,0x30,0x78,0x00, // 0x6C 0x00,0x00,0xCC,0xFE,0xFE,0xD6,0xC6,0x00, // 0x6D 0x00,0x00,0xF8,0xCC,0xCC,0xCC,0xCC,0x00, // 0x6E 0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x00, // 0x6F 0x00,0x00,0xDC,0x66,0x66,0x7C,0x60,0xF0, // 0x70 0x00,0x00,0x76,0xCC,0xCC,0x7C,0x0C,0x1E, // 0x71 0x00,0x00,0xDC,0x76,0x66,0x60,0xF0,0x00, // 0x72 0x00,0x00,0x7C,0xC0,0x78,0x0C,0xF8,0x00, // 0x73 0x10,0x30,0x7C,0x30,0x30,0x34,0x18,0x00, // 0x74 0x00,0x00,0xCC,0xCC,0xCC,0xCC,0x76,0x00, // 0x75 0x00,0x00,0xCC,0xCC,0xCC,0x78,0x30,0x00, // 0x76 0x00,0x00,0xC6,0xD6,0xFE,0xFE,0x6C,0x00, // 0x77 0x00,0x00,0xC6,0x6C,0x38,0x6C,0xC6,0x00, // 0x78 0x00,0x00,0xCC,0xCC,0xCC,0x7C,0x0C,0xF8, // 0x79 0x00,0x00,0xFC,0x98,0x30,0x64,0xFC,0x00, // 0x7A 0x1C,0x30,0x30,0xE0,0x30,0x30,0x1C,0x00, // 0x7B 0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x00, // 0x7C 0xE0,0x30,0x30,0x1C,0x30,0x30,0xE0,0x00, // 0x7D 0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00, // 0x7E 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #define CMAX_X 60 #define CMAX_Y 38 #define PIXELSIZE 3 //in short #define LINESIZE 512 //in short #define FRAMESIZE 0xAA000 //in byte #define TEXTCOLOUR 0x00FFFFFF #define BLUE 0x00FF0000 #define RED 0x000000FF #define GREEN 0x0000FF00 unsigned char *vramtop=(unsigned char *)0x04000000; unsigned long drawframe; // get vram address for character position unsigned char *GetVramAddr(unsigned long x,unsigned long y) { return vramtop+(drawframe?FRAMESIZE:0)+x*4+y*LINESIZE*4+0x40000000; } struct timeval { long tv_sec; long tv_usec; }; struct timezone { int tz_minuteswest; int tz_dsttime; }; int sceKernelLibcGettimeofday(struct timeval *tp, struct timezone *tzp) { register int lret asm("$2"); register struct timeval * ltp asm("$4") = tp; register struct timezone * ltzp asm("$5") = tzp; // This number is not accurate, but it doesn't matter because it will be fixed up asm ("syscall 0x2109" : "=r" (lret) : "r" (ltp), "r" (ltzp) ); return(lret); } /*****************************************************************************/ /* A very basic rand() */ /*****************************************************************************/ int rand() { struct timeval tp; struct timezone tz; sceKernelLibcGettimeofday(&tp, &tz); return tp.tv_usec; } // print a single character void PutChar(unsigned long x,unsigned long y,unsigned long color,unsigned long bgcolor,unsigned char ch,char drawfg,char drawbg,char mag) { unsigned char *vptr0; //pointer to vram unsigned char *vptr; //pointer to vram const unsigned char *cfont; //pointer to font unsigned long cx,cy; unsigned long b; char mx,my; cfont=font+ch*8; vptr0=GetVramAddr(x,y); for (cy=0; cy<8; cy++) { for (my=0; my>1; } vptr0+=LINESIZE*4; // 2 } cfont++; } } // print a string void Print(unsigned long x,unsigned long y,unsigned long color,const char *str) { while (*str!=0 && x=CMAX_X) { x=0; y++; } } } // x is in pixels rather than character cells void PrintFine(unsigned long x,unsigned long y,unsigned long color,const char *str) { while (*str!=0 && x<(CMAX_X*8) && y=(CMAX_X*8)) { x=0; y++; } } } // clear video ram void Fillvram(unsigned long color) { unsigned char *vptr0; //pointer to vram unsigned long i; vptr0=GetVramAddr(0,0); for (i=0; i<(FRAMESIZE/4); i++) { *(unsigned long *)vptr0=color; vptr0+=4; } } SceCtrlData gpaddata; int sceCtrlReadBufferPositive(SceCtrlData *pad_data, int count) { register int lret asm("$2"); register SceCtrlData * lpaddata asm("$4") = pad_data; register SceCtrlData * lcount asm("$5") = count; asm __volatile__ ("syscall 0x215F;" : "=r" (lret) : "r" (lpaddata), "r" (lcount) ); return(lret); } int sceCtrlSetSamplingCycle(int cycle) { register int lret asm("$2"); register int lcycle asm("$4") = cycle; asm __volatile__ ("syscall 0x2150;" : // no output regs : "r" (lcycle) ); return(lret); } int sceCtrlSetSamplingMode(int mode) { register int lret asm("$2"); register int lmode asm("$4") = mode; asm __volatile__ ("syscall 0x215D;" : "=r" (lret) : "r" (lmode) ); return(lret); } int sceDisplayWaitVblank(void) { register int lret asm("$2"); asm __volatile__ ("syscall 0x2154" : "=r" (lret)); return(lret); } int sceDisplayWaitVblankStart(void) { register int lret asm("$2"); asm __volatile__ ("syscall 0x2156" : "=r" (lret)); return(lret); } void WriteNibble(int x, int y, unsigned char val) { if (val > 9) { val = 'A' + val - 10; } else { val = '0' + val; } PutChar(x*8,y*8,TEXTCOLOUR,0,val,1,1,1); } void WriteByte(int x, int y, unsigned char val) { char lchr; lchr = (val & 0xF0) >> 4; WriteNibble(x,y,lchr); lchr = (val & 0xF); WriteNibble(x+1,y,lchr); } void WriteDword(int x, int y, unsigned long val) { WriteByte(x,y,(val & 0xFF000000L) >> 24); WriteByte(x+2,y,(val & 0xFF0000L) >> 16); WriteByte(x+4,y,(val & 0xFF00L) >> 8); WriteByte(x+6,y,(val & 0xFFL)); } void WriteNibbleDummy(int x, int y, unsigned char val) { if (val > 9) { val = 'A' + val - 10; } else { val = '0' + val; } PutChar(x*8,y*8,0,0,val,1,1,1); } void WriteByteDummy(int x, int y, unsigned char val) { char lchr; lchr = (val & 0xF0) >> 4; WriteNibbleDummy(x,y,lchr); lchr = (val & 0xF); WriteNibbleDummy(x+1,y,lchr); } void WriteDwordDummy(int x, int y, unsigned long val) { WriteByteDummy(x,y,(val & 0xFF000000L) >> 24); WriteByteDummy(x+2,y,(val & 0xFF0000L) >> 16); WriteByteDummy(x+4,y,(val & 0xFF00L) >> 8); WriteByteDummy(x+6,y,(val & 0xFFL)); } int sceDisplaySetMode(int mode, int width, int height) { register int lret asm("$2"); register int lmode asm("$4") = mode; register int lwidth asm("$5") = width; register int lheight asm("$6") = height; asm __volatile__ ("syscall 0x2146;" : "=r" (lret) : "r" (lmode), "r" (lwidth), "r" (lheight) ); return(lret); } void sceDisplaySetFrameBuf(void *topaddr, int bufferwidth, int pixelformat, int sync) { register void * ltop asm("$4") = topaddr; register int lwidth asm("$5") = bufferwidth; register int lformat asm("$6") = pixelformat; register int lsync asm("$7") = sync; asm __volatile__ ("syscall 0x214C;" : // no output regs : "r" (ltop), "r" (lwidth), "r" (lformat), "r" (lsync) ); } void FillRect(RECT *xirect, unsigned long xicolour) { unsigned long *vptrl; unsigned char *vptrc; int y; for (y = xirect->top; y < xirect->bottom; y++) { int x = xirect->left; vptrc = GetVramAddr(x,y); vptrl = (unsigned long*)vptrc; while (x < xirect->right) { *vptrl++ = xicolour; x++; } } } POINT gcursor; void MoveToEx(short x, short y) { gcursor.x = x; gcursor.y = y; } void LineTo(short x, short y) { // XXX to do } void changeBuffer() { sceDisplayWaitVblank(); sceDisplaySetFrameBuf( (void*)GetVramAddr(0,0), 512, PSP_DISPLAY_PIXEL_FORMAT_8888 ,0); drawframe=(drawframe?0:1); } void DebugValue(int y, char * label, unsigned long val) { Print(0,y,TEXTCOLOUR,label); WriteDword(10,y,val); } void WriteDecimal(int x, int y, unsigned long val) { unsigned long divisor = 10000000L; unsigned char nibble; val = val % 100000000L; while (divisor > 0) { nibble = val / divisor; WriteNibble(x, y, nibble); val = val - (nibble * divisor); x++; divisor /= 10; } } void initScreenAndCtrl() { drawframe = 0; sceDisplaySetMode(0,SCREEN_WIDTH,SCREEN_HEIGHT); sceDisplaySetFrameBuf( (void*)vramtop, 512, PSP_DISPLAY_PIXEL_FORMAT_8888 ,1); Fillvram(0x00000000); drawframe = 1; Fillvram(0x00000000); sceCtrlSetSamplingCycle(0); sceCtrlSetSamplingMode(1); } int strlen(char * xistr) { int i = 0; while (*xistr) { i++; } return(i); } #define O_RDONLY 1 #define O_WRONLY 2 #define O_RDWR 3 #define O_CREAT 0x200 #define O_TRUNC 0x400 #define O_APPEND 0x100 SceUID sceIoOpen(const char *file, int flags, int mode) { register const char * lfile asm ("$4") = file; register int lflags asm ("$5") = flags; register int lmode asm ("$6") = mode; register SceUID lret asm ("$2"); asm __volatile__ ( "syscall 0x208F;" : "=r" (lret) : "r" (lfile), "r" (lflags), "r" (lmode) ); return lret; } int sceIoClose(SceUID fd) { register SceUID lfd asm ("$4") = fd; register int lret asm ("$2"); asm __volatile__ ( "syscall 0x208D;" : "=r" (lret) : "r" (lfd) ); } int sceIoRead(int fd,char *buf,int sz) { register int lfd asm ("$4") = fd; register char * ldata asm ("$5") = buf; register int lcount asm ("$6") = sz; register int lret asm ("$2"); asm __volatile__ ( "syscall 0x2091;" : "=r" (lret) : "r" (lfd), "r" (ldata), "r" (lcount) ); return lret; } int sceIoWrite(SceUID fd, const void *data, SceSize size) { register SceUID lfd asm ("$4") = fd; register const void * ldata asm ("$5") = data; register SceSize lcount asm ("$6") = size; register int lret asm ("$2"); asm __volatile__ ( "syscall 0x2093;" : "=r" (lret) : "r" (lfd), "r" (ldata), "r" (lcount) ); return lret; } int sceKernelExitGame() { asm("syscall 0x20F2"); } int sceKernelTerminateDeleteThread(SceUID thid) { register int lret asm("$2"); register int lthid asm("$4") = thid; asm ("syscall 0x2074;" : "=r" (lret) : "r" (lthid) ); return(lret); } int sceKernelDeleteCallback(SceUID cbid) { register int lret asm("$2"); register int lthid asm("$4") = cbid; asm ("syscall 0x200E;" : "=r" (lret) : "r" (lthid) ); return(lret); } #if USE_MISSING_NIDS==1 int sceKernelReferCallbackStatus(SceUID cb, SceKernelCallbackInfo *info) { register int lret asm("$2"); register int lthid asm("$4") = cb; register int linfo asm("$5") = info; asm("syscall 0x2013" : "=r" (lret) : "r" (lthid), "r" (linfo) ); return(lret); } int sceKernelReferThreadStatus(int thid, SceKernelThreadInfo *info) { register int lret asm("$2"); register int lthid asm("$4") = thid; register int linfo asm("$5") = info; asm("syscall 0x2080" : "=r" (lret) : "r" (lthid), "r" (linfo) ); return(lret); } int sceKernelCancelCallback(SceUID cbid) { register int lret asm("$2"); register int lthid asm("$4") = cbid; asm ("syscall 0x2010" : "=r" (lret) : "r" (lthid) ); return(lret); } int sceKernelDeleteEventFlag(SceUID vplid) { register int lret asm("$2"); register int lthid asm("$4") = vplid; asm ("syscall 0x2029" : "=r" (lret) : "r" (lthid) ); return(lret); } int sceKernelIcacheInvalidateAll() { asm("syscall 0x20cd"); } SceSize sceKernelTotalFreeMemSize(void) { register SceSize lreturn asm ("$2") = 0; asm __volatile__ ("syscall 0x20E0;" : "=r" (lreturn) ); return(lreturn); } int sceKernelDisableSubIntr(SceUID intno, SceUID no) { register int lret asm("$2"); register int lfplid asm("$4") = intno; register void* linfo asm("$5") = no; asm("syscall 0x2003" : "=r" (lret) : "r" (lfplid), "r" (linfo) ); return(lret); } // 0x644395e2 int sceKernelGetModuleIdList(SceUID *readbuf, int readbufsize, int *idcount) { register int lret asm("$2"); register SceUID *lbuf asm("$4") = readbuf; register int lsize asm("$5") = readbufsize; register int* lidcount asm("$6") = idcount; asm __volatile__ ("syscall 0x20DB" : "=r" (lret) : "r" (lbuf), "r" (lsize), "r" (lidcount) ); return(lret); } // 0x748cbed9 int sceKernelQueryModuleInfo(SceUID modid, SceKernelModuleInfo *info) { register int lret asm("$2"); register SceUID lid asm("$4") = modid; register void* linfo asm("$5") = info; asm __volatile__ ("syscall 0x20DC" : "=r" (lret) : "r" (lid), "r" (linfo) ); return(lret); } #endif void sceKernelDelayThread(SceUInt delay) { register unsigned long lsecs asm("$4") = delay; asm __volatile__ ("syscall 0x201c;" : : "r" (lsecs) ); } int sceKernelGetThreadId() { register int lret asm("$2"); asm("syscall 0x207B" : "=r" (lret)); return(lret); } #if USE_MISSING_NIDS==1 int sceKernelGetThreadmanIdList(enum SceKernelIdListType type, SceUID *readbuf, int readbufsize, int *idcount) { register int ltype asm("$4") = type; register int * lbuf asm("$5") = readbuf; register int lsize asm("$6") = readbufsize; register int *lcount asm("$7") = idcount; register int lret asm("$2"); asm("syscall 0x2083" : "=r" (lret) : "r" (ltype), "r" (lbuf), "r" (lsize), "r" (lcount) ); return(lret); } #endif SceUID sceKernelAllocPartitionMemory(SceUID partitionid, const char *name, int type, SceSize size, void *addr) { register SceUID lreturn asm ("$2"); register SceUID lpart asm ("$4") = partitionid; register const char * lname asm ("$5") = name; register int ltype asm ("$6") = type; register SceSize lsize asm ("$7") = size; register void* laddr asm("$8") = addr; asm __volatile__ ("syscall 0x2169;" // fake : exitgame : "=r" (lreturn) : "r" (lpart), "r" (lname), "r" (ltype), "r" (lsize), "r" (laddr) ); return(lreturn); } int sceKernelFreePartitionMemory(SceUID blockid) { register int lreturn asm ("$2"); register SceUID lblockid asm ("$4") = blockid; asm __volatile__ ("syscall 0x20E2;" : "=r" (lreturn) : "r" (lblockid) ); return(lreturn); } void * sceKernelGetBlockHeadAddr(SceUID blockid) { register void *lreturn asm ("$2"); register SceUID lblockid asm ("$4") = blockid; asm __volatile__ ("syscall 0x20e3;" : "=r" (lreturn) : "r" (lblockid) ); return(lreturn); } int sceKernelCreateThread(const char *name, SceKernelThreadEntry entry, int initPriority, int stackSize, SceUInt attr, SceKernelThreadOptParam *option) { asm("syscall 0x206d"); } int sceKernelStartThread(SceUID thid, SceSize args, void *argp) { asm("syscall 0x206f"); } SceSize sceKernelMaxFreeMemSize(void) { register SceSize lreturn asm ("$2") = 0; asm __volatile__ ("syscall 0x20DF;" : "=r" (lreturn) ); return(lreturn); } int sceKernelDcacheWritebackInvalidateAll() { asm("syscall 0x20c7"); } int sceKernelDeleteFpl(SceUID fplid) { register int lret asm("$2"); register int lthid asm("$4") = fplid; asm ("syscall 0x204C" : "=r" (lret) : "r" (lthid) ); return(lret); } int sceKernelDeleteSema(SceUID vplid) { register int lret asm("$2"); register int lthid asm("$4") = vplid; asm ("syscall 0x2021" : "=r" (lret) : "r" (lthid) ); return(lret); } int sceKernelReleaseSubIntrHandler(SceUID intno, SceUID no) { register int lret asm("$2"); register int lfplid asm("$4") = intno; register void* linfo asm("$5") = no; asm("syscall 0x2001" : "=r" (lret) : "r" (lfplid), "r" (linfo) ); return(lret); } // sceKernelStopModule 0xd1ff982a int sceKernelStopModule( SceUID modid, SceSize argsize, void* argp, int* status, SceKernelSMOption* option) { register SceUID lreturn asm ("$2"); register SceUID lmodid asm ("$4") = modid; register SceSize largsize asm ("$5") = argsize; register void* largp asm("$6") = argp; register int* lstatus asm("$7") = status; register SceKernelSMOption* loption asm("$8") = option; asm __volatile__ ("syscall 0x20D7" : "=r" (lreturn) : "r" (lmodid), "r" (largsize), "r" (largp), "r" (lstatus), "r" (loption) ); return(lreturn); } // sceKernelUnloadModule 0x2e0911aa int sceKernelUnloadModule( SceUID modid ) { register int lret asm("$2"); register int lthid asm("$4") = modid; asm ("syscall 0x20D8" : "=r" (lret) : "r" (lthid) ); return(lret); } int sceKernelSelfStopUnloadModule (int modid, SceSize argsize, void *argp) { register SceUID lreturn asm ("$2"); register SceUID lmodid asm ("$4") = modid; register SceSize largsize asm ("$5") = argsize; register void* largp asm("$6") = argp; asm __volatile__ ("syscall 0x20D9" : "=r" (lreturn) : "r" (lmodid), "r" (largsize), "r" (largp) ); return(lreturn); } int sceKernelVolatileMemUnlock(int unknown) { register int lret asm("$2"); register int lunknown asm("$4") = unknown; asm __volatile__ ("syscall 0x20EF" : "=r" (lret) : "r" (lunknown) ); return(lret); } int sceUmdUnRegisterUMDCallBack() { asm("syscall 0x21BF"); } int scePowerUnregisterCallback() { asm("syscall 0x219B"); } int sceGeUnsetCallback() { asm("syscall 0x2107"); } int sceUtilitySavedataShutdownStart() { register int lret asm("$2"); asm ("syscall 0x2201" : "=r" (lret) ); return(lret); } int sceUtilitySavedataGetStatus() { register int lret asm("$2"); asm ("syscall 0x2203" : "=r" (lret) ); return(lret); } int sceUtilitySavedataUpdate( SceUID modid ) { register int lret asm("$2"); register int lthid asm("$4") = modid; asm ("syscall 0x2202" : "=r" (lret) : "r" (lthid) ); return(lret); } int sceAudioChRelease( SceUID modid ) { register int lret asm("$2"); register int lthid asm("$4") = modid; asm ("syscall 0x2135" : "=r" (lret) : "r" (lthid) ); return(lret); } /*****************************************************************************/ /* NID resolution starts here */ /*****************************************************************************/ /* typedef struct { unsigned long l1; // unknown 0xd632acdb unsigned long l2; // unknown 0xf01d73a7 unsigned long startAddress; // address of _start unsigned long moduleInfoAddr; // address of sceModuleInfo struct } SceResidentData; */ #define OFFSET_MODULE_INFO_ADDR 0x1C // 28 bytes /* typedef struct { unsigned char c1, c2, c3, c4; char name[28]; unsigned long gp; // ptr to somewhere after executable unsigned long libEnt; // ptr to .lib.ent section unsigned long libEntBtm; // ptr to end of .lib.ent section unsigned long libStub; // ptr to .lib.stub section unsigned long libStubBtm; // ptr to end of .lib.stub section } __attribute__((packed)) SceModuleInfo; */ #define OFFSET_LIB_ENT_TOP_ADDR 0x2C // 44 bytes #define OFFSET_LIB_ENT_BOTTOM_ADDR 0x30 // 48 bytes /* typedef struct { const char *libname; // Library name. unsigned int flags; // Flags. unsigned char ent_len; // Number of DWORDs in this entry. The size of the entry is ent_len * 4. unsigned char var_ent_count; // Number of variable entries following function entries. unsigned short func_ent_count; // Number of function entries. unsigned int lib_loc // I've added this, havn't found doc on it - Ditlew unsigned int func_loc // I've added this, havn't found doc on it - Ditlew } SceLibEntData; */ #define OFFSET_FUNC_COUNT 0x0A // 10 bytes #define OFFSET_LIB_LOC_ADDR 0x0C // 12 bytes #define OFFSET_FUNC_LOC_ADDR 0x10 // 16 bytes typedef struct { unsigned int NID; unsigned int pLoc; unsigned char *pLibName; unsigned int syscall; } FUNCTIONS_TABLE; #if USE_MISSING_NIDS==1 typedef struct { unsigned int NID; unsigned int pLoc; unsigned int referenceNID; signed int offsetFromReference20; signed int offsetFromReference25; signed int offsetFromReference26; } MISSING_FUNCTIONS_TABLE; #endif int gDetectedFirmware; // 200, 250, 260 unsigned char IoFileMgrForUser[] = "IoFileMgrForUser"; unsigned char Threadman[] = "ThreadManForUser"; unsigned char sceDisplay[] = "sceDisplay"; unsigned char sceCtrl[] = "sceCtrl"; unsigned char SysMem[] = "SysMemUserForUser"; unsigned char ge[] = "sceGe_user"; unsigned char UtilsForUser[] = "UtilsForUser"; unsigned char InterruptManager[] = "InterruptManager"; unsigned char ModuleMgrForUser[] = "ModuleMgrForUser"; unsigned char SuspendForUser[] = "sceSuspendForUser"; unsigned char UMDForUser[] = "sceUmdUser"; unsigned char Power[] = "scePower"; unsigned char sceAudio[] = "sceAudio"; unsigned char sceUtility[] = "sceUtility"; unsigned char LoadExecForUser[] = "LoadExecForUser"; #if USE_MISSING_NIDS==1 MISSING_FUNCTIONS_TABLE missing_functions[] = { { 0x94416130, (unsigned int)&sceKernelGetThreadmanIdList, 0x293b45b8, 8, 8, 0 }, { 0x17c1684e, (unsigned int)&sceKernelReferThreadStatus, 0x293b45b8, 5, 5, 0 }, { 0xba4051d6, (unsigned int)&sceKernelCancelCallback, 0x293b45b8, -107, -107, 0 }, { 0x730ed8bc, (unsigned int)&sceKernelReferCallbackStatus, 0x293b45b8, -104, -104, 0 }, { 0xef9e4c70, (unsigned int)&sceKernelDeleteEventFlag, 0x293b45b8, -82, -82, 0 }, { 0x920f104a, (unsigned int)&sceKernelIcacheInvalidateAll, 0xb435dec5, 6, 6, 0 }, { 0xf919f628, (unsigned int)&sceKernelTotalFreeMemSize, 0x237dbd4f, -1, -8, 0 }, { 0x8a389411, (unsigned int)&sceKernelDisableSubIntr, 0xd61e6961, 2, 2, 0 }, { 0x748cbed9, (unsigned int)&sceKernelQueryModuleInfo, 0x2e0911aa, 4, 4, 0 }, { 0x644395e2, (unsigned int)&sceKernelGetModuleIdList, 0x2e0911aa, 3, 3, 0 }, { 0, NULL, 0, 0 } // terminator }; #endif /*****************************************************************************/ /* You can set pLoc to 0 to just retrieve the syscall, but not update the */ /* code. */ /*****************************************************************************/ FUNCTIONS_TABLE functions[] = { { 0x109f50bc, (unsigned int)&sceIoOpen, &IoFileMgrForUser, 0 }, { 0x810c4bc3, (unsigned int)&sceIoClose, &IoFileMgrForUser, 0 }, { 0x6a638d83, (unsigned int)&sceIoRead, &IoFileMgrForUser, 0 }, { 0x42ec03ac, (unsigned int)&sceIoWrite, &IoFileMgrForUser, 0 }, { 0x2e0911aa, (unsigned int)&sceKernelUnloadModule, &ModuleMgrForUser, 0 }, { 0xd1ff982a, (unsigned int)&sceKernelStopModule, &ModuleMgrForUser, 0 }, { 0xd675ebb8, (unsigned int)&sceKernelSelfStopUnloadModule, &ModuleMgrForUser, 0 }, { 0x237dbd4f, (unsigned int)&sceKernelAllocPartitionMemory, &SysMem, 0 }, { 0xb6d61d02, (unsigned int)&sceKernelFreePartitionMemory, &SysMem, 0 }, { 0x9D9A5BA1, (unsigned int)&sceKernelGetBlockHeadAddr, &SysMem, 0 }, { 0xa291f107, (unsigned int)&sceKernelMaxFreeMemSize, &SysMem, 0 }, { 0x383f7bcc, (unsigned int)&sceKernelTerminateDeleteThread, &Threadman, 0 }, { 0x293b45b8, (unsigned int)&sceKernelGetThreadId, &Threadman, 0 }, { 0x446D8DE6, (unsigned int)&sceKernelCreateThread, &Threadman, 0 }, { 0xF475845D, (unsigned int)&sceKernelStartThread, &Threadman, 0 }, { 0xceadeb47, (unsigned int)&sceKernelDelayThread, &Threadman, 0 }, { 0xedba5844, (unsigned int)&sceKernelDeleteCallback, &Threadman, 0 }, { 0xed1410e0, (unsigned int)&sceKernelDeleteFpl, &Threadman, 0 }, { 0x28b6489c, (unsigned int)&sceKernelDeleteSema, &Threadman, 0 }, { 0xd61e6961, (unsigned int)&sceKernelReleaseSubIntrHandler,&InterruptManager, 0 }, { 0xca04a2b9, (unsigned int)0, &InterruptManager, 0 }, { 0xfb8e22ec, (unsigned int)0, &InterruptManager, 0 }, { 0xb435dec5, (unsigned int)&sceKernelDcacheWritebackInvalidateAll, &UtilsForUser, 0 }, { 0x71ec4271, (unsigned int)&sceKernelLibcGettimeofday, &UtilsForUser, 0 }, { 0xa569e425, (unsigned int)&sceKernelVolatileMemUnlock, &SuspendForUser, 0 }, { 0xBD2BDE07, (unsigned int)&sceUmdUnRegisterUMDCallBack, &UMDForUser, 0 }, { 0xDFA8BAF8, (unsigned int)&scePowerUnregisterCallback, &Power, 0 }, { 0x05DB22CE, (unsigned int)&sceGeUnsetCallback, &ge, 0 }, { 0x9790B33C, (unsigned int)&sceUtilitySavedataShutdownStart, &sceUtility, 0 }, { 0xd4b95ffb, (unsigned int)&sceUtilitySavedataUpdate, &sceUtility, 0 }, { 0x8874dbe0, (unsigned int)&sceUtilitySavedataGetStatus, &sceUtility, 0 }, { 0x6a2774f3, (unsigned int)&sceCtrlSetSamplingCycle, &sceCtrl, 0 }, { 0x1f4011e6, (unsigned int)&sceCtrlSetSamplingMode, &sceCtrl, 0 }, { 0x1f803938, (unsigned int)&sceCtrlReadBufferPositive, &sceCtrl, 0 }, { 0x984c27e7, (unsigned int)&sceDisplayWaitVblankStart, &sceDisplay, 0 }, { 0x0e20f177, (unsigned int)&sceDisplaySetMode, &sceDisplay, 0 }, { 0x289d82fe, (unsigned int)&sceDisplaySetFrameBuf, &sceDisplay, 0 }, { 0x6fc46853, (unsigned int)&sceAudioChRelease, &sceAudio, 0 }, { 0x05572a5f, (unsigned int)&sceKernelExitGame, &LoadExecForUser, 0 }, { 0x00000000, NULL, NULL, 0 } // list terminator }; // This is how 20 first bytes of the GTA .rodata.sceResident looks like - Ditlew unsigned char hash_values[0x14] = { 0xDB, 0xAC, 0x32, 0xD6, // module_start (little-endian) - Ditlew 0x3C, 0x59, 0xE8, 0xCE, // module_stop (little-endian) - Ditlew 0xA7, 0x73, 0x1D, 0xF0, // module_info (little-endian) - Ditlew 0x6C, 0x27, 0x7C, 0x0F, 0x97, 0xC6, 0x0C, 0xCF }; unsigned int find_gta_sceResident(unsigned char *data, unsigned int length) { unsigned int i, j, found = 0; // find the gta .rodata.sceResident location for (i = 0, j = 0; i < length; i++) { // check a byte if (*(unsigned char *)(data + i) == hash_values[j]) { // initialize pointer to beginning if (found == 0) found = i; // increase pointer in hash_values if (++j == 0x14) return found; } else { // not found j = found = 0; } } return 0; } int numfailed = 0; int failednids[50]; int findKnownSyscall(unsigned long xiNID) { int i; int lret = 0; for (i=0; functions[i].NID; i++) { if (functions[i].NID == xiNID) { lret = functions[i].syscall; break; } } return(lret); } #define USER_PARTITION_START 0x08800000 #define USER_PARTITION_LENGTH 0x01800000 void findNIDs(unsigned char *data, unsigned int length, unsigned int lib_stub_top, unsigned int lib_stub_bottom) { unsigned short int num_funcs; unsigned int i, j, k, lib_loc, name_loc, func_loc, syscall_opcode; int lfound; // process all functions for (i = 0; functions[i].NID; i++) { // process all libraries // 20 bytes (0x14) used on each library - Ditlew for (j = lib_stub_top; j < lib_stub_bottom; j += 0x14) { // check if this is the one we want name_loc = *(unsigned int *)&data[j] - USER_PARTITION_START; if (!strcmp((unsigned char *)&data[name_loc], functions[i].pLibName)) { lfound = 0; // process all NIDs num_funcs = *(unsigned short int *)(&data[j + OFFSET_FUNC_COUNT]); lib_loc = *(unsigned int *) (&data[j + OFFSET_LIB_LOC_ADDR ]) - USER_PARTITION_START; func_loc = *(unsigned int *) (&data[j + OFFSET_FUNC_LOC_ADDR]) - USER_PARTITION_START; for (k = 0; k < num_funcs; k++) { syscall_opcode = 0; // check if this is the one we want if (*(unsigned int *)(&data[lib_loc + (k * 0x04)]) == functions[i].NID) { // patch the syscall to what it should be syscall_opcode = *(unsigned int *)(&data[func_loc + (k * 0x08) + 0x04]); functions[i].syscall = syscall_opcode >> 6; /*****************************************************************/ /* Only actually modify the code if pLoc is non-null */ /*****************************************************************/ if (functions[i].pLoc) { // force the address to be uncached functions[i].pLoc |= 0x40000000; // find the syscall opcode, and replace it { int l; unsigned int opcode; for (l=0; l<20; l++) { opcode = ((unsigned int *)(functions[i].pLoc))[l]; if ((opcode & 0xFF00000FL) == 0x0000000CL) { ((unsigned int *)(functions[i].pLoc))[l] = syscall_opcode; lfound = 1; break; } } } } else { lfound = 1; } } } if (!lfound) { failednids[numfailed++] = functions[i].NID; } break; } } } /***************************************************************************/ /* Decide which firmware version we're on, based on known NIDs */ /***************************************************************************/ if (findKnownSyscall(0x293b45b8L) == 0x207b) { gDetectedFirmware = 200; } else if ((findKnownSyscall(0xfb8e22ecL) - findKnownSyscall(0xca04a2b9)) == 2) { gDetectedFirmware = 250; } else { gDetectedFirmware = 260; } #if USE_MISSING_NIDS==1 /***************************************************************************/ /* Now fix up the ones that we have to do by inference */ /***************************************************************************/ for (i = 0; missing_functions[i].NID; i++) { unsigned int syscall = findKnownSyscall(missing_functions[i].referenceNID); unsigned int syscall_opcode; lfound = 0; switch (gDetectedFirmware) { case 200: syscall += missing_functions[i].offsetFromReference20; break; case 250: syscall += missing_functions[i].offsetFromReference25; break; case 260: syscall += missing_functions[i].offsetFromReference26; break; } syscall_opcode = (syscall << 6) | 0x0c; missing_functions[i].pLoc |= 0x40000000; // find the syscall opcode, and replace it { int l; unsigned int opcode; for (l=0; l<20; l++) { opcode = ((unsigned int *)(missing_functions[i].pLoc))[l]; if ((opcode & 0xFF00000FL) == 0x0000000CL) { ((unsigned int *)(missing_functions[i].pLoc))[l] = syscall_opcode; lfound = 1; break; } } } if (!lfound) { failednids[numfailed++] = missing_functions[i].NID; } } #endif } void initial_setup(unsigned char *data, unsigned long length) { unsigned int sceRes, module_info, lib_ent_top, lib_ent_bottom; // find sceResident sceRes = find_gta_sceResident(data, length); if (sceRes > 0) { // setup the necessary locations module_info = *(unsigned int *)(&data[sceRes] + OFFSET_MODULE_INFO_ADDR ) - USER_PARTITION_START; lib_ent_top = *(unsigned int *)(&data[module_info + OFFSET_LIB_ENT_TOP_ADDR ]) - USER_PARTITION_START; lib_ent_bottom = *(unsigned int *)(&data[module_info + OFFSET_LIB_ENT_BOTTOM_ADDR]) - USER_PARTITION_START; // start finding the NID's findNIDs(data, length, lib_ent_top, lib_ent_bottom); } }