diff --git a/Frameworks/lazyusf/lazyusf/cpu.c b/Frameworks/lazyusf/lazyusf/cpu.c index 6596e8a47..66d430fd8 100644 --- a/Frameworks/lazyusf/lazyusf/cpu.c +++ b/Frameworks/lazyusf/lazyusf/cpu.c @@ -74,7 +74,7 @@ void CheckTimer (usf_state_t * state) { state->Timers->CurrentTimerType = count; } if (state->Timers->CurrentTimerType == -1) { - DisplayError("No active timers ???\nEmulation Stoped"); + DisplayError(state, "No active timers ???\nEmulation Stopped"); StopEmulation(state); } for (count = 0; count < MaxTimers; count++) { @@ -363,7 +363,7 @@ void InPermLoop ( usf_state_t * state ) { return; InterruptsDisabled: - DisplayError("Stuck in Permanent Loop"); + DisplayError(state, "Stuck in Permanent Loop"); StopEmulation(state); } diff --git a/Frameworks/lazyusf/lazyusf/interpreter_ops.c b/Frameworks/lazyusf/lazyusf/interpreter_ops.c index 0859b6319..f30297c53 100644 --- a/Frameworks/lazyusf/lazyusf/interpreter_ops.c +++ b/Frameworks/lazyusf/lazyusf/interpreter_ops.c @@ -258,7 +258,8 @@ void r4300i_LH (usf_state_t * state) { if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } if (!r4300i_LH_VAddr(state,Address,&state->GPR[state->Opcode.u.b.rt].UHW[0])) { //if (ShowTLBMisses) { - DisplayError("LH TLB: %X",Address); + // Too spammy + //DisplayError(state, "LH TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { @@ -306,7 +307,8 @@ void r4300i_LBU (usf_state_t * state) { uint32_t Address = state->GPR[state->Opcode.u.c.base].UW[0] + (int16_t)state->Opcode.u.b.offset; if (!r4300i_LB_VAddr(state,Address,&state->GPR[state->Opcode.u.b.rt].UB[0])) { //if (ShowTLBMisses) { - DisplayError("LBU TLB: %X",Address); + // Too spammy + //DisplayError(state, "LBU TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { @@ -319,7 +321,8 @@ void r4300i_LHU (usf_state_t * state) { if ((Address & 1) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } if (!r4300i_LH_VAddr(state,Address,&state->GPR[state->Opcode.u.b.rt].UHW[0])) { //if (ShowTLBMisses) { - DisplayError("LHU TLB: %X",Address); + // Too spammy + //DisplayError(state, "LHU TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { @@ -351,7 +354,8 @@ void r4300i_LWU (usf_state_t * state) { if (!r4300i_LW_VAddr(state,Address,&state->GPR[state->Opcode.u.b.rt].UW[0])) { //if (ShowTLBMisses) { - DisplayError("LWU TLB: %X",Address); + // Too spammy + //DisplayError(state, "LWU TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { @@ -494,7 +498,8 @@ void r4300i_LL (usf_state_t * state) { if (!r4300i_LW_VAddr(state,Address,&state->GPR[state->Opcode.u.b.rt].UW[0])) { //if (ShowTLBMisses) { - DisplayError("LW TLB: %X",Address); + // Too spammy + //DisplayError(state, "LW TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } else { @@ -513,7 +518,8 @@ void r4300i_LWC1 (usf_state_t * state) { if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,1); } if (!r4300i_LW_VAddr(state,Address,&*(uint32_t *)state->FPRFloatLocation[state->Opcode.u.f.ft])) { //if (ShowTLBMisses) { - DisplayError("LWC1 TLB: %X",Address); + // Too spammy + //DisplayError(state, "LWC1 TLB: %X",Address); //} TLB_READ_EXCEPTION(Address); } @@ -524,7 +530,7 @@ void r4300i_SC (usf_state_t * state) { if ((Address & 3) != 0) { ADDRESS_ERROR_EXCEPTION(Address,0); } if (state->LLBit == 1) { if (!r4300i_SW_VAddr(state,Address,state->GPR[state->Opcode.u.b.rt].UW[0])) { - DisplayError("SW TLB: %X",Address); + DisplayError(state, "SW TLB: %X",Address); } } state->GPR[state->Opcode.u.b.rt].UW[0] = state->LLBit; @@ -1331,6 +1337,6 @@ void r4300i_COP1_L_CVT_D (usf_state_t * state) { /************************** Other functions **************************/ void R4300i_UnknownOpcode (usf_state_t * state) { - DisplayError("Unknown R4300i Opcode.\tPC:%08x\tOp:%08x\n", state->PROGRAM_COUNTER,state->Opcode.u.Hex); + DisplayError(state, "Unknown R4300i Opcode.\tPC:%08x\tOp:%08x\n", state->PROGRAM_COUNTER,state->Opcode.u.Hex); StopEmulation(state); } diff --git a/Frameworks/lazyusf/lazyusf/main.c b/Frameworks/lazyusf/lazyusf/main.c index 33ecf9e60..1488639df 100644 --- a/Frameworks/lazyusf/lazyusf/main.c +++ b/Frameworks/lazyusf/lazyusf/main.c @@ -18,14 +18,21 @@ void StopEmulation(usf_state_t * state) state->cpu_running = 0; } -void DisplayError (char * Message, ...) { +void DisplayError (usf_state_t * state, char * Message, ...) { (void)Message; - //char Msg[1000]; - //va_list ap; + va_list ap; + + size_t len = strlen( state->error_message ); + + if ( len ) + state->error_message[ len++ ] = '\n'; - //va_start( ap, Message ); - //vsprintf( Msg, Message, ap ); - //va_end( ap ); + va_start( ap, Message ); + vsprintf( state->error_message + len, Message, ap ); + va_end( ap ); + + state->last_error = state->error_message; + StopEmulation( state ); //printf("Error: %s\n", Msg); } diff --git a/Frameworks/lazyusf/lazyusf/main.h b/Frameworks/lazyusf/lazyusf/main.h index 62aec0390..df5ea9c23 100644 --- a/Frameworks/lazyusf/lazyusf/main.h +++ b/Frameworks/lazyusf/lazyusf/main.h @@ -2,9 +2,5 @@ #include "usf.h" -#define CPU_Default -1 -#define CPU_Interpreter 0 -#define CPU_Recompiler 1 - -void DisplayError (char * Message, ...); +void DisplayError (usf_state_t *, char * Message, ...); void StopEmulation(usf_state_t *); diff --git a/Frameworks/lazyusf/lazyusf/memory.c b/Frameworks/lazyusf/lazyusf/memory.c index b24464542..6bb506975 100644 --- a/Frameworks/lazyusf/lazyusf/memory.c +++ b/Frameworks/lazyusf/lazyusf/memory.c @@ -93,7 +93,7 @@ int32_t Allocate_Memory ( void * state ) { USF_STATE->N64MEM = USF_STATE->MemChunk + 0x100000 * sizeof(uintptr_t) + 0x10000; if(USF_STATE->N64MEM == NULL) { - DisplayError("Failed to allocate N64MEM"); + DisplayError(USF_STATE, "Failed to allocate N64MEM"); return 0; } @@ -695,7 +695,7 @@ int32_t r4300i_SW_NonMemory ( usf_state_t * state, uint32_t PAddr, uint32_t Valu PI_DMA_WRITE(state); break; case 0x04600010: - //if ((Value & PI_SET_RESET) != 0 ) { DisplayError("reset Controller"); } + //if ((Value & PI_SET_RESET) != 0 ) { DisplayError(state, "reset Controller"); } if ((Value & PI_CLR_INTR) != 0 ) { MI_INTR_REG &= ~MI_INTR_PI; CheckInterrupts(state); diff --git a/Frameworks/lazyusf/lazyusf/rsp/execute.h b/Frameworks/lazyusf/lazyusf/rsp/execute.h index bebc42223..8afbb7238 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/execute.h +++ b/Frameworks/lazyusf/lazyusf/rsp/execute.h @@ -21,6 +21,7 @@ NOINLINE void run_task(usf_state_t * state) { register int PC; + int wrap_count = 0; if (CFG_WAIT_FOR_CPU_HOST != 0) { @@ -37,6 +38,11 @@ NOINLINE void run_task(usf_state_t * state) inst = *(uint32_t *)(state->IMEM + FIT_IMEM(PC)); #ifdef EMULATE_STATIC_PC PC = (PC + 0x004); + if ( FIT_IMEM(PC) == 0 && ++wrap_count == 32 ) + { + message( state, "RSP execution presumably caught in an infinite loop", 3 ); + break; + } EX: #endif #ifdef SP_EXECUTE_LOG @@ -445,6 +451,11 @@ EX: { state->stage = 2*state->stage; /* next IW in branch delay slot? */ PC = (PC + 0x004) & 0xFFC; + if ( FIT_IMEM(PC) == 0 && ++wrap_count == 32 ) + { + message( state, "RSP execution presumably caught in an infinite loop", 3 ); + break; + } SP_PC_REG = 0x04001000 + PC; } continue; @@ -467,7 +478,7 @@ BRANCH: {} else /* ??? unknown, possibly external intervention from CPU memory map */ { - message("SP_SET_HALT", 3); + message(state, "SP_SET_HALT", 3); return; } SP_STATUS_REG &= ~0x00000001; /* CPU restarts with the correct SIGs. */ diff --git a/Frameworks/lazyusf/lazyusf/rsp/rsp.c b/Frameworks/lazyusf/lazyusf/rsp/rsp.c index 2aec78eeb..3aa510c66 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/rsp.c +++ b/Frameworks/lazyusf/lazyusf/rsp/rsp.c @@ -21,6 +21,7 @@ #include "../dma.h" #include "../exception.h" +#include "../main.h" #include "../memory.h" #include "../registers.h" @@ -38,7 +39,7 @@ void real_run_rsp(usf_state_t * state, uint32_t cycles) if (SP_STATUS_REG & 0x00000003) { - message("SP_STATUS_HALT", 3); + message(state, "SP_STATUS_HALT", 3); return; } run_task(state); diff --git a/Frameworks/lazyusf/lazyusf/rsp/rsp.h b/Frameworks/lazyusf/lazyusf/rsp/rsp.h index fc9041f28..e408fb3e2 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/rsp.h +++ b/Frameworks/lazyusf/lazyusf/rsp/rsp.h @@ -42,10 +42,12 @@ typedef unsigned char byte; typedef uint32_t RCPREG; #endif -NOINLINE void message(const char* body, int priority) +NOINLINE void message(usf_state_t * state, const char* body, int priority) { (void)body; (void)priority; + if ( priority > 1 ) + DisplayError( state, "%s", body ); } /* diff --git a/Frameworks/lazyusf/lazyusf/rsp/su.h b/Frameworks/lazyusf/lazyusf/rsp/su.h index 48e79786a..fd4177821 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/su.h +++ b/Frameworks/lazyusf/lazyusf/rsp/su.h @@ -143,7 +143,7 @@ static void MT_DMA_WRITE_LENGTH(usf_state_t * state, int rt) static void MT_SP_STATUS(usf_state_t * state, int rt) { if (state->SR[rt] & 0xFE000040) - message("MTC0\nSP_STATUS", 2); + message(state, "MTC0\nSP_STATUS", 2); SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000001) << 0); SP_STATUS_REG |= (!!(state->SR[rt] & 0x00000002) << 0); SP_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000004) << 1); @@ -184,21 +184,21 @@ static void MT_CMD_START(usf_state_t * state, int rt) const uint32_t source = state->SR[rt] & 0xFFFFFFF8; /* Funnelcube demo */ if (DPC_BUFBUSY_REG) /* lock hazards not implemented */ - message("MTC0\nCMD_START", 0); + message(state, "MTC0\nCMD_START", 0); DPC_END_REG = DPC_CURRENT_REG = DPC_START_REG = source; return; } static void MT_CMD_END(usf_state_t * state, int rt) { if (DPC_BUFBUSY_REG) - message("MTC0\nCMD_END", 0); /* This is just CA-related. */ + message(state, "MTC0\nCMD_END", 0); /* This is just CA-related. */ DPC_END_REG = state->SR[rt] & 0xFFFFFFF8; return; } static void MT_CMD_STATUS(usf_state_t * state, int rt) { if (state->SR[rt] & 0xFFFFFD80) /* unsupported or reserved bits */ - message("MTC0\nCMD_STATUS", 2); + message(state, "MTC0\nCMD_STATUS", 2); DPC_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000001) << 0); DPC_STATUS_REG |= (!!(state->SR[rt] & 0x00000002) << 0); DPC_STATUS_REG &= ~(!!(state->SR[rt] & 0x00000004) << 1); @@ -214,7 +214,7 @@ static void MT_CMD_STATUS(usf_state_t * state, int rt) } static void MT_CMD_CLOCK(usf_state_t * state, int rt) { - message("MTC0\nCMD_CLOCK", 1); /* read-only?? */ + message(state, "MTC0\nCMD_CLOCK", 1); /* read-only?? */ DPC_CLOCK_REG = state->SR[rt]; return; /* Appendix says this is RW; elsewhere it says R. */ } @@ -225,7 +225,7 @@ static void MT_READ_ONLY(usf_state_t * state, int rt) //char text[64]; //sprintf(text, "MTC0\nInvalid write attempt.\nstate->SR[%i] = 0x%08X", rt, state->SR[rt]); - //message(text, 2); + //message(state, text, 2); return; } @@ -419,14 +419,14 @@ INLINE static void LSV(usf_state_t * state, int vt, int element, int offset, int if (e & 0x1) { - message("LSV\nIllegal element.", 3); + message(state, "LSV\nIllegal element.", 3); return; } addr = (state->SR[base] + 2*offset) & 0x00000FFF; correction = addr % 0x004; if (correction == 0x003) { - message("LSV\nWeird addr.", 3); + message(state, "LSV\nWeird addr.", 3); return; } VR_S(vt, e) = *(short *)(state->DMEM + addr - HES(0x000)*(correction - 1)); @@ -440,13 +440,13 @@ INLINE static void LLV(usf_state_t * state, int vt, int element, int offset, int if (e & 0x1) { - message("LLV\nOdd element.", 3); + message(state, "LLV\nOdd element.", 3); return; } /* Illegal (but still even) elements are used by Boss Game Studios. */ addr = (state->SR[base] + 4*offset) & 0x00000FFF; if (addr & 0x00000001) { - message("LLV\nOdd addr.", 3); + message(state, "LLV\nOdd addr.", 3); return; } correction = HES(0x000)*(addr%0x004 - 1); @@ -462,7 +462,7 @@ INLINE static void LDV(usf_state_t * state, int vt, int element, int offset, int if (e & 0x1) { - message("LDV\nOdd element.", 3); + message(state, "LDV\nOdd element.", 3); return; } /* Illegal (but still even) elements are used by Boss Game Studios. */ addr = (state->SR[base] + 8*offset) & 0x00000FFF; @@ -568,13 +568,13 @@ INLINE static void SLV(usf_state_t * state, int vt, int element, int offset, int if ((e & 0x1) || e > 0xC) /* must support illegal even elements in F3DEX2 */ { - message("SLV\nIllegal element.", 3); + message(state, "SLV\nIllegal element.", 3); return; } addr = (state->SR[base] + 4*offset) & 0x00000FFF; if (addr & 0x00000001) { - message("SLV\nOdd addr.", 3); + message(state, "SLV\nOdd addr.", 3); return; } correction = HES(0x000)*(addr%0x004 - 1); @@ -680,7 +680,7 @@ INLINE static void LPV(usf_state_t * state, int vt, int element, int offset, int if (e != 0x0) { - message("LPV\nIllegal element.", 3); + message(state, "LPV\nIllegal element.", 3); return; } addr = (state->SR[base] + 8*offset) & 0x00000FFF; @@ -911,7 +911,7 @@ INLINE static void SPV(usf_state_t * state, int vt, int element, int offset, int if (e != 0x0) { - message("SPV\nIllegal element.", 3); + message(state, "SPV\nIllegal element.", 3); return; } addr = (state->SR[base] + 8*offset) & 0x00000FFF; @@ -1023,7 +1023,7 @@ INLINE static void SUV(usf_state_t * state, int vt, int element, int offset, int if (e != 0x0) { - message("SUV\nIllegal element.", 3); + message(state, "SUV\nIllegal element.", 3); return; } addr = (state->SR[base] + 8*offset) & 0x00000FFF; @@ -1054,7 +1054,7 @@ INLINE static void SUV(usf_state_t * state, int vt, int element, int offset, int state->DMEM[addr + BES(0x003)] = (unsigned char)(state->VR[vt][07] >> 7); return; default: /* Completely legal, just never seen it be done. */ - message("SUV\nWeird addr.", 3); + message(state, "SUV\nWeird addr.", 3); return; } } @@ -1070,13 +1070,13 @@ static void LHV(usf_state_t * state, int vt, int element, int offset, int base) if (e != 0x0) { - message("LHV\nIllegal element.", 3); + message(state, "LHV\nIllegal element.", 3); return; } addr = (state->SR[base] + 16*offset) & 0x00000FFF; if (addr & 0x0000000E) { - message("LHV\nIllegal addr.", 3); + message(state, "LHV\nIllegal addr.", 3); return; } addr ^= MES(00); @@ -1102,7 +1102,7 @@ NOINLINE static void LFV(usf_state_t * state, int vt, int element, int offset, i sprintf(debugger, "%s $v%i[0x%X], 0x%03X($%i)", "LFV", vt, element, offset & 0xFFF, base); - message(debugger, 3);*/ + message(state, debugger, 3);*/ return; } static void SHV(usf_state_t * state, int vt, int element, int offset, int base) @@ -1112,13 +1112,13 @@ static void SHV(usf_state_t * state, int vt, int element, int offset, int base) if (e != 0x0) { - message("SHV\nIllegal element.", 3); + message(state, "SHV\nIllegal element.", 3); return; } addr = (state->SR[base] + 16*offset) & 0x00000FFF; if (addr & 0x0000000E) { - message("SHV\nIllegal addr.", 3); + message(state, "SHV\nIllegal addr.", 3); return; } addr ^= MES(00); @@ -1155,7 +1155,7 @@ static void SFV(usf_state_t * state, int vt, int element, int offset, int base) state->DMEM[addr + 0x00C] = (unsigned char)(state->VR[vt][07] >> 7); return; default: - message("SFV\nIllegal element.", 3); + message(state, "SFV\nIllegal element.", 3); return; } } @@ -1172,13 +1172,13 @@ INLINE static void LQV(usf_state_t * state, int vt, int element, int offset, int if (e & 0x1) { - message("LQV\nOdd element.", 3); + message(state, "LQV\nOdd element.", 3); return; } addr = (state->SR[base] + 16*offset) & 0x00000FFF; if (addr & 0x00000001) { - message("LQV\nOdd addr.", 3); + message(state, "LQV\nOdd addr.", 3); return; } b = addr & 0x0000000F; @@ -1247,13 +1247,13 @@ static void LRV(usf_state_t * state, int vt, int element, int offset, int base) if (e != 0x0) { - message("LRV\nIllegal element.", 3); + message(state, "LRV\nIllegal element.", 3); return; } addr = (state->SR[base] + 16*offset) & 0x00000FFF; if (addr & 0x00000001) { - message("LRV\nOdd addr.", 3); + message(state, "LRV\nOdd addr.", 3); return; } b = addr & 0x0000000F; @@ -1360,7 +1360,7 @@ INLINE static void SQV(usf_state_t * state, int vt, int element, int offset, int *(short *)(state->DMEM + addr + HES(0x00E)) = state->VR[vt][04]; return; default: - message("SQV\nWeird addr.", 3); + message(state, "SQV\nWeird addr.", 3); return; } } @@ -1372,13 +1372,13 @@ static void SRV(usf_state_t * state, int vt, int element, int offset, int base) if (e != 0x0) { - message("SRV\nIllegal element.", 3); + message(state, "SRV\nIllegal element.", 3); return; } addr = (state->SR[base] + 16*offset) & 0x00000FFF; if (addr & 0x00000001) { - message("SRV\nOdd addr.", 3); + message(state, "SRV\nOdd addr.", 3); return; } b = addr & 0x0000000F; @@ -1444,18 +1444,18 @@ INLINE static void LTV(usf_state_t * state, int vt, int element, int offset, int if (e & 1) { - message("LTV\nIllegal element.", 3); + message(state, "LTV\nIllegal element.", 3); return; } if (vt & 07) { - message("LTV\nUncertain case!", 3); + message(state, "LTV\nUncertain case!", 3); return; /* For LTV I am not sure; for STV I have an idea. */ } addr = (state->SR[base] + 16*offset) & 0x00000FFF; if (addr & 0x0000000F) { - message("LTV\nIllegal addr.", 3); + message(state, "LTV\nIllegal addr.", 3); return; } for (i = 0; i < 8; i++) /* SGI screwed LTV up on N64. See STV instead. */ @@ -1474,7 +1474,7 @@ NOINLINE static void SWV(usf_state_t * state, int vt, int element, int offset, i sprintf(debugger, "%s $v%i[0x%X], 0x%03X($%i)", "SWV", vt, element, offset & 0xFFF, base); - message(debugger, 3);*/ + message(state, debugger, 3);*/ return; } INLINE static void STV(usf_state_t * state, int vt, int element, int offset, int base) @@ -1485,18 +1485,18 @@ INLINE static void STV(usf_state_t * state, int vt, int element, int offset, int if (e & 1) { - message("STV\nIllegal element.", 3); + message(state, "STV\nIllegal element.", 3); return; } if (vt & 07) { - message("STV\nUncertain case!", 2); + message(state, "STV\nUncertain case!", 2); return; /* vt &= 030; */ } addr = (state->SR[base] + 16*offset) & 0x00000FFF; if (addr & 0x0000000F) { - message("STV\nIllegal addr.", 3); + message(state, "STV\nIllegal addr.", 3); return; } for (i = 0; i < 8; i++) diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h index abf08e8e6..7c56c7f25 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vmacq.h @@ -19,6 +19,6 @@ static void VMACQ(usf_state_t * state, int vd, int vs, int vt, int e) vd &= vs &= vt &= e &= 0; /* unused */ if (vd != vs || vt != e) return; - message("VMACQ\nUnimplemented.", 3); /* untested, any N64 ROMs use this?? */ + message(state, "VMACQ\nUnimplemented.", 3); /* untested, any N64 ROMs use this?? */ return; } diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h index 2b9bd23e3..92227ee84 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vnop.h @@ -20,6 +20,6 @@ static void VNOP(usf_state_t * state, int vd, int vs, int vt, int e) (void)state; if (WB_inhibit) - return; /* message("VNOP", WB_inhibit); */ + return; /* message(state, "VNOP", WB_inhibit); */ return; } diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h index 34bb56ac7..e033c7a3d 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vrsq.h @@ -16,7 +16,7 @@ static void VRSQ(usf_state_t * state, int vd, int de, int vt, int e) { - message("VRSQ\nUntested.", 1); + message(state, "VRSQ\nUntested.", 1); state->DivIn = (int)state->VR[vt][e & 07]; do_div(state, state->DivIn, SP_DIV_SQRT_YES, SP_DIV_PRECISION_SINGLE); SHUFFLE_VECTOR(VACC_L, state->VR[vt], e); diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h index 4263d90b6..ae0e26e2b 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vsaw.h @@ -33,7 +33,7 @@ static void VSAR(int vd, int vs, int vt, int e) */ if (e > 2) { - message("VSAR\nInvalid mask.", 2); + message(state, "VSAR\nInvalid mask.", 2); for (i = 0; i < N; i++) VR[vd][i] = 0x0000; /* override behavior (zilmar) */ } @@ -58,7 +58,7 @@ static void VSAW(usf_state_t * state, int vd, int vs, int vt, int e) if (e > 0x2) { /* branch very unlikely...never seen a game do VSAW illegally */ - message("VSAW\nIllegal mask.", 2); + message(state, "VSAW\nIllegal mask.", 2); for (i = 0; i < N; i++) state->VR[vd][i] = 0x0000; /* override behavior (zilmar) */ return; diff --git a/Frameworks/lazyusf/lazyusf/rsp/vu/vu.h b/Frameworks/lazyusf/lazyusf/rsp/vu/vu.h index cfaac480c..7981bdc67 100644 --- a/Frameworks/lazyusf/lazyusf/rsp/vu/vu.h +++ b/Frameworks/lazyusf/lazyusf/rsp/vu/vu.h @@ -53,14 +53,14 @@ static void res_V(usf_state_t * state, int vd, int vs, int vt, int e) vs = vt = e = 0; if (vs != vt || vt != e) return; - message("C2\nRESERVED", 2); /* uncertain how to handle reserved, untested */ + message(state, "C2\nRESERVED", 2); /* uncertain how to handle reserved, untested */ for (i = 0; i < N; i++) state->VR[vd][i] = 0x0000; /* override behavior (bpoint) */ return; } static void res_M(usf_state_t * state, int vd, int vs, int vt, int e) { - message("VMUL IQ", 2); + message(state, "VMUL IQ", 2); res_V(state, vd, vs, vt, e); return; /* Ultra64 OS did have these, so one could implement this ext. */ } diff --git a/Frameworks/lazyusf/lazyusf/usf.c b/Frameworks/lazyusf/lazyusf/usf.c index bdc85e908..9d5d39244 100644 --- a/Frameworks/lazyusf/lazyusf/usf.c +++ b/Frameworks/lazyusf/lazyusf/usf.c @@ -14,7 +14,7 @@ #include "usf_internal.h" -size_t get_usf_state_size() +size_t usf_get_state_size() { return sizeof(usf_state_t) + 8192; } @@ -22,7 +22,7 @@ size_t get_usf_state_size() void usf_clear(void * state) { size_t offset; - memset(state, 0, get_usf_state_size()); + memset(state, 0, usf_get_state_size()); offset = 4096 - (((uintptr_t)state) & 4095); USF_STATE_HELPER->offset_to_structure = offset; @@ -155,7 +155,7 @@ int usf_upload_section(void * state, const uint8_t * data, size_t size) return 0; } -static void usf_startup(void * state) +static int usf_startup(void * state) { // Detect the Ramsize before the memory allocation @@ -168,15 +168,24 @@ static void usf_startup(void * state) } else if(*(uint32_t*)(USF_STATE->savestatespace + 4) == 0x800000) USF_STATE->RdramSize = 0x800000; - Allocate_Memory(state); + if ( !Allocate_Memory(state) ) + return -1; StartEmulationFromSave(USF_STATE, USF_STATE->savestatespace); + + return 0; } -void usf_render(void * state, int16_t * buffer, size_t count, int32_t * sample_rate) +const char * usf_render(void * state, int16_t * buffer, size_t count, int32_t * sample_rate) { + USF_STATE->last_error = 0; + USF_STATE->error_message[0] = '\0'; + if ( !USF_STATE->MemoryState ) - usf_startup( USF_STATE ); + { + if ( usf_startup( USF_STATE ) < 0 ) + return USF_STATE->last_error; + } if ( USF_STATE->samples_in_buffer ) { @@ -195,7 +204,7 @@ void usf_render(void * state, int16_t * buffer, size_t count, int32_t * sample_r if ( USF_STATE->samples_in_buffer ) { memmove( USF_STATE->samplebuf, USF_STATE->samplebuf + do_max * 2, sizeof(int16_t) * 2 * USF_STATE->samples_in_buffer ); - return; + return 0; } if ( buffer ) @@ -213,6 +222,8 @@ void usf_render(void * state, int16_t * buffer, size_t count, int32_t * sample_r if ( sample_rate ) *sample_rate = USF_STATE->SampleRate; + + return USF_STATE->last_error; } void usf_restart(void * state) diff --git a/Frameworks/lazyusf/lazyusf/usf.h b/Frameworks/lazyusf/lazyusf/usf.h index 111e88317..05ac5797e 100644 --- a/Frameworks/lazyusf/lazyusf/usf.h +++ b/Frameworks/lazyusf/lazyusf/usf.h @@ -42,8 +42,9 @@ int usf_upload_section(void * state, const uint8_t * data, size_t size); A null pointer is acceptable, in which case samples will be discarded. Requesting zero samples with a null pointer is an acceptable way to force at least one block of samples to render and return the current - sample rate in the variable passed in. */ -void usf_render(void * state, int16_t * buffer, size_t count, int32_t * sample_rate); + sample rate in the variable passed in. + Returns 0 on success, or a pointer to the last error message on failure. */ +const char * usf_render(void * state, int16_t * buffer, size_t count, int32_t * sample_rate); /* Reloads the ROM and save state, effectively restarting emulation. Also discards any buffered sample data. */ diff --git a/Frameworks/lazyusf/lazyusf/usf_internal.h b/Frameworks/lazyusf/lazyusf/usf_internal.h index 2a688294f..47368c32a 100644 --- a/Frameworks/lazyusf/lazyusf/usf_internal.h +++ b/Frameworks/lazyusf/lazyusf/usf_internal.h @@ -71,6 +71,9 @@ struct usf_state int16_t samplebuf[16384]; size_t samples_in_buffer; + const char * last_error; + char error_message[1024]; + // cpu.c uint32_t NextInstruction, JumpToLocation, AudioIntrReg; CPU_ACTION * CPU_Action; diff --git a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm index 632726f9a..32692c720 100644 --- a/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm +++ b/Plugins/HighlyComplete/HighlyComplete/HCDecoder.mm @@ -1010,7 +1010,7 @@ static int usf_info(void * context, const char * name, const char * value) struct usf_loader_state state; memset( &state, 0, sizeof(state) ); - state.emu_state = malloc( get_usf_state_size() ); + state.emu_state = malloc( usf_get_state_size() ); usf_clear( state.emu_state ); @@ -1022,7 +1022,8 @@ static int usf_info(void * context, const char * name, const char * value) usf_set_compare( state.emu_state, state.enablecompare ); usf_set_fifo_full( state.emu_state, state.enablefifofull ); - usf_render( state.emu_state, 0, 0, &samplerate ); + if ( usf_render( state.emu_state, 0, 0, &samplerate ) != 0 ) + return NO; sampleRate = samplerate; @@ -1294,7 +1295,8 @@ static int usf_info(void * context, const char * name, const char * value) { int32_t samplerate; - usf_render( emulatorCore, (int16_t*) buf, frames, &samplerate ); + if ( usf_render( emulatorCore, (int16_t*) buf, frames, &samplerate ) != 0 ) + return 0; sampleRate = samplerate; } @@ -1523,7 +1525,8 @@ static int usf_info(void * context, const char * name, const char * value) { ssize_t howmany = frame - framesRead; if (howmany > 1024) howmany = 1024; - usf_render(emulatorCore, temp, howmany, NULL); + if ( usf_render(emulatorCore, temp, howmany, NULL) != 0 ) + return -1; framesRead += howmany; } while (framesRead < frame); }