/*========================================================================= paul.cpp Author: PKG Created: Project: Spongebob Purpose: Copyright (c) 2000 Climax Development Ltd ===========================================================================*/ /*---------------------------------------------------------------------- Includes -------- */ #include "except.h" #ifdef __INSTALL_EXCEPTION_HANDLER__ #ifndef _GLOBAL_HEADER_ #include "global.h" #endif #ifndef __GFX_FONT_H__ #include "gfx\font.h" #endif #ifndef __VID_HEADER_ #include "system\vid.h" #endif #ifndef __SYSTEM_LNKOPT_H__ #include "system\lnkopt.h" #endif #ifndef __SYSTEM_GSTATE_H__ #include "system\gstate.h" #endif /* Std Lib ------- */ #include #include #include #include /* Data ---- */ /*---------------------------------------------------------------------- Tyepdefs && Defines ------------------- */ // Offsets in the register dump list enum { OFS_AT,OFS_V0,OFS_V1,OFS_A0,OFS_A1,OFS_A2,OFS_A3,OFS_T0,OFS_T1,OFS_T2,OFS_T3, OFS_T4,OFS_T5,OFS_T6,OFS_T7,OFS_S0,OFS_S1,OFS_S2,OFS_S3,OFS_S4,OFS_S5,OFS_S6, OFS_S7,OFS_T8,OFS_T9,OFS_GP,OFS_SP,OFS_FP,OFS_RA,OFS_HI,OFS_LO,OFS_SR,OFS_CA, OFS_EPC }; // Pages enum { PAGE_REGS, PAGE_DUMP, PAGE_VALUES, NUM_PAGES }; /*---------------------------------------------------------------------- Structure defintions -------------------- */ // Used by displayRegisters to define page layout typedef struct { char *m_name; int m_offset; } RegDef; /*---------------------------------------------------------------------- Function Prototypes ------------------- */ static void displayTitle(); static void displayCause(); static void displayRegs(); static void displayDump(); static void displayValues(); static void displayKeys(); static void cls(); static void print(char *_string); static void printAdr(int *_adr); /*---------------------------------------------------------------------- Vars ---- */ // Exception description strings static char *s_exceptionText[]={ "external interrupt", "tlb modification exception", "tlb miss (load or fetch)", "tlb miss (store)", "address error (load or fetch)", "address error (store)", "bus error (fetch)", "bus error (load or store)", "syscall", "break", "reserved instruction", "coprocessor unusable", "arithmetic overflow", "unknown exception", "unknown exception", "unknown exception" }; static char *s_breakText[]={ "6 (overflow)", "7 (div by zero)" }; // Font stuff static FontBank *excFont; static int fontx; static int fonty; static const int LEFTMARGIN=20; static const int TOPMARGIN=20; static const int CHARWIDTH=11; static const int CHARHEIGHT=10; static int currentPage=PAGE_REGS; // Layout for displayRegs() static RegDef s_regDefs[]= { {"at",OFS_AT},{"v0",OFS_V0},{"v1",OFS_V1},{NULL,0}, {"a0",OFS_A0},{"a1",OFS_A1},{"a2",OFS_A2},{NULL,0}, {"a3",OFS_A3},{"t0",OFS_T0},{"t1",OFS_T1},{NULL,0}, {"t2",OFS_T2},{"t3",OFS_T3},{"t4",OFS_T4},{NULL,0}, {"t5",OFS_T5},{"t6",OFS_T6},{"t7",OFS_T7},{NULL,0}, {"s0",OFS_S0},{"s1",OFS_S1},{"s2",OFS_S2},{NULL,0}, {"s3",OFS_S3},{"s4",OFS_S4},{"s5",OFS_S5},{NULL,0}, {"s6",OFS_S6},{"s7",OFS_S7},{"t8",OFS_T8},{NULL,0}, {"t9",OFS_T9},{"gp",OFS_GP},{"sp",OFS_SP},{NULL,0}, {"fp",OFS_FP},{"ra",OFS_RA},{"hi",OFS_HI},{NULL,0}, {"lo",OFS_LO},{"sr",OFS_SR},{"ca",OFS_CA},{NULL,0}, {"epc",OFS_EPC}, }; static int s_numRegs=sizeof(s_regDefs)/sizeof(RegDef); // Pointers for displayDump(); static int *s_viewSp; static int *s_viewPc; // Various externs for displayValues() extern sLList MainRam; extern int MemNodeCount; /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ extern void installExceptionHandler() { install_exc(); excFont=new ("ExcFont") FontBank(); excFont->initialise( &standardFont ); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ void exc_c(void) { static int s_padDelay=50; PadInit(0); s_viewSp=(int *)reg_lst[OFS_SP]; s_viewPc=(int *)reg_lst[OFS_EPC]; while(1) { // Think if(s_padDelay) { s_padDelay--; } else { int pad=PadRead(1); if(pad&PADRdown) { if(++currentPage==NUM_PAGES)currentPage=0; s_padDelay=15; } if(currentPage==PAGE_DUMP) { if(pad&PADL1) s_viewSp-=8; if(pad&PADL2) s_viewSp+=8; if(pad&PADR1) s_viewPc-=8; if(pad&PADR2) s_viewPc+=8; if(pad&PADstart) { s_viewSp=(int *)reg_lst[OFS_SP]; s_viewPc=(int *)reg_lst[OFS_EPC]; } } } // Draw cls(); displayTitle(); displayCause(); switch(currentPage) { case PAGE_REGS: displayRegs(); break; case PAGE_DUMP: displayDump(); break; case PAGE_VALUES: displayValues(); break; } displayKeys(); // Swap while(DrawSync(1)); VidSwapDraw(); PrimDisplay(); } } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void cls() { fontx=LEFTMARGIN; fonty=TOPMARGIN; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void print(char *_string) { char text[2]="?"; while(*_string) { char _next=*_string; if(_next=='\n') { fontx=LEFTMARGIN; fonty+=CHARHEIGHT; } else { text[0]=*_string; excFont->print(fontx+((CHARWIDTH-excFont->getCharWidth(text[0]))/2),fonty,text); fontx+=CHARWIDTH; } _string++; } } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void printAdr(int *_adr) { int chk,dummy_mem,error; char textBuf[64]; chk=(int)_adr; dummy_mem=chk&0xf0000000; chk&=0x0ffffffc; error=1; if(chk<(int)OPT_LinkerOpts.RamSize) error=0; if(chk>0x1f800000&&chk<0x1f800400) error=0; _adr=(int *)(chk|dummy_mem); if(error==0) sprintf(textBuf,"%08x=%08x",(int)(_adr),*_adr); else sprintf(textBuf,"%08x=XXXXXXXX",(int)(_adr)); print(textBuf); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void displayTitle() { static int r=0,g=0,b=0; char textBuf[10]; excFont->setColour(r,g,b); print("["); excFont->setColour(255,255,255); switch(currentPage) { case PAGE_REGS: print("Registers"); break; case PAGE_DUMP: print("Dumps"); break; case PAGE_VALUES: print("Values"); break; } excFont->setColour(r,g,b); print("]\n\n"); r+=8; g+=16; b+=32; } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void displayCause() { char textBuf[100]; int *exc; excFont->setColour(255,0,0); exc=(int*)reg_lst[OFS_EPC]; sprintf(textBuf,"%s",s_exceptionText[reg_lst[OFS_CA]>>2&0x1f]); print(textBuf); if((reg_lst[OFS_CA]>>2&0x1f)==9) { int i=(*exc>>16)-6; if(i==0||i==1) sprintf(textBuf," %s",s_breakText[i]); print(textBuf); } sprintf(textBuf,"\nPC=%08x",(int)exc); print(textBuf); if((reg_lst[OFS_CA]&0x80000000)==0x80000000) print(" in branch delay slot"); print("\n\n"); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void displayRegs() { char textBuf[20]; excFont->setColour(255,255,255); RegDef *regs=s_regDefs; for(int i=0;im_name) { sprintf(textBuf,"%s=%08x ",regs->m_name,reg_lst[regs->m_offset]); } else { sprintf(textBuf,"\n"); } print(textBuf); regs++; } } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void displayDump() { char textBuf[100]; int *sp,*pc; excFont->setColour(255,255,255); sp=s_viewSp; pc=s_viewPc; print("SP PC\n"); for(int i=0;i<10;i++) { // SP if(sp==(int*)reg_lst[OFS_SP]) { print(">"); } else { print(" "); } printAdr(sp); print(" "); sp+=8; // PC if(pc==(int*)reg_lst[OFS_EPC]) { print(">"); } else { print(" "); } printAdr(pc); print("\n"); pc+=8; } } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void displayValues() { char textBuf[256]; CScene *scene; excFont->setColour(255,255,255); print("Memory:\n"); sprintf(textBuf," %ld used in %d nodes (%ld available)\n",MainRam.RamUsed,MemNodeCount,MainRam.TotalRam); print(textBuf); sprintf(textBuf," %dk ram size set in link options\n",(int)(OPT_LinkerOpts.RamSize/1024)); print(textBuf); print("Scene:\n"); scene=GameState::getCurrentScene(); sprintf(textBuf," Current scene: %s\n",scene?scene->getSceneName():"None!?!?"); print(textBuf); scene=GameState::getPendingScene(); sprintf(textBuf," Pending scene: %s\n",scene?scene->getSceneName():"None"); print(textBuf); } /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ static void displayKeys() { char textBuf[256]; excFont->setColour(64,32,128); sprintf(textBuf,"\n\nX=Next page\n"); print(textBuf); textBuf[0]='\0'; switch(currentPage) { case PAGE_REGS: break; case PAGE_DUMP: sprintf(textBuf,"L1/L2=Scroll SP, R1/R2=Scroll PC\nSTART=Reset"); break; case PAGE_VALUES: break; } print(textBuf); } #else /*---------------------------------------------------------------------- Function: Purpose: Params: Returns: ---------------------------------------------------------------------- */ extern void installExceptionHandler() { } extern void exc_c() { } #endif /* __INSTALL_EXCEPTION_HANDLER__ */ /*=========================================================================== end */