Rom Information
Updates:
04 Apr 1997 - Replaced some sys_xx_yy by their names. - Added some copy protection comments doExec (bfc0d570). - Corrected some addresses (some a001xxxx are in fact a000xxxx). - Change some numeric variables (a000b9xx) to names (event_cd_xxxxx). 08 Jul 1997 - Changed Rectangle() - 0xbfc03d80 -> GPU_dw - Added 0xbfc04610|InitIntr() - Added 0xbfc04678|InitEvent() - Changed ClearWorkArea to SysInitKMem - Changed OpenAllEvents to OpenCDEvents - Added 0xbfc0d4cc|EnableIORedirection() - Added black cd check related routines: bfc0d600/d640/d664/d72c 16 Oct 1997 - Changed SetGPU_status to SendGPU - Changed *GPU_status to *gp1 - Changed H0x1f801810 to gp0 - Changed H0x1f80180[0123] to reg[0123] - Changed _0x1f801014 to *spu_delay - Changed _0x1f801018 to *dv5_delay - Changed _0x1f801020 to *com_delay - Changed _0x1f801060, *H0x1f801060 to *ram_size - Changed H0x1f801070 to *i_reg 22 Oct 1997 - Added some nice comments on ColorBars()
/* 0xbfc00000 */ start() { _0x1f801010 = 0x0013243f; *ram_size = 0x00000b88; jmp_part0(); } /* 0xbfc00150 */ part0() { *com_delay = 0x00031125; _0x1f801000 = 0x1f000000; _0x1f801004 = 0x1f002000; _0x1f801008 = 0x0013243f; *spu_delay = 0x200931e1; *dv5_delay = 0x00020843; _0x1f80100c = 0x00003022; _0x1f80101c = 0x00070777; clear_all_registers(); /* inline */ _0xfffe0130 = 0x00000804; /* Flushing Cache begin */ /* details deleted */ /* Flushing Cache end */ tmp = _0xa0000000; tmp = _0x00000000; tmp = _0x00000000; tmp = _0x00000000; tmp = _0x00000000; tmp = _0x00000000; tmp = _0x00000000; tmp = _0x00000000; _0xfffe0130 = 0x0001e988; C0.DCIC = 0; C0.BPC = 0; C0.BDA = 0; C0.TAR = 0; C0.BDAM = 0; C0.BPCM = 0; C0.SR = 0; C0.CAUSE = 0; for (tmp = 0xa0009000 ; tmp != 0xa000c160 ; tmp++) *tmp=0; _stk = 0x801fff00; _gp_ = 0xa0010ff0; _fp_ = _stk; *ram_size = 0x00000b88; _0x00000060=2; _0x00000064=0; _0x00000068=0xff; zero_stuff(); jump_part2(); } SysInitKMem() /* 0xbfc00420 */ { long count , *src , *dst; src = 0xbfc10000; dst = 0xa0000500; for (count = 0x8fb0 ; count != 0 ; count -= 4) *dst++ = *src++; jmp_0xa0000500(); } /* 0xbfc00460 */ ColorBars() { SendGPU(0); /* Some kind of reset ? */ Clear_(); SendGPU(0x03000000); /* Display Mask (enable display) */ Clear_(); SendGPU(0x06c60260); /* Screen horizontal start/end */ Clear_(); SendGPU(0x07040010); /* Screen vertical start/end */ Clear_(); GPU_cw(0xe1000400); /* Draw on display area */ Clear_(); GPU_cw(0xe3000000); /* Draw Area x, y */ Clear_(); GPU_cw(0xe407ffff); /* Draw Area w, h */ Clear_(); GPU_cw(0xe5000000); /* Draw Offset */ Clear_(); SendGPU(0x08000000); /* Display mode, 256x240/NTSC/noninterlaced */ Clear_(); SendGPU(0x08000000); /* Display mode, 256x240/NTSC/noninterlaced */ Clear_(); DrawBackground(); SendGPU(0x08000000); /* Display mode, 256x240/NTSC/noninterlaced */ Clear_(); DrawBackground(); Rectangle( 0, 0, 32, 241, 255, 255, 255); Rectangle( 32, 0, 32, 241, 255, 255, 0); Rectangle( 64, 0, 32, 241, 0, 255, 255); Rectangle( 96, 0, 32, 241, 0, 255, 0); Rectangle(128, 0, 32, 241, 255, 0, 255); Rectangle(160, 0, 32, 241, 255, 0, 0); Rectangle(192, 0, 32, 241, 0, 0, 255); Rectangle(224, 0, 32, 241, 0, 0, 0); return 0; } /* 0xbfc00778 */ DrawBackground() { Rectangle( 0 , 0 , 513 , 257 , 0 , 0 , 0); Rectangle( 0 , 256 , 513 , 257 , 0 , 0 , 0); Rectangle(512 , 0 , 513 , 257 , 0 , 0 , 0); Rectangle(512 , 256 , 513 , 257 , 0 , 0 , 0); } /* 0xbfc00810 */ Rectangle(int x , int y , int w , int h , int R , int G , int B) { long local[5]; local[0] = ((B << 16) | 0x28000000) | (G << 8) | (R); local[1] = (y << 16) | (x); local[2] = (y << 16) | (x + w); local[3] = ((y + h) << 16) | (x); local[4] = ((y + h) << 16) | (x + w); GPU_cwb(local , 5); } ParseSetupFile(char *buf,TCBEV *a,char *boot) { long tmp,*z; z=a; for (tmp=0 ; tmp !=3 ; ++tmp) { *z++=0; } *boot="\0"; _0x00000180=(char)0; GetValue(buf , &a->Tcb , "TCB"); GetValue(buf , &a->Event , "EVENT"); GetValue(buf , &a->Stack , "STACK"); GetString(buf , boot , 384 , "BOOT"); } __trace(char value) { _1f802041 = value; Clear0XA001B068(); } /* sys_a0_42 0xbfc03a18 */ int Load(char *name,struct EXEC *header) { int fd; if ((fd = open(name,1)) <0) { return 0; } if (ReadExeHeader(fd , header)="=" 0) { close(fd); return 0; } read(fd , header->t_addr , header->t_size); close(fd); FlushCache(); return 1; } /* 0xbfc03aa4 */ LoadExec(char *name , int argc , char **argv) { char *src,*dst; char tmp[32]; src = name; dst = tmp; while (*src && *src != ':') { *dst++ = *src++; } while (*dst++ = toupper(*src++)) ; dst = tmp; while (*dst && *dst != ';') { dst++; } if (!*dst) { strcat(tmp,";1"); } _0xa0009144 = _0xa000b890; _0xa0009148 = _0xa000b894; ExitCriticalSection(); if (Load(tmp , ExeHeader) == 1) { _0xa000b890 = argc; _0xa000b894 = argv; Exec(ExeHeader , tmp , 0); } else { printf("No EXE-file !\n"); } printf("Execute the boot file %s.\n" , BootFile); ExitCriticalSection(); if (Load(BootFile,ExeHeader) == 1) { _0xa000b890 = _0xa0009144; _0xa000b894 = _0xa0009148; Exec(ExeHeader,1,0); } printf("No boot file !\n"); while (1) ; } /* 0xbfc03c90 */ int ReadExeHeader(int fd,void *buf) { if (read(fd , Buffer , 2048) <2048) { return 0; } memcpy(buf , &Buffer[0x10] , 0x3c); return 1; } /* sys_a0_43 0xbfc03cf0 */ int Exec(struct EXEC *exe , int argc , char **argv) { int i; long *p; exe->SavedS0 = _s0_; exe->SavedRA = _ra_; exe->SavedSP = _sp_; exe->SavedS8 = _s8_; exe->SavedGP = _gp_; if (exe->b_size) { p = exe->b_addr; for (i = exe->b_size ; i > 0 ; i -= 4) { *p++ = 0; } } if (exe->s_addr) { _stk_ = exe->s_addr + exe->s_size; _fp_ = _stk_; } _gp_ = exe->gp0; (exe->pc0)(argc , argv); _ra_ = exe->SavedRA; _sp_ = exe->SavedSP; _s8_ = exe->SavedS8; _gp_ = exe->SavedGP; _s0_ = exe->SavedS0; return 1; } /* 0xbfc03d80 */ GPU_dw(x,y,w,h,*data) { int count; count = 16; while (!(*gp1 & 0x04000000)) { if (! count--) { printGPUtimeout("GPU_dw"); } } *gp0 = 0xa0000000; *gp0 = (y<<16)|(x&0xffff); *gp0 = (h<<16)|(y&0xffff); count = (w*h)/2-1; if (count==-1) return; do { *gp0 = *data++; } while(count--); } printGPUtimeout(char* str) // bfc04260 { printf("%s timeout: gp1=%08x",str,*gp1); } GPU_cw(u_long c) { GPU_sync(); *gp0=c; } bfunc40ec() { *d2_chcr=0x0401; *gp1=0x04000000; *gp1=0x02000000; *gp1=0x01000000; } // download from gp0 bfunc3fe0(u_long a0, u_long a1) { GPU_sync(); } SendPrimitives(void* ptr) // bfc0403c { printf("0x01(%08x)\n",ptr); GPU_sync(); *gp1=0x04000002; *d_icr=0; *d_pcr|=0x0800; *d2_madr=ptr; *d2_bcr=0; printf("0x02\n"); *d2_chcr=0x01000401; printf("0x03\n"); } /* 0xbfc04610 */ InitIntr(int count) { u_char *p; u_long size; size=count * 8; if ((p=_SysMalloc(size))==NULL) { return 0; } bclear(p, size); *(u_long *)0xa0000100=p; *(u_long *)0xa0000104=size; return size; } /* 0xbfc04678 */ InitEvent(int n) { int i; unsigned long *h, *p; printf("\nConfiguration : EvCB\0100x%02x\010\010", n); i=n; n *=28; if ((h=_SysMalloc(n))== NULL) { return 0; } *(u_long *)0xa0000124=n; *(u_long *)0xa0000120=h; for (p=h ; p < (EvCB *)(h + n) ; p++) { *p=0; } return n; } /* sys_a0_9f 0xbfc06680 */ SetMem(size) { int *mem,new; mem=*ram_size; new=*mem & 0xfffff8ff; switch(size) { case 2: *mem=new; *(long *)(0x00000060)=size; printf("Change effective memory : %d MBytes\n",size); break; case 8: *mem=new | 0x300; *(long *)(0x00000060)=size; printf("Change effective memory : %d MBytes\n",size); default: printf("Effective memory must be 2/8 MBytes\n"); break; } } /* 0xbfc06700 */ do_a_long_jump(int value) { longjmp(&context,value); } /* sys_a0_9d 0xbfc06728 */ GetConf(long *Event,long *TCB,long *Stack) { *Stack=sys_conf.Stack; *Event=sys_conf.Event; *TCB=sys_conf.TCB; } /* sys_a0_9c 0xbfc06750 */ SetConf(long Event,long TCB,long Stack) { sys_conf.Stack=Stack; sys_conf.Event=Event; sys_conf.TCB=TCB; _kernel_setup(); } /* 0xbfc06784 */ part3() { char s1[80],s2[80]; strcpy(s2,"cdrom:"); strcat(s2,"SYSTEM.CNF;1"); strcpy(s1,"cdrom:"); strcat(s1,"PSX.EXE;1"); bootstrap(s2,s1); } /* 0xbfc067e8 */ bootstrap(char *config,char *executable) { int fd,readen; __trace(1); setSTATUS(getSTATUS() & 0xfffffbfe); zero_stuff(); __trace(2); SysInitKMem(); __trace(3); InstallInterruptTables(); InstallInterruptDispatch(); PatchA0Table(); InstallExceptionHandler(); ResetEntryInt(); __trace(4); zero_stuff(); IntrMask=0; *i_reg=0; InstallDevices(_0xa000b9b0); __trace(5); printf("\nPS-X Realtime Kernel Ver.2.5\n \ Copyright 1993,1994 (C) Sony Computer Entertainment Inc. \n"); __trace(6); zero_stuff(); memcpy(&sys_conf , &default_sys_conf , 12); printf("KERNEL SETUP!\n"); SysInitMemory(0xa000e000 , 0x2000); InitIntr(4); InitException(0); InitDefInt(3); InitEvent(sys_conf.Event); InitSchr(1,sys_conf.TCB); InitRCnt(1); zero_stuff(); if (setjmp(&context)) sys_err(0x0385); __trace(7); ExecuteShell(); /* this is where the country lockout is located */ __trace(8); IntrMask=0; *i_reg=0; _96_init(); if (setjmp(&context)) sys_err(0x0399); if (CheckForDevice1()== 1) InitDevice1(); printf("\nBOOTSTRAP LOADER Type C Ver 2.1 03-JUL-1994\n\ Copyright 1993,1994 (C) Sony Computer Entertainment Inc.\n"); if (setjmp(&context)) sys_err(0x0386); __trace(9); if (setjmp(&context)) sys_err(0x387); if ((fd=open(config , 1))>= 0) { printf("setup file : %s\n",config); if (setjmp(&context)) sys_err(0x038f); if ( (readen = read(fd , Buffer , 2048)) == 0) { memcpy(&sys_conf , &default_sys_conf , 12); strcpy(BootFile , executable); } else { Buffer[readen] = (char) 0; close(fd); if (setjmp(&context)) sys_err(0x0390); ParseSetupFile(Buffer , sys_conf , BootFile); } } else { if (setjmp(&context)) sys_err(0x0391); _0x00000180 = (char)0; memcpy(&sys_conf , &default_sys_conf , 12); strcpy(BootFile , executable); } if (setjmp(&context)) sys_err(0x0388); kernel_setup(); printf("boot file : %s\n",BootFile); if (setjmp(&context)) sys_err(0x0389); ClearRam(); if (Load(BootFile,ExeHeader)) sys_err(0x038a); printf("EXEC:PC0(%08x) T_ADDR(%08x) T_SIZE(%08x)\n", ExeHeader.pc0 , ExeHeader.t_addr , ExeHeader.t_size); printf("boot address : %08x %08x\nExecute !\n\n", ExeHeader.pc0 , sys_conf.Stack); _0xa000b890 = sys_conf.Stack; _0xa000b894 = 0; printf(" S_ADDR(%08x) S_SIZE(%08x)\n", sys_conf.Stack , 0); EnterCriticalSection(); if (setjmp(&context)) sys_err(0x038b); doExec(ExeHeader,1,0); printf("End of Main\n"); sys_err(0x038c); } /* 0xbfc06f28 */ kernel_setup() { printf("KERNEL SETUP!\n"); SysInitMemory(0xa000e000 , 0x2000); InitIntr(4); InitException(0); InitDefInt(3); InitEvent(sys_conf.Event); InitSchr(1,sys_conf.TCB); InitRCnt(1); _96_init(); } part2() { __trace(0x0f); zero_stuff(); if (CheckForDevice2() == 1) InitDevice2(); __trace(0x0e); _0xa000b9b0 = 0; part3(); } /* 0xbfc06ff0 */ ExecuteShell(long arg) { memcpy(0x80030000 , 0xbfc18000 , 0x67ff0); FlushCache(); (char *)(0x80030000)(arg); } /* 0xbfc0703c */ CheckForDevice2() { char *src,*dst; src = License; dst = 0x1f000084; if (License[0]) { while (src) { if (*src++ != *dst++) break; } } if (*src) return 0; else return 1; } /* 0xbfc070ac */ CheckForDevice1() { char *src,*dst; src = License; dst = 0x1f000004; if (License[0]) { while (src) { if (*src++ != *dst++) break; } } if (*src) return 0; else return 1; } /* 0xbfc0711c */ InitDevice2() { (char *)(0x1f000080)(); } 0xbfc07148() /* */ { printf("PIO SHELL for PlayStation(tm)\n"); printf("%s\n",0x1f000004); (char *)(0x1f000000)(); } /* 0xbfc071a0 */ OpenCDEvents() { sys_a0_a2(); event_cd_ack = OpenEvent(0xf0000003 , 0x10 , 0x2000 , 0); event_cd_comp = OpenEvent(0xf0000003 , 0x20 , 0x2000 , 0); event_cd_dr = OpenEvent(0xf0000003 , 0x40 , 0x2000 , 0); event_cd_de = OpenEvent(0xf0000003 , 0x80 , 0x2000 , 0); event_cd_error = OpenEvent(0xf0000003 , 0x8000 , 0x2000 , 0); EnableEvent(event_cd_ack); EnableEvent(event_cd_comp); EnableEvent(event_cd_dr); EnableEvent(event_cd_de); EnableEvent(event_cd_error); ExitCriticalSection(); _0xa0009d80 = (char)0; } 0xbfc07330() { OpenCDEvents(); while (!sys_a0_95()) ; } /* 0xbfc073a0 */ _96_init() { long tmp; 0xbfc07330(); tmp = 0; while (tmp <50000) { /* this loop might be stupid, but its */ tmp=tmp; /* what it does */ tmp++; } dev_cd_initfs(); } /* 0xbfc0c720 */ Test6ButtonPad() { /* Would u believe me if i told u that */ u_long tmp; /* this and a lot more routines are */ u_long paddata; /* NEVER called ? */ printf("test 6 button PAD (NEW)\n"); if (!PAD_init(0x20000001 , &paddata)) return; while (1) { tmp=0x000186a0; for (i=0 ; i < tmp; i++ ) { i=i; /* burn some cycles */ } tmp=PAD_dr(); EnterCriticalSection(); printf("ret:%08x stock:",tmp); printf(" %08x",paddata); printf("\n"); ExitCriticalSection(); } } /* 0xbfc0d4cc */ EnableIORedirection() { AddDrv(&tty_redir); /* 0xbfc0e59c */ } /* 0xbfc0d570 */ doExec(struct EXEC *exeheader,long arg1,long arg2) { ExitCriticalSection(); if (_0xa000dffc) { /* THIS LOOP IS COPYPROTECTION RELATED */ if (0xbfc0d72c() < 0) { /* This routine and the next one, */ SystemError(0x44 , 0x038b); } /* does some kind of black or country */ if (0xbfc0d7bc() < 0) { /* check. These are used in the shell */ SystemError(0x44 , 0x038b); } /* also, if they fail, byebye */ } /* Noping them here or in the shell, wont solve a thing */ EnterCriticalSection(); /* I hope to have the time someday */ Exec(exeheader , arg1 , arg2); /* to write about protections, since */ /* i know some stuff about. I guided a friend with a DDX, in tracing */ /* executing some code. He came to the conclusion that these routines */ /* return different values whether a CD is audio, psx original, psx */ /* foreign, or gold/HK. Hope to write about it soon */ } /* 0xbfc0d600 */ 0xbfc0d600() { *reg0=1; *reg3=0x1f; for (i=0 ; i !=4 ; i++) { *(long *)(0)=i & 3; } } /* 0xbfc0d640 */ 0xbfc0d640() { *reg0=1; *reg2=0x1f; } /* 0xbfc0d664 */ 0xbfc0d664() { *reg0=1; *reg2=0x18; } /* 0xbfc0d72c */ 0xbfc0d72c() { 0xbfc0d600(); 0xbfc0d664(); *reg0=0; *reg1=0x1e; tmp=0xbfc0d688(); if (tmp < 0) { 0xbfc0d640(); return 1; } if (tmp & 0x1d) { 0xbfc0d640(); return 1; } 0xbfc0d600(); 0xbfc0d640(); return 0; } /* 0xbfc0d850 */ ClearRam() { u_long *p,top; top=_stk_ | 0xa0000000; for (p=0xa0010000 ; p !=top ; p++) { *p=0; } } static char License[]="Licensed by Sony Computer Entertainment Inc." ; static struct default_sys_conf={ 4, 16, 0x801fff00 }; /* 0xbfc0e14c */ static struct EXEC ExeHeader; /* 0xa000b870 */ static char *BootFile; /* 0xa000b8b0 */ static struct sys_conf { /* 0xa000b940 */ u_long TCB; u_long Event; u_long Stack; }; static jmp_buf context; /* 0xa000b980 */
A lot more soon, got a bus to catch, i need the week-end break...
si17911@ci.uminho.pt