/*

Hello World v2 for PSP v2.0
(c) 04/09/2005 by abu <x@sunkone.cjb.net>
http://sunkone.cjb.net/psp/

You can use this code freely, but remember credits.

Based on:

  Hello World v1 for PSP v2.0
  (w) 24/09/2005 by Groepaz/Hitmen
  http://www.hitmen-console.org

*/

#include <pspthreadman.h>

#define DUMP_START  0x08400000
#define DUMP_END    0x0A000000


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)
{
	Main();
} 

// 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,
    0x30,0x30,0x30,0xff,0xff,0x30,0x30,0x30,	// 0xff

};

#define CMAX_X 60
#define CMAX_Y 38
#define PIXELSIZE 3				//in short
#define LINESIZE 	512				//in short
#define FRAMESIZE  0xAA000			//in byte

unsigned char *vramtop=(unsigned char *)0x04000000;
unsigned long drawframe,bgcolor=0;

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

// 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<mag; my++)
		{
			vptr=vptr0;
			b=0x80;
			for (cx=0; cx<8; cx++)
			{
				for (mx=0; mx<mag; mx++)
				{
					if ((*cfont&b)!=0)
					{
						if (drawfg) *(unsigned long *)vptr=color;
					} else {
						if (drawbg) *(unsigned long *)vptr=bgcolor;
					}
					vptr+=4; // PIXELSIZE*2;
				}
				b=b>>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 && y<CMAX_Y) {
		PutChar(x*8,y*8,color,bgcolor,*str,1,1,1);
		str++;
		x++;
		if (x>=CMAX_X) {
			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)*2; i++) 
	{
		*(unsigned long *)vptr0=color;
		vptr0+=4;
	}
}


// for printing a 32bit hex --abu

void num2hex(char *dst, int n) {
   int i;
   static char hex[]="0123456789ABCDEF";
   for (i=0; i<8; i++) {
      dst[i]=hex[(n>>((7-i)*4))&15];
   }
}


int sceIoOpen(char *name, int flags, int mode) {
   // function args are readily in registers, so just do syscall, seems to work
   // syscall numbers from PSPInside's syscalls.txt --abu
   // turn gcc optimization off, this must not be inlined
   asm("syscall 0x208f");
}

void sceKernelDelayThread(SceUInt delay) {
   asm("syscall 0x201c");
}

int sceDisplaySetFrameBuf(void *topaddr,int w, int pf, int s) {
   asm("syscall 0x2148");
}

int sceKernelGetThreadmanIdList(enum SceKernelIdListType type, SceUID *readbuf, int readbufsize, int *idcount) {
   asm("syscall 0x2083");
}

int sceKernelReferThreadStatus(SceUID thid, SceKernelThreadInfo *info) {
   asm("syscall 0x2080");
}

int sceKernelGetThreadId() {
   asm("syscall 0x207b");
}

int sceKernelExitDeleteThread(int st) {
   asm("syscall 0x2072");
}



void strcpy(char *dst,char *src) {
   while((*dst++=*src++)) ;
}

int getsp() {
   int sp=&sp;
   return sp;
}

// this is for clean exit. find the libtiff return address on stack
// and calculate what stackpointer was before the overflow.
// 
int fixsp() {
   int *ptr=getsp()+64;
   while(*ptr!=0x9a97ff4) ptr++;
   return ptr-13;
}


int threads[32];
int nthreads=0;
char killtxt[]="killed -------- threads";
char line[60];
int killed=0;

void listThreads() {
   SceKernelThreadInfo ti;
   int i,j;
   nthreads=0;
   i=sceKernelGetThreadmanIdList(SCE_KERNEL_TMID_Thread, threads, sizeof(threads), &nthreads);
   if (i<0) return;
   Print(1,1,0x00ffffff,"ATTR     THREAD NAME");
   for (i=0; i<nthreads; i++) {
      j=sceKernelReferThreadStatus(threads[i], &ti);
      if (j<0) strcpy(line,"?");
      else {
	 num2hex(line,ti.attr);
	 line[8]=' ';
	 ti.name[31]=0; strcpy(line+9,ti.name);
      }
      Print(1,i+2,0xb0b0b0,line);
   }  
   num2hex(killtxt+7,killed); 
   Print(1,i+4,0x00ff00,killtxt);
   sceKernelDelayThread(5000000);
}


// hijacked threads will go here
// 
void killme() {
   killed++;
   asm("syscall 0x2071 \n nop");		// sceKernelExitThread
   while(1) { }
}

// This function replaces syscall instructions in user memory
// with jump instructions. We redirect code flow of other
// threads to our own code.
//
// You could use this to manipulate the syscall parameters
// or return values etc. but in this example we just kill
// the thread to own the screen.

void hijack() {
   int *ptr;
   int jump=0x08000000 | (((int)killme)>>2);       // j addr
   
   for (ptr=DUMP_START; ptr<DUMP_END; ptr++) {
      if (ptr[0]==0x03e00008) {       // jr ra
	 unsigned int sc=ptr[1];
	 if ((sc&0xfc000000)==0) {
	    sc>>=6;
	    if ((sc>=0x201c && sc<=0x201f) || (sc>=0x20ef && sc<=0x2120)) {
	       int *ptr2=(int *)((int)ptr|0x40000000);   // don't cache
	       ptr2[0]=jump;		// j killme
	       ptr2[1]=0x24190000|sc;	// save syscall number
	    }
	 }
      }
   }
}

   

void Main(void)
{
   char err[]="ERROR: --------\n";
   int i;
   
   hijack();
   sceKernelDelayThread(1000);
   Fillvram(0);
   i=sceDisplaySetFrameBuf(vramtop,512,3,0);
   listThreads();
   Fillvram(0);
   
   Print(1,1,0xffffff,"------------");
   Print(1,3,0xffffff,"HELLO WORLD");
   Print(1,5,0xffffff," version 2");
   Print(1,7,0xffffff,"------------");
   Print(1,9,0xffffff,"(c) abu <x@sunkone.cjb.net> http://sunkone.cjb.net/psp/");
   bgcolor=0xffffff;
   Print(57,9,0xff0000,"\xff");
   // the system isn't usable if we've killed the threads, so loop forever
   while(1) { sceKernelDelayThread(10000); }
   
   // otherwise a clean exit could be done like this:   
out:
   if (i<0) {
      num2hex(err+7,i);
      for (i=0; i<2000; i++) {
	 Print(1,2,0xff,err);
	 sceKernelDelayThread(1000);
      }
   }
   
   // pretend that nothing happened
   i=fixsp();
   
   asm("			\n\
        move	$sp,$2		\n\
        j	0x9aaca64	\n\
   ");
   
   return 0;
}
