view src/sexypsf/PsxBios.c @ 493:31d21ad70903 trunk

[svn] flac 113 plugin: stability fixes and a new option to disable bitrate update in player window during playback (saves cpu, this is the solution for most people playing flac and reporting high cpu usage)
author giacomo
date Sun, 21 Jan 2007 16:08:19 -0800
parents 3da1b8942b8b
children a8471cee0697
line wrap: on
line source

/*  Pcsx - Pc Psx Emulator
 *  Copyright (C) 1999-2002  Pcsx Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h>
#include <stdarg.h>
#include <ctype.h>

#include "PsxCommon.h"
//We try to emulate bios :) HELP US :P

#ifdef NONONO
char *biosA0n[256] = {
// 0x00
	"open",		"lseek",	"read",		"write",
	"close",	"ioctl",	"exit",		"sys_a0_07",
	"getc",		"putc",		"todigit",	"atof",
	"strtoul",	"strtol",	"abs",		"labs",
// 0x10
	"atoi",		"atol",		"atob",		"setjmp",
	"longjmp",	"strcat",	"strncat",	"strcmp",
	"strncmp",	"strcpy",	"strncpy",	"strlen",
	"index",	"rindex",	"strchr",	"strrchr",
// 0x20
	"strpbrk",	"strspn",	"strcspn",	"strtok",
	"strstr",	"toupper",	"tolower",	"bcopy",
	"bzero",	"bcmp",		"memcpy",	"memset",
	"memmove",	"memcmp",	"memchr",	"rand",
// 0x30
	"srand",	"qsort",	"strtod",	"malloc",
	"free",		"lsearch",	"bsearch",	"calloc",
	"realloc",	"InitHeap",	"_exit",	"getchar",
	"putchar",	"gets",		"puts",		"printf",
// 0x40
	"sys_a0_40",		"LoadTest",					"Load",		"Exec",
	"FlushCache",		"InstallInterruptHandler",	"GPU_dw",	"mem2vram",
	"SendGPUStatus",	"GPU_cw",					"GPU_cwb",	"SendPackets",
	"sys_a0_4c",		"GetGPUStatus",				"GPU_sync",	"sys_a0_4f",
// 0x50
	"sys_a0_50",		"LoadExec",				"GetSysSp",		"sys_a0_53",
	"_96_init()",		"_bu_init()",			"_96_remove()",	"sys_a0_57",
	"sys_a0_58",		"sys_a0_59",			"sys_a0_5a",	"dev_tty_init",
	"dev_tty_open",		"sys_a0_5d",			"dev_tty_ioctl","dev_cd_open",
// 0x60
	"dev_cd_read",		"dev_cd_close",			"dev_cd_firstfile",	"dev_cd_nextfile",
	"dev_cd_chdir",		"dev_card_open",		"dev_card_read",	"dev_card_write",
	"dev_card_close",	"dev_card_firstfile",	"dev_card_nextfile","dev_card_erase",
	"dev_card_undelete","dev_card_format",		"dev_card_rename",	"dev_card_6f",
// 0x70
	"_bu_init",			"_96_init",		"_96_remove",		"sys_a0_73",
	"sys_a0_74",		"sys_a0_75",	"sys_a0_76",		"sys_a0_77",
	"_96_CdSeekL",		"sys_a0_79",	"sys_a0_7a",		"sys_a0_7b",
	"_96_CdGetStatus",	"sys_a0_7d",	"_96_CdRead",		"sys_a0_7f",
// 0x80
	"sys_a0_80",		"sys_a0_81",	"sys_a0_82",		"sys_a0_83",
	"sys_a0_84",		"_96_CdStop",	"sys_a0_86",		"sys_a0_87",
	"sys_a0_88",		"sys_a0_89",	"sys_a0_8a",		"sys_a0_8b",
	"sys_a0_8c",		"sys_a0_8d",	"sys_a0_8e",		"sys_a0_8f",
// 0x90
	"sys_a0_90",		"sys_a0_91",	"sys_a0_92",		"sys_a0_93",
	"sys_a0_94",		"sys_a0_95",	"AddCDROMDevice",	"AddMemCardDevide",
	"DisableKernelIORedirection",		"EnableKernelIORedirection", "sys_a0_9a", "sys_a0_9b",
	"SetConf",			"GetConf",		"sys_a0_9e",		"SetMem",
// 0xa0
	"_boot",			"SystemError",	"EnqueueCdIntr",	"DequeueCdIntr",
	"sys_a0_a4",		"ReadSector",	"get_cd_status",	"bufs_cb_0",
	"bufs_cb_1",		"bufs_cb_2",	"bufs_cb_3",		"_card_info",
	"_card_load",		"_card_auto",	"bufs_cd_4",		"sys_a0_af",
// 0xb0
	"sys_a0_b0",		"sys_a0_b1",	"do_a_long_jmp",	"sys_a0_b3",
	"?? sub_function",
};

char *biosB0n[256] = {
// 0x00
	"SysMalloc",		"sys_b0_01",	"sys_b0_02",	"sys_b0_03",
	"sys_b0_04",		"sys_b0_05",	"sys_b0_06",	"DeliverEvent",
	"OpenEvent",		"CloseEvent",	"WaitEvent",	"TestEvent",
	"EnableEvent",		"DisableEvent",	"OpenTh",		"CloseTh",
// 0x10
	"ChangeTh",			"sys_b0_11",	"InitPAD",		"StartPAD",
	"StopPAD",			"PAD_init",		"PAD_dr",		"ReturnFromExecption",
	"ResetEntryInt",	"HookEntryInt",	"sys_b0_1a",	"sys_b0_1b",
	"sys_b0_1c",		"sys_b0_1d",	"sys_b0_1e",	"sys_b0_1f",
// 0x20
	"UnDeliverEvent",	"sys_b0_21",	"sys_b0_22",	"sys_b0_23",
	"sys_b0_24",		"sys_b0_25",	"sys_b0_26",	"sys_b0_27",
	"sys_b0_28",		"sys_b0_29",	"sys_b0_2a",	"sys_b0_2b",
	"sys_b0_2c",		"sys_b0_2d",	"sys_b0_2e",	"sys_b0_2f",
// 0x30
	"sys_b0_30",		"sys_b0_31",	"open",			"lseek",
	"read",				"write",		"close",		"ioctl",
	"exit",				"sys_b0_39",	"getc",			"putc",
	"getchar",			"putchar",		"gets",			"puts",
// 0x40
	"cd",				"format",		"firstfile",	"nextfile",
	"rename",			"delete",		"undelete",		"AddDevice",
	"RemoteDevice",		"PrintInstalledDevices", "InitCARD", "StartCARD",
	"StopCARD",			"sys_b0_4d",	"_card_write",	"_card_read",
// 0x50
	"_new_card",		"Krom2RawAdd",	"sys_b0_52",	"sys_b0_53",
	"_get_errno",		"_get_error",	"GetC0Table",	"GetB0Table",
	"_card_chan",		"sys_b0_59",	"sys_b0_5a",	"ChangeClearPAD",
	"_card_status",		"_card_wait",
};

char *biosC0n[256] = {
// 0x00
	"InitRCnt",			  "InitException",		"SysEnqIntRP",		"SysDeqIntRP",
	"get_free_EvCB_slot", "get_free_TCB_slot",	"ExceptionHandler",	"InstallExeptionHandler",
	"SysInitMemory",	  "SysInitKMem",		"ChangeClearRCnt",	"SystemError",
	"InitDefInt",		  "sys_c0_0d",			"sys_c0_0e",		"sys_c0_0f",
// 0x10
	"sys_c0_10",		  "sys_c0_11",			"InstallDevices",	"FlushStfInOutPut",
	"sys_c0_14",		  "_cdevinput",			"_cdevscan",		"_circgetc",
	"_circputc",		  "ioabort",			"sys_c0_1a",		"KernelRedirect",
	"PatchAOTable",
};
#endif

//#define r0 (psxRegs.GPR.n.r0)
#define at (psxRegs.GPR.n.at)
#define v0 (psxRegs.GPR.n.v0)
#define v1 (psxRegs.GPR.n.v1)
#define a0 (psxRegs.GPR.n.a0)
#define a1 (psxRegs.GPR.n.a1)
#define a2 (psxRegs.GPR.n.a2)
#define a3 (psxRegs.GPR.n.a3)
#define t0 (psxRegs.GPR.n.t0)
#define t1 (psxRegs.GPR.n.t1)
#define t2 (psxRegs.GPR.n.t2)
#define t3 (psxRegs.GPR.n.t3)
#define t4 (psxRegs.GPR.n.t4)
#define t5 (psxRegs.GPR.n.t5)
#define t6 (psxRegs.GPR.n.t6)
#define t7 (psxRegs.GPR.n.t7)
#define s0 (psxRegs.GPR.n.s0)
#define s1 (psxRegs.GPR.n.s1)
#define s2 (psxRegs.GPR.n.s2)
#define s3 (psxRegs.GPR.n.s3)
#define s4 (psxRegs.GPR.n.s4)
#define s5 (psxRegs.GPR.n.s5)
#define s6 (psxRegs.GPR.n.s6)
#define s7 (psxRegs.GPR.n.s7)
#define t8 (psxRegs.GPR.n.t6)
#define t9 (psxRegs.GPR.n.t7)
#define k0 (psxRegs.GPR.n.k0)
#define k1 (psxRegs.GPR.n.k1)
#define gp (psxRegs.GPR.n.gp)
#define sp (psxRegs.GPR.n.sp)
#define fp (psxRegs.GPR.n.s8)
#define ra (psxRegs.GPR.n.ra)
#define pc0 (psxRegs.pc)

#define Ra0 ((char*)PSXM(a0))
#define Ra1 ((char*)PSXM(a1))
#define Ra2 ((char*)PSXM(a2))
#define Ra3 ((char*)PSXM(a3))
#define Rv0 ((char*)PSXM(v0))
#define Rsp ((char*)PSXM(sp))


typedef struct _malloc_chunk {
	u32 stat;
	u32 size;
	u32 fd;
	u32 bk;
} PACKSTRUCT malloc_chunk;

#define INUSE 0x1

typedef struct {
	u32 desc;
	s32 status;
	s32 mode;
	u32 fhandler;
} PACKSTRUCT EvCB[32];

#define EvStUNUSED	0x0000
#define EvStWAIT	0x1000
#define EvStACTIVE	0x2000
#define EvStALREADY 0x4000

#define EvMdINTR	0x1000
#define EvMdNOINTR	0x2000

typedef struct {
	s32 status;
	s32 mode;
	u32 reg[32];
	u32 func;
} PACKSTRUCT TCB;

static u32 *jmp_int;

static u32 regs[35];
static EvCB *Event;

//static EvCB *HwEV; // 0xf0
//static EvCB *EvEV; // 0xf1
static EvCB *RcEV; // 0xf2
//static EvCB *UeEV; // 0xf3
//static EvCB *SwEV; // 0xf4
//static EvCB *ThEV; // 0xff

static u32 heap_addr;
static u32 SysIntRP[8];
static TCB Thread[8];
static int CurThread;

static INLINE void softCall(u32 pc) {
	pc0 = pc;
	ra = 0x80001000;
	while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
}

static INLINE void softCall2(u32 pc) {
	u32 sra = ra;
	pc0 = pc;
	ra = 0x80001000;
	while (pc0 != 0x80001000) psxCpu->ExecuteBlock();
	ra = sra;
}

static INLINE void DeliverEvent(u32 ev, u32 spec) {
	if (Event[ev][spec].status != BFLIP32S(EvStACTIVE)) return;

//	Event[ev][spec].status = BFLIP32S(EvStALREADY);
	if (Event[ev][spec].mode == BFLIP32S(EvMdINTR)) {
		softCall2(BFLIP32S(Event[ev][spec].fhandler));
	} else Event[ev][spec].status = BFLIP32S(EvStALREADY);
}

/*                                           *
//                                           *
//                                           *
//               System calls A0             */

/* Abs and labs do the same thing? */

static void bios_abs() { // 0x0e
	if((s32)a0 < 0) v0=0-(s32)a0;
	else v0=a0;
	//v0 = abs(a0);
	pc0 = ra;
}

static void bios_labs() { // 0x0f
        if((s32)a0 < 0) v0=0-(s32)a0;
        else v0=a0;
	//v0 = labs(a0);
	pc0 = ra;
}

static void bios_atoi() { // 0x10
	v0 = atoi((char *)Ra0);
	pc0 = ra;
}

static void bios_atol() { // 0x11
	v0 = atoi((char *)Ra0);
	pc0 = ra;
}

static void bios_setjmp() { // 13
	u32 *jmp_buf= (u32*)Ra0;
	int i;

	jmp_buf[0] =  BFLIP32(ra);
	jmp_buf[1] =  BFLIP32(sp);
	jmp_buf[2] =  BFLIP32(fp);
	for (i=0; i<8; i++) // s0-s7
		jmp_buf[3+i] = BFLIP32(psxRegs.GPR.r[16+i]);
	jmp_buf[11] =  BFLIP32(gp);

	v0 = 0; pc0 = ra;
}

static void bios_longjmp() { //14
	u32 *jmp_buf= (u32*)Ra0;
	int i;

	ra = BFLIP32(jmp_buf[0]); /* ra */
	sp = BFLIP32(jmp_buf[1]); /* sp */
	fp = BFLIP32(jmp_buf[2]); /* fp */
	for (i=0; i<8; i++) // s0-s7
	   psxRegs.GPR.r[16+i] =  BFLIP32(jmp_buf[3+i]);
	gp = BFLIP32(jmp_buf[11]); /* gp */

	v0 = a1; pc0 = ra;
}

static void bios_strcat() { // 0x15
	u32 dest,src;

	dest=a0;
	src=a1;

	while(PSXMu8(dest) != 0) dest++; /* Move to end of first string. */
	while(PSXMu8(src) != 0) 
	{
	 if(PSXM(dest) && PSXM(src))
	  PSXMu8(dest)=PSXMu8(src);
	 src++;
	 dest++;
	}
	PSXMu8(dest) = 0;	/* Append null character. */
	//strcat(Ra0, Ra1);

	v0 = a0; 
	pc0 = ra;
}

/*0x16*/
static void bios_strncat() 
{ 
        u32 dest,src,count;
        
        dest=a0;
        src=a1;
        count=a2;

        while(PSXMu8(dest) != 0) dest++; /* Move to end of first string. */
        while(PSXMu8(src) != 0 && count)
        {
         if(PSXM(dest) && PSXM(src))
          PSXMu8(dest)=PSXMu8(src);
         src++;
         dest++;
	 count--;
        }
        PSXMu8(dest) = 0;       /* Append null character. */

 //strncat(Ra0, Ra1, a2); 
 v0 = a0; 
 pc0 = ra;
}

static void bios_strcmp() { // 0x17
	v0 = strcmp(Ra0, Ra1);
	pc0 = ra;
}

static void bios_strncmp() { // 0x18
	u32 max=a2;
	u32 string1=a0;
	u32 string2=a1;
	s8 tmpv=0;

	while(max>0)
	{
	 u8 tmp1=PSXMuR8(string1);
	 u8 tmp2=PSXMuR8(string2);

	 if(!tmp1 || !tmp2) break;

	 tmpv=tmp1-tmp2;
	 if(tmpv) break;
         if(!tmp1 || !tmp2) break;
	 if(!PSXM(string1) || !PSXM(string2)) break;
	 max--;
	 string1++;
	 string2++;
	}
	if(tmpv>0) v0=1;
	else if(tmpv<0) v0=-1;
	else v0=0;
	//printf("%s:%s, %d, %d\n",Ra0,Ra1,a2,v0);
	//v0 = strncmp(Ra0, Ra1, a2);
	pc0 = ra;
}

/*0x19*/
static void bios_strcpy()  
{ 
 u32 src=a1,dest=a0;
 u8 val;

 do
 {
  val=PSXMu8(src);
  PSXMu8(dest)=val;
  src++; 
  dest++;
 } while(val);
 //strcpy(Ra0, Ra1); 
 v0 = a0; 
 pc0 = ra;
}
/*0x1a*/
static void bios_strncpy() 
{ 
 u32 src=a1,dest=a0,max=a2;
 u8 val;  
 
 do
 {
  val=PSXMu8(src); 
  PSXMu8(dest)=val;
  src++;   
  dest++;
  max--;
 } while(val && max);

 //strncpy(Ra0, Ra1, a2);  
 v0 = a0; 
 pc0 = ra;
}

/*0x1b*/
static void bios_strlen()  
{ 
 u32 src=a0;

 while(PSXMu8(src)) src++;

 v0 = src-a0;  
 pc0 = ra;
}

static void bios_index() { // 0x1c
	char *pcA0 = (char *)Ra0; 
	char *pcRet = strchr(pcA0, a1); 
	if(pcRet) 
		v0 = a0 + pcRet - pcA0; 
	else 
		v0 = 0;
    pc0 = ra;
}

static void bios_rindex() { // 0x1d
	char *pcA0 = (char *)Ra0; 
	char *pcRet = strrchr(pcA0, a1); 
	if(pcRet) 
		v0 = a0 + pcRet - pcA0; 
	else 
		v0 = 0;
    pc0 = ra;  
}

static void bios_strchr() { // 0x1e
	char *pcA0 = (char *)Ra0; 
	char *pcRet = strchr(pcA0, a1); 
	if(pcRet) 
		v0 = a0 + pcRet - pcA0; 
	else 
		v0 = 0;
    pc0 = ra;
}

static void bios_strrchr() { // 0x1f
	char *pcA0 = (char *)Ra0; 
	char *pcRet = strrchr(pcA0, a1); 
	if(pcRet) 
		v0 = a0 + pcRet - pcA0; 
	else 
		v0 = 0;
    pc0 = ra;
}

static void bios_strpbrk() { // 0x20
	char *pcA0 = (char *)Ra0; 
	char *pcRet = strpbrk(pcA0, (char *)Ra1); 
	if(pcRet) 
		v0 = a0 + pcRet - pcA0; 
	else 
		v0 = 0;
    pc0 = ra;
}

static void bios_strspn()  { v0 = strspn ((char *)Ra0, (char *)Ra1); pc0 = ra;}/*21*/ 
static void bios_strcspn() { v0 = strcspn((char *)Ra0, (char *)Ra1); pc0 = ra;}/*22*/ 

#ifdef MOO
static void bios_strtok() { // 0x23
	char *pcA0 = (char *)Ra0;
	char *pcRet = strtok(pcA0, (char *)Ra1);
	if(pcRet)
		v0 = a0 + pcRet - pcA0;
	else
		v0 = 0;
    pc0 = ra;
}
#endif

static void bios_strstr() { // 0x24
	char *pcA0 = (char *)Ra0;
	char *pcRet = strstr(pcA0, (char *)Ra1);
	if(pcRet)
		v0 = a0 + pcRet - pcA0;
	else
		v0 = 0;
    pc0 = ra;
}

/*0x25*/
static void bios_toupper() {v0 = toupper(a0); pc0 = ra;}

/*0x26*/
static void bios_tolower() {v0 = tolower(a0); pc0 = ra;}

/*0x27*/
static void bios_bcopy()   
{
 u32 dest=a1, src=a0, len=a2;

 while(len--)
 {
  PSXMu8(dest)=PSXMu8(src);
  dest++;
  src++;
 }
 //memcpy(Ra1,Ra0,a2); 
 pc0=ra;
}

/*0x28*/
static void bios_bzero()   
{
 u32 dest=a0, len=a1;
 
 while(len--)
 {
  PSXMu8(dest)=0;
  dest++;
 }

 //memset(Ra0,0,a1); 
 pc0=ra;
}

/*0x29*/
static void bios_bcmp()    {v0 = memcmp(Ra0,Ra1,a2); pc0=ra; }

/*0x2a*/
static void bios_memcpy()  
{
 u32 dest=a0, src=a1, len=a2;
 
 while(len--)
 {
  PSXMu8(dest)=PSXMu8(src);
  dest++;
  src++;
 }
 //memcpy(Ra0, Ra1, a2); 
 v0 = a0; 
 pc0 = ra;
}

static void bios_memset()  /*0x2b*/
{
 u32 len=a2;
 u32 dest=a0;

 while(len--)
 {
  if(PSXM(dest)) PSXMu8(dest)=a1;
  dest++;
 }
 //memset(Ra0, a1, a2);
 v0 = a0; 
 pc0 = ra;
}

#ifdef MOO
/*0x2c*/void bios_memmove() {memmove(Ra0, Ra1, a2); v0 = a0; pc0 = ra;}
#endif

/*0x2d*/
static void bios_memcmp()  
{
 v0 = memcmp(Ra0, Ra1, a2); 
 pc0 = ra;
}

static void bios_memchr() { // 2e
	void *ret = memchr(Ra0, a1, a2);
	if (ret != NULL) v0 = (u32)((char*)ret - Ra0) + a0;
	else v0 = 0;
	pc0 = ra;
}

static void bios_rand() { // 2f
	v0 = 1+(int) (32767.0*rand()/(RAND_MAX+1.0));
	pc0 = ra;
}

static void bios_srand() { // 30
	srand(a0); pc0 = ra;
}

static void bios_malloc() { // 33
	u32 chunk;
	u32 fd;

	/* a0:  Number of bytes to allocate. */

	chunk = heap_addr;

	/* Search for first chunk that's large enough and not currently
	   being used.
	*/
	while( (a0 > BFLIP32(((malloc_chunk*)PSXM(chunk)) ->size)) ||
		(BFLIP32( ((malloc_chunk*)PSXM(chunk))->stat  ) == INUSE)
		)
		chunk=((malloc_chunk*)PSXM(chunk)) -> fd;
	//printf("%08x\n",chunk);

	/* split free chunk */
	fd = chunk + sizeof(malloc_chunk) + a0;
	((malloc_chunk*)PSXM(fd))->stat = ((malloc_chunk*)PSXM(chunk))->stat;
	((malloc_chunk*)PSXM(fd))->size = BFLIP32(BFLIP32(((malloc_chunk*)PSXM(chunk))->size) - a0);
	((malloc_chunk*)PSXM(fd))->fd = ((malloc_chunk*)PSXM(chunk))->fd;
	((malloc_chunk*)PSXM(fd))->bk = chunk;

	/* set new chunk */
	((malloc_chunk*)PSXM(chunk))->stat = BFLIP32(INUSE);
	((malloc_chunk*)PSXM(chunk))->size = BFLIP32(a0);
	((malloc_chunk*)PSXM(chunk))->fd = fd;

	v0 = chunk + sizeof(malloc_chunk);
	v0|= 0x80000000;
	//	printf ("malloc %lx,%lx\n", v0, a0);
	pc0 = ra;
}

static void bios_InitHeap() { // 39
	malloc_chunk *chunk;

	heap_addr = a0; // Ra0

	chunk = (malloc_chunk *)PSXM(heap_addr);
	chunk->stat = 0;
	if (((a0 & 0x1fffff) + a1)>= 0x200000) 
	 chunk->size = BFLIP32(0x1ffffc - (a0 & 0x1fffff));
	else chunk->size = BFLIP32(a1);
	chunk->fd = 0;
	chunk->bk = 0;

	pc0 = ra;
}

static void bios_FlushCache() { // 44

	pc0 = ra;
}

static void bios__bu_init() { // 70

	DeliverEvent(0x11, 0x2); // 0xf0000011, 0x0004
	DeliverEvent(0x81, 0x2); // 0xf4000001, 0x0004

	pc0 = ra;
}

static void bios__96_init() { // 71

	pc0 = ra;
}

static void bios__96_remove() { // 72

	pc0 = ra;
}

/* System calls B0 */

static void bios_SetRCnt() { // 02

	a0&= 0x3;
	if (a0 != 3) {
		u32 mode=0;

		psxRcntWtarget(a0, a1);
		if (a2&0x1000) mode|= 0x050; // Interrupt Mode
		if (a2&0x0100) mode|= 0x008; // Count to 0xffff
		if (a2&0x0010) mode|= 0x001; // Timer stop mode
		if (a0 == 2) { if (a2&0x0001) mode|= 0x200; } // System Clock mode
		else         { if (a2&0x0001) mode|= 0x100; } // System Clock mode

		psxRcntWmode(a0, mode);
	}
	pc0 = ra;
}

static void bios_GetRCnt() { // 03

	a0&= 0x3;
	if (a0 != 3) v0 = psxRcntRcount(a0);
	else v0 = 0;
	pc0 = ra;
}

static void bios_StartRCnt() { // 04

	a0&= 0x3;
	if (a0 != 3) psxHu32(0x1074)|= BFLIP32(1<<(a0+4));
	else psxHu32(0x1074)|= BFLIP32(0x1);
	v0 = 1; pc0 = ra;
}

static void bios_StopRCnt() { // 05

	a0&= 0x3;
	if (a0 != 3) psxHu32(0x1074)&= BFLIP32(~(1<<(a0+4)));
	else psxHu32(0x1074)&= BFLIP32(~0x1);
	pc0 = ra;
}

static void bios_ResetRCnt() { // 06

	a0&= 0x3;
	if (a0 != 3) {
		psxRcntWmode(a0, 0);
		psxRcntWtarget(a0, 0);
		psxRcntWcount(a0, 0);
	}
	pc0 = ra;
}


/* gets ev for use with Event */
#define GetEv() \
	ev = (a0 >> 24) & 0xf; \
	if (ev == 0xf) ev = 0x5; \
	ev*= 32; \
	ev+= a0&0x1f;

/* gets spec for use with Event */
#define GetSpec() \
	spec = 0; \
	switch (a1) { \
		case 0x0301: spec = 16; break; \
		case 0x0302: spec = 17; break; \
		default: \
			for (i=0; i<16; i++) if (a1 & (1 << i)) { spec = i; break; } \
			break; \
	}

static void bios_DeliverEvent() { // 07
	int ev, spec;
	int i;

	GetEv();
	GetSpec();

	DeliverEvent(ev, spec);

	pc0 = ra;
}

static void bios_OpenEvent() { // 08
	int ev, spec;
	int i;

	GetEv();
	GetSpec();

	Event[ev][spec].status = BFLIP32S(EvStWAIT);
	Event[ev][spec].mode = BFLIP32(a2);
	Event[ev][spec].fhandler = BFLIP32(a3);

	v0 = ev | (spec << 8);
	pc0 = ra;
}

static void bios_CloseEvent() { // 09
	int ev, spec;

	ev   = a0 & 0xff;
	spec = (a0 >> 8) & 0xff;

	Event[ev][spec].status = BFLIP32S(EvStUNUSED);

	v0 = 1; pc0 = ra;
}

static void bios_WaitEvent() { // 0a
	int ev, spec;

	ev   = a0 & 0xff;
	spec = (a0 >> 8) & 0xff;

	Event[ev][spec].status = BFLIP32S(EvStACTIVE);

	v0 = 1; pc0 = ra;
}

static void bios_TestEvent() { // 0b
	int ev, spec;

	ev   = a0 & 0xff;
	spec = (a0 >> 8) & 0xff;

	if (Event[ev][spec].status == BFLIP32S(EvStALREADY)) {
		Event[ev][spec].status = BFLIP32S(EvStACTIVE); v0 = 1;
	} else v0 = 0;

	pc0 = ra;
}

static void bios_EnableEvent() { // 0c
	int ev, spec;

	ev   = a0 & 0xff;
	spec = (a0 >> 8) & 0xff;

	Event[ev][spec].status = BFLIP32S(EvStACTIVE);

	v0 = 1; pc0 = ra;
}

static void bios_DisableEvent() { // 0d
	int ev, spec;

	ev   = a0 & 0xff;
	spec = (a0 >> 8) & 0xff;

	Event[ev][spec].status = BFLIP32S(EvStWAIT);

	v0 = 1; pc0 = ra;
}

/*
 *	long OpenTh(long (*func)(), unsigned long sp, unsigned long gp);
 */

static void bios_OpenTh() { // 0e
	int th;

	for (th=1; th<8; th++)
		if (Thread[th].status == 0) break;

	Thread[th].status = BFLIP32(1);
	Thread[th].func    = BFLIP32(a0);
	Thread[th].reg[29] = BFLIP32(a1);
	Thread[th].reg[28] = BFLIP32(a2);

	v0 = th; pc0 = ra;
}

/*
 *	int CloseTh(long thread);
 */

static void bios_CloseTh() { // 0f
	int th = a0 & 0xff;

	if (Thread[th].status == 0) {
		v0 = 0;
	} else {
		Thread[th].status = 0;
		v0 = 1;
	}

	pc0 = ra;
}

/*
 *	int ChangeTh(long thread);
 */

static void bios_ChangeTh() { // 10
	int th = a0 & 0xff;

	if (Thread[th].status == 0 || CurThread == th) {
		v0 = 0;

		pc0 = ra;
	} else {
		v0 = 1;

		if (Thread[CurThread].status == BFLIP32S(2)) {
			Thread[CurThread].status = BFLIP32S(1);
			Thread[CurThread].func = BFLIP32(ra);
			memcpy(Thread[CurThread].reg, psxRegs.GPR.r, 32*4);
		}

		memcpy(psxRegs.GPR.r, Thread[th].reg, 32*4);
		pc0 = BFLIP32(Thread[th].func);
		Thread[th].status = BFLIP32(2);
		CurThread = th;
	}
}

static void bios_ReturnFromException() { // 17
	memcpy(psxRegs.GPR.r, regs, 32*4);
	psxRegs.GPR.n.lo = regs[32];
	psxRegs.GPR.n.hi = regs[33];

	pc0 = psxRegs.CP0.n.EPC;
	if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;

	psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
						  ((psxRegs.CP0.n.Status & 0x3c) >> 2);
}

static void bios_ResetEntryInt() { // 18

	jmp_int = NULL;
	pc0 = ra;
}

static void bios_HookEntryInt() { // 19

	jmp_int = (u32*)Ra0;
	pc0 = ra;
}

static void bios_UnDeliverEvent() { // 0x20
	int ev, spec;
	int i;

	GetEv();
	GetSpec();

	if (Event[ev][spec].status == BFLIP32S(EvStALREADY) &&
		Event[ev][spec].mode == BFLIP32S(EvMdNOINTR))
			Event[ev][spec].status = BFLIP32S(EvStACTIVE);

	pc0 = ra;
}

static void bios_GetC0Table() { // 56

	v0 = 0x674; pc0 = ra;
}

static void bios_GetB0Table() { // 57

	v0 = 0x874; pc0 = ra;
}

/* System calls C0 */

/*
 * int SysEnqIntRP(int index , long *queue);
 */

static void bios_SysEnqIntRP() { // 02

	SysIntRP[a0] = a1;

	v0 = 0; pc0 = ra;
}

/*
 * int SysDeqIntRP(int index , long *queue);
 */

static void bios_SysDeqIntRP() { // 03

	SysIntRP[a0] = 0;

	v0 = 0; pc0 = ra;
}

static void bios_ChangeClearRCnt() { // 0a
	u32 *ptr;

	ptr = (u32*)PSXM((a0 << 2) + 0x8600);
	v0 = BFLIP32(*ptr);
	*ptr = BFLIP32(a1);

//	psxRegs.CP0.n.Status|= 0x404;
	pc0 = ra;
}

static void bios_dummy() { 
	pc0 = ra; 
}

void (*biosA0[256])();
void (*biosB0[256])();
void (*biosC0[256])();

void psxBiosInit() {
	u32 base, size;
	u32 *ptr; 
	int i;

	heap_addr=0;
	CurThread = 0;
	jmp_int = NULL;

	for(i = 0; i < 256; i++) {
		biosA0[i] = NULL;
		biosB0[i] = NULL;
		biosC0[i] = NULL;
	}

	for(i = 0; i < 256; i++) {
		if (biosA0[i] == NULL) biosA0[i] = bios_dummy;
		if (biosB0[i] == NULL) biosB0[i] = bios_dummy;
		if (biosC0[i] == NULL) biosC0[i] = bios_dummy;
	}

	biosA0[0x0e] = bios_abs;
	biosA0[0x0f] = bios_labs;
	biosA0[0x10] = bios_atoi;  
	biosA0[0x11] = bios_atol;  
	//biosA0[0x12] = bios_atob;
	biosA0[0x13] = bios_setjmp;
	biosA0[0x14] = bios_longjmp;

	biosA0[0x15] = bios_strcat;
	biosA0[0x16] = bios_strncat;
	biosA0[0x17] = bios_strcmp;
	biosA0[0x18] = bios_strncmp;
	biosA0[0x19] = bios_strcpy;
	biosA0[0x1a] = bios_strncpy;
	biosA0[0x1b] = bios_strlen;
	biosA0[0x1c] = bios_index;
	biosA0[0x1d] = bios_rindex;
	biosA0[0x1e] = bios_strchr;
	biosA0[0x1f] = bios_strrchr;
	biosA0[0x20] = bios_strpbrk;
	biosA0[0x21] = bios_strspn;
	biosA0[0x22] = bios_strcspn;
	//biosA0[0x23] = bios_strtok;
	biosA0[0x24] = bios_strstr;
	biosA0[0x25] = bios_toupper;
	biosA0[0x26] = bios_tolower;
	biosA0[0x27] = bios_bcopy;
	biosA0[0x28] = bios_bzero;
	biosA0[0x29] = bios_bcmp;
	biosA0[0x2a] = bios_memcpy;
	biosA0[0x2b] = bios_memset;
	//biosA0[0x2c] = bios_memmove;
	biosA0[0x2c] = bios_memcpy;	/* Our code should be compatible
					   with both memcpy and memmove 
					   semantics. */
	biosA0[0x2d] = bios_memcmp;
	biosA0[0x2e] = bios_memchr;

	biosA0[0x2f] = bios_rand;
	biosA0[0x30] = bios_srand;

	//biosA0[0x31] = bios_qsort;
	//biosA0[0x32] = bios_strtod;
	biosA0[0x33] = bios_malloc;
	//biosA0[0x34] = bios_free;
    	//biosA0[0x35] = bios_lsearch;
    	//biosA0[0x36] = bios_bsearch;
    	//biosA0[0x37] = bios_calloc;
    	//biosA0[0x38] = bios_realloc;
	biosA0[0x39] = bios_InitHeap;
    	//biosA0[0x3a] = bios__exit;
	biosA0[0x44] = bios_FlushCache;
    	//biosA0[0x45] = bios_InstallInterruptHandler;
	//biosA0[0x4f] = bios_sys_a0_4f;
	//biosA0[0x50] = bios_sys_a0_50;		
	biosA0[0x70] = bios__bu_init;
	biosA0[0x71] = bios__96_init;
	biosA0[0x72] = bios__96_remove;
	//biosA0[0x73] = bios_sys_a0_73;
	//biosA0[0x74] = bios_sys_a0_74;
	//biosA0[0x75] = bios_sys_a0_75;
	//biosA0[0x76] = bios_sys_a0_76;
	//biosA0[0x77] = bios_sys_a0_77;
	//biosA0[0x78] = bios__96_CdSeekL;
	//biosA0[0x79] = bios_sys_a0_79;
	//biosA0[0x7a] = bios_sys_a0_7a;
	//biosA0[0x7b] = bios_sys_a0_7b;
	//biosA0[0x7c] = bios__96_CdGetStatus;
	//biosA0[0x7d] = bios_sys_a0_7d;
	//biosA0[0x7e] = bios__96_CdRead;
	//biosA0[0x7f] = bios_sys_a0_7f;
	//biosA0[0x80] = bios_sys_a0_80;
	//biosA0[0x81] = bios_sys_a0_81;
	//biosA0[0x82] = bios_sys_a0_82;		
	//biosA0[0x83] = bios_sys_a0_83;
	//biosA0[0x84] = bios_sys_a0_84;
	//biosA0[0x85] = bios__96_CdStop;	
	//biosA0[0x86] = bios_sys_a0_86;
	//biosA0[0x87] = bios_sys_a0_87;
	//biosA0[0x88] = bios_sys_a0_88;
	//biosA0[0x89] = bios_sys_a0_89;
	//biosA0[0x8a] = bios_sys_a0_8a;
	//biosA0[0x8b] = bios_sys_a0_8b;
	//biosA0[0x8c] = bios_sys_a0_8c;
	//biosA0[0x8d] = bios_sys_a0_8d;
	//biosA0[0x8e] = bios_sys_a0_8e;		
	//biosA0[0x8f] = bios_sys_a0_8f;
	//biosA0[0x90] = bios_sys_a0_90;
	//biosA0[0x91] = bios_sys_a0_91;
	//biosA0[0x92] = bios_sys_a0_92;
	//biosA0[0x93] = bios_sys_a0_93;
	//biosA0[0x94] = bios_sys_a0_94;
	//biosA0[0x95] = bios_sys_a0_95;
	//biosA0[0x96] = bios_AddCDROMDevice;
	//biosA0[0x97] = bios_AddMemCardDevide;
	//biosA0[0x98] = bios_DisableKernelIORedirection;
	//biosA0[0x99] = bios_EnableKernelIORedirection;
	//biosA0[0x9a] = bios_sys_a0_9a;
	//biosA0[0x9b] = bios_sys_a0_9b;
	//biosA0[0x9c] = bios_SetConf;
	//biosA0[0x9d] = bios_GetConf;
	//biosA0[0x9e] = bios_sys_a0_9e;
	//biosA0[0x9f] = bios_SetMem;
	//biosA0[0xa0] = bios__boot;
	//biosA0[0xa1] = bios_SystemError;
	//biosA0[0xa2] = bios_EnqueueCdIntr;
	//biosA0[0xa3] = bios_DequeueCdIntr;
	//biosA0[0xa4] = bios_sys_a0_a4;
	//biosA0[0xa5] = bios_ReadSector;
	//biosA0[0xa6] = bios_get_cd_status;
	//biosA0[0xa7] = bios_bufs_cb_0;
	//biosA0[0xa8] = bios_bufs_cb_1;
	//biosA0[0xa9] = bios_bufs_cb_2;
	//biosA0[0xaa] = bios_bufs_cb_3;
	//biosA0[0xab] = bios__card_info;
	//biosA0[0xac] = bios__card_load;
	//biosA0[0axd] = bios__card_auto;
	//biosA0[0xae] = bios_bufs_cd_4;
	//biosA0[0xaf] = bios_sys_a0_af;
	//biosA0[0xb0] = bios_sys_a0_b0;
	//biosA0[0xb1] = bios_sys_a0_b1;
	//biosA0[0xb2] = bios_do_a_long_jmp
	//biosA0[0xb3] = bios_sys_a0_b3;
	//biosA0[0xb4] = bios_sub_function;
//*******************B0 CALLS****************************
	//biosB0[0x00] = bios_SysMalloc;
	//biosB0[0x01] = bios_sys_b0_01;
	biosB0[0x02] = bios_SetRCnt;
	biosB0[0x03] = bios_GetRCnt;
	biosB0[0x04] = bios_StartRCnt;
	biosB0[0x05] = bios_StopRCnt;
	biosB0[0x06] = bios_ResetRCnt;
	biosB0[0x07] = bios_DeliverEvent;
	biosB0[0x08] = bios_OpenEvent;
	biosB0[0x09] = bios_CloseEvent;
	biosB0[0x0a] = bios_WaitEvent;
	biosB0[0x0b] = bios_TestEvent;
	biosB0[0x0c] = bios_EnableEvent;
	biosB0[0x0d] = bios_DisableEvent;
	biosB0[0x0e] = bios_OpenTh;
	biosB0[0x0f] = bios_CloseTh;
	biosB0[0x10] = bios_ChangeTh;
	//biosB0[0x11] = bios_bios_b0_11;
	biosB0[0x17] = bios_ReturnFromException;
	biosB0[0x18] = bios_ResetEntryInt;
	biosB0[0x19] = bios_HookEntryInt;
	//biosB0[0x1a] = bios_sys_b0_1a;
	//biosB0[0x1b] = bios_sys_b0_1b;
	//biosB0[0x1c] = bios_sys_b0_1c;
	//biosB0[0x1d] = bios_sys_b0_1d;
	//biosB0[0x1e] = bios_sys_b0_1e;
	//biosB0[0x1f] = bios_sys_b0_1f;
	biosB0[0x20] = bios_UnDeliverEvent;
	//biosB0[0x21] = bios_sys_b0_21;
	//biosB0[0x22] = bios_sys_b0_22;
	//biosB0[0x23] = bios_sys_b0_23;
	//biosB0[0x24] = bios_sys_b0_24;
	//biosB0[0x25] = bios_sys_b0_25;
	//biosB0[0x26] = bios_sys_b0_26;
	//biosB0[0x27] = bios_sys_b0_27;
	//biosB0[0x28] = bios_sys_b0_28;
	//biosB0[0x29] = bios_sys_b0_29;
	//biosB0[0x2a] = bios_sys_b0_2a;
	//biosB0[0x2b] = bios_sys_b0_2b;
	//biosB0[0x2c] = bios_sys_b0_2c;
	//biosB0[0x2d] = bios_sys_b0_2d;
	//biosB0[0x2e] = bios_sys_b0_2e;
	//biosB0[0x2f] = bios_sys_b0_2f;
	//biosB0[0x30] = bios_sys_b0_30;
	//biosB0[0x31] = bios_sys_b0_31;
	biosB0[0x56] = bios_GetC0Table;
	biosB0[0x57] = bios_GetB0Table;
	//biosB0[0x58] = bios__card_chan;
	//biosB0[0x59] = bios_sys_b0_59;
	//biosB0[0x5a] = bios_sys_b0_5a;
	//biosB0[0x5c] = bios__card_status;
	//biosB0[0x5d] = bios__card_wait;
//*******************C0 CALLS****************************
	//biosC0[0x00] = bios_InitRCnt;
	//biosC0[0x01] = bios_InitException;
	biosC0[0x02] = bios_SysEnqIntRP;
	biosC0[0x03] = bios_SysDeqIntRP;
	//biosC0[0x04] = bios_get_free_EvCB_slot;
	//biosC0[0x05] = bios_get_free_TCB_slot;
	//biosC0[0x06] = bios_ExceptionHandler;
	//biosC0[0x07] = bios_InstallExeptionHandler;
	//biosC0[0x08] = bios_SysInitMemory;
	//biosC0[0x09] = bios_SysInitKMem;
	biosC0[0x0a] = bios_ChangeClearRCnt;	
	//biosC0[0x0b] = bios_SystemError;
	//biosC0[0x0c] = bios_InitDefInt;
	//biosC0[0x0d] = bios_sys_c0_0d;
	//biosC0[0x0e] = bios_sys_c0_0e;
	//biosC0[0x0f] = bios_sys_c0_0f;
	//biosC0[0x10] = bios_sys_c0_10;
	//biosC0[0x11] = bios_sys_c0_11;
	//biosC0[0x12] = bios_InstallDevices;
	//biosC0[0x13] = bios_FlushStfInOutPut;
	//biosC0[0x14] = bios_sys_c0_14;
	//biosC0[0x15] = bios__cdevinput;
	//biosC0[0x16] = bios__cdevscan;
	//biosC0[0x17] = bios__circgetc;
	//biosC0[0x18] = bios__circputc;		  
	//biosC0[0x19] = bios_ioabort;
	//biosC0[0x1a] = bios_sys_c0_1a
	//biosC0[0x1b] = bios_KernelRedirect;
	//biosC0[0x1c] = bios_PatchAOTable;
//************** THE END ***************************************

	base = 0x1000;
	size = sizeof(EvCB) * 32;
	Event = (void *)&psxR[base]; base+= size*6;
	memset(Event, 0, size * 6);
	//HwEV = Event;
	//EvEV = Event + 32;
	RcEV = Event + 32*2;
	//UeEV = Event + 32*3;
	//SwEV = Event + 32*4;
	//ThEV = Event + 32*5;

	ptr = (u32*)&psxM[0x0874]; // b0 table
	ptr[0] = BFLIP32(0x4c54 - 0x884);

	ptr = (u32*)&psxM[0x0674]; // c0 table
	ptr[6] = BFLIP32(0xc80);

	memset(SysIntRP, 0, sizeof(SysIntRP));
	memset(Thread, 0, sizeof(Thread));
	Thread[0].status = BFLIP32(2); // main thread

	psxMu32(0x0150) = BFLIP32(0x160);
	psxMu32(0x0154) = BFLIP32(0x320);
	psxMu32(0x0160) = BFLIP32(0x248);
	strcpy(&psxM[0x248], "bu");

/*	psxMu32(0x0ca8) = BFLIP32(0x1f410004);
	psxMu32(0x0cf0) = BFLIP32(0x3c020000);
	psxMu32(0x0cf4) = BFLIP32(0x2442641c);
	psxMu32(0x09e0) = BFLIP32(0x43d0);
	psxMu32(0x4d98) = BFLIP32(0x946f000a);
*/
	// opcode HLE
	psxRu32(0x0000) = BFLIP32((0x3b << 26) | 4);
	psxMu32(0x0000) = BFLIP32((0x3b << 26) | 0);
	psxMu32(0x00a0) = BFLIP32((0x3b << 26) | 1);
	psxMu32(0x00b0) = BFLIP32((0x3b << 26) | 2);
	psxMu32(0x00c0) = BFLIP32((0x3b << 26) | 3);
	psxMu32(0x4c54) = BFLIP32((0x3b << 26) | 0);
	psxMu32(0x8000) = BFLIP32((0x3b << 26) | 5);
	psxMu32(0x07a0) = BFLIP32((0x3b << 26) | 0);
	psxMu32(0x0884) = BFLIP32((0x3b << 26) | 0);
	psxMu32(0x0894) = BFLIP32((0x3b << 26) | 0);
}

void psxBiosShutdown() {
}

void biosInterrupt() {
	if (BFLIP32(psxHu32(0x1070)) & 0x1) { // Vsync
		if (RcEV[3][1].status == BFLIP32S(EvStACTIVE)) {
			softCall(BFLIP32(RcEV[3][1].fhandler));
//			hwWrite32(0x1f801070, ~(1));
		}
	}

	if (BFLIP32(psxHu32(0x1070)) & 0x70) { // Rcnt 0,1,2
		int i;

		for (i=0; i<3; i++) {
			if (BFLIP32(psxHu32(0x1070)) & (1 << (i+4))) {
				if (RcEV[i][1].status == BFLIP32S(EvStACTIVE)) {
					softCall(BFLIP32(RcEV[i][1].fhandler));
					psxHwWrite32(0x1f801070, ~(1 << (i+4)));
				}
			}
		}
	}
}

static INLINE void SaveRegs() {
        memcpy(regs, psxRegs.GPR.r, 32*4);
        regs[32] = psxRegs.GPR.n.lo;
        regs[33] = psxRegs.GPR.n.hi;
        regs[34] = psxRegs.pc;
}

void psxBiosException() {
	int i;

	switch (psxRegs.CP0.n.Cause & 0x3c) {
		case 0x00: // Interrupt
#ifdef PSXCPU_LOG
//			PSXCPU_LOG("interrupt\n");
#endif
			SaveRegs();

			biosInterrupt();

			for (i=0; i<8; i++) {
				if (SysIntRP[i]) {
					u32 *queue = (u32*)PSXM(SysIntRP[i]);

					s0 = BFLIP32(queue[2]);
					softCall(BFLIP32(queue[1]));
				}
			}

			if (jmp_int != NULL) {
				int i;

				psxHwWrite32(0x1f801070, 0xffffffff);

				ra = BFLIP32(jmp_int[0]);
				sp = BFLIP32(jmp_int[1]);
				fp = BFLIP32(jmp_int[2]);
				for (i=0; i<8; i++) // s0-s7
					 psxRegs.GPR.r[16+i] = BFLIP32(jmp_int[3+i]);
				gp = BFLIP32(jmp_int[11]);

				v0 = 1;
				pc0 = ra;
				return;
			}
			psxHwWrite16(0x1f801070, 0);
			break;
		case 0x20: // Syscall
#ifdef PSXCPU_LOG
//			PSXCPU_LOG("syscall exp %x\n", a0);
#endif
			switch (a0) {
				case 1: // EnterCritical - disable irq's
					psxRegs.CP0.n.Status&=~0x404; break;
				case 2: // ExitCritical - enable irq's
					psxRegs.CP0.n.Status|= 0x404; break;
			}
			pc0 = psxRegs.CP0.n.EPC + 4;

			psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
								  ((psxRegs.CP0.n.Status & 0x3c) >> 2);
			return;
		default:
#ifdef PSXCPU_LOG
			PSXCPU_LOG("unk exp\n");
#endif
			break;
	}

	pc0 = psxRegs.CP0.n.EPC;
	if (psxRegs.CP0.n.Cause & 0x80000000) pc0+=4;

	psxRegs.CP0.n.Status = (psxRegs.CP0.n.Status & 0xfffffff0) |
						  ((psxRegs.CP0.n.Status & 0x3c) >> 2);
}