mirror of https://github.com/PCSX2/pcsx2.git
579 lines
15 KiB
C
579 lines
15 KiB
C
/* Pcsx2 - Pc Ps2 Emulator
|
|
* Copyright (C) 2002-2003 Pcsx2 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "Common.h"
|
|
#include "Memory.h"
|
|
#include "Hw.h"
|
|
#include "Debug.h"
|
|
#include "R3000A.h"
|
|
#include "VUmicro.h"
|
|
#include "GS.h"
|
|
|
|
static int inter;
|
|
|
|
PCSX2_ALIGNED16(cpuRegisters cpuRegs);
|
|
PCSX2_ALIGNED16(fpuRegisters fpuRegs);
|
|
PCSX2_ALIGNED16(tlbs tlb[48]);
|
|
PCSX2_ALIGNED16(GPR_reg64 g_cpuConstRegs[32]) = {0};
|
|
|
|
u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0;
|
|
R5900cpu *Cpu;
|
|
|
|
int EEsCycle;
|
|
u32 EEoCycle, IOPoCycle;
|
|
|
|
extern u32 dwSaveVersion;
|
|
|
|
int cpuInit()
|
|
{
|
|
int ret;
|
|
|
|
SysPrintf("PCSX2 v" PCSX2_VERSION " save ver: %x\n", dwSaveVersion);
|
|
SysPrintf("Color Legend: White - PCSX2 message\n");
|
|
SysPrintf(COLOR_GREEN " Green - EE sio2 printf\n" COLOR_RESET);
|
|
SysPrintf(COLOR_RED " Red - IOP printf\n" COLOR_RESET);
|
|
|
|
printf("%d", (u32)&cpuRegs.pc - (u32)&cpuRegs);
|
|
|
|
InitFPUOps();
|
|
cpudetectInit();
|
|
|
|
cpuRegs.constzero = 0;
|
|
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
|
|
|
|
ret = Cpu->Init();
|
|
if (ret == -1 && CHECK_EEREC) {
|
|
SysMessage(_("Error initializing Recompiler, switching to Interpreter"));
|
|
Config.Options &= ~(PCSX2_EEREC|PCSX2_VU1REC|PCSX2_VU0REC);
|
|
Cpu = &intCpu;
|
|
ret = Cpu->Init();
|
|
}
|
|
|
|
#ifdef WIN32_VIRTUAL_MEM
|
|
if (memInit() == -1) {
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si;
|
|
char strdir[255], strexe[255];
|
|
if( MessageBox(NULL, "Failed to allocate enough physical memory to run pcsx2. Try closing\n"
|
|
"down background programs, restarting windows, or buying more memory.\n\n"
|
|
"Launch TLB version of pcsx2 (pcsx2t.exe)?", "Memory Allocation Error", MB_YESNO) == IDYES ) {
|
|
|
|
GetCurrentDirectory(ARRAYSIZE(strdir), strdir);
|
|
_snprintf(strexe, ARRAYSIZE(strexe), "%s\\pcsx2t.exe", strdir);
|
|
|
|
memset(&si, 0, sizeof(si));
|
|
|
|
if( !CreateProcess(strexe, "", NULL, NULL, FALSE, DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP, NULL, strdir, &si, &pi)) {
|
|
_snprintf(strdir, ARRAYSIZE(strexe), "Failed to launch %s\n", strexe);
|
|
MessageBox(NULL, strdir, "Failure", MB_OK);
|
|
}
|
|
else {
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
#endif
|
|
if (hwInit() == -1) return -1;
|
|
if (vu0Init() == -1) return -1;
|
|
if (vu1Init() == -1) return -1;
|
|
#ifndef WIN32_VIRTUAL_MEM
|
|
if (memInit() == -1) return -1;
|
|
#endif
|
|
|
|
#ifdef PCSX2_DEVBUILD
|
|
Log = 0;
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
void cpuReset()
|
|
{
|
|
Cpu->Reset();
|
|
|
|
memReset();
|
|
|
|
memset(&cpuRegs, 0, sizeof(cpuRegs));
|
|
memset(&fpuRegs, 0, sizeof(fpuRegs));
|
|
memset(&tlb, 0, sizeof(tlb));
|
|
|
|
cpuRegs.pc = 0xbfc00000; ///set pc reg to stack
|
|
cpuRegs.CP0.n.Config = 0x440;
|
|
cpuRegs.CP0.n.Status.val = 0x70400004; //0x10900000 <-- wrong; // COP0 enabled | BEV = 1 | TS = 1
|
|
cpuRegs.CP0.n.PRid = 0x00002e20; // PRevID = Revision ID, same as R5900
|
|
fpuRegs.fprc[0] = 0x00002e00; // fpu Revision..
|
|
fpuRegs.fprc[31] = 0x01000001; // fpu Status/Control
|
|
|
|
vu0Reset();
|
|
vu1Reset();
|
|
hwReset();
|
|
vif0Reset();
|
|
vif1Reset();
|
|
rcntInit();
|
|
psxReset();
|
|
}
|
|
|
|
void cpuShutdown()
|
|
{
|
|
hwShutdown();
|
|
// biosShutdown();
|
|
psxShutdown();
|
|
vu0Shutdown();
|
|
vu1Shutdown();
|
|
memShutdown();
|
|
gsShutdown();
|
|
disR5900FreeSyms();
|
|
|
|
Cpu->Shutdown();
|
|
}
|
|
|
|
void cpuException(u32 code, u32 bd) {
|
|
u32 offset;
|
|
cpuRegs.CP0.n.Cause = code & 0xffff;
|
|
|
|
if(cpuRegs.CP0.n.Status.b.ERL == 0){ //Error Level 0-1
|
|
if(((code & 0x7C) >= 0x8) && ((code & 0x7C) <= 0xC)) offset = 0x0; //TLB Refill
|
|
else if ((code & 0x7C) == 0x0) offset = 0x200; //Interrupt
|
|
else offset = 0x180; // Everything else
|
|
|
|
|
|
if (cpuRegs.CP0.n.Status.b.EXL == 0) {
|
|
cpuRegs.CP0.n.Status.b.EXL = 1;
|
|
if (bd) {
|
|
SysPrintf("branch delay!!\n");
|
|
cpuRegs.CP0.n.EPC = cpuRegs.pc - 4;
|
|
cpuRegs.CP0.n.Cause |= 0x80000000;
|
|
} else {
|
|
cpuRegs.CP0.n.EPC = cpuRegs.pc;
|
|
cpuRegs.CP0.n.Cause &= ~0x80000000;
|
|
}
|
|
} else {
|
|
offset = 0x180; //Overrride the cause
|
|
SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code);
|
|
}
|
|
if (cpuRegs.CP0.n.Status.b.BEV == 0) {
|
|
cpuRegs.pc = 0x80000000 + offset;
|
|
} else {
|
|
cpuRegs.pc = 0xBFC00200 + offset;
|
|
}
|
|
} else { //Error Level 2
|
|
SysPrintf("FIX ME: Level 2 cpuException\n");
|
|
if((code & 0x38000) <= 0x8000 ) { //Reset / NMI
|
|
cpuRegs.pc = 0xBFC00000;
|
|
SysPrintf("Reset request\n");
|
|
UpdateCP0Status();
|
|
return;
|
|
} else if((code & 0x38000) == 0x10000) offset = 0x80; //Performance Counter
|
|
else if((code & 0x38000) == 0x18000) offset = 0x100; //Debug
|
|
else SysPrintf("Unknown Level 2 Exception!! Cause %x\n", code);
|
|
|
|
if (cpuRegs.CP0.n.Status.b.EXL == 0) {
|
|
cpuRegs.CP0.n.Status.b.EXL = 1;
|
|
if (bd) {
|
|
SysPrintf("branch delay!!\n");
|
|
cpuRegs.CP0.n.EPC = cpuRegs.pc - 4;
|
|
cpuRegs.CP0.n.Cause |= 0x80000000;
|
|
} else {
|
|
cpuRegs.CP0.n.EPC = cpuRegs.pc;
|
|
cpuRegs.CP0.n.Cause &= ~0x80000000;
|
|
}
|
|
} else {
|
|
offset = 0x180; //Overrride the cause
|
|
SysPrintf("cpuException: Status.EXL = 1 cause %x\n", code);
|
|
}
|
|
if (cpuRegs.CP0.n.Status.b.DEV == 0) {
|
|
cpuRegs.pc = 0x80000000 + offset;
|
|
} else {
|
|
cpuRegs.pc = 0xBFC00200 + offset;
|
|
}
|
|
}
|
|
UpdateCP0Status();
|
|
}
|
|
|
|
void cpuTlbMiss(u32 addr, u32 bd, u32 excode) {
|
|
SysPrintf("cpuTlbMiss %x, %x, status=%x, code=%x\n", cpuRegs.pc, cpuRegs.cycle, cpuRegs.CP0.n.Status.val, excode);
|
|
if (bd) {
|
|
SysPrintf("branch delay!!\n");
|
|
}
|
|
cpuRegs.CP0.n.BadVAddr = addr;
|
|
cpuRegs.CP0.n.Context &= 0xFF80000F;
|
|
cpuRegs.CP0.n.Context |= (addr >> 9) & 0x007FFFF0;
|
|
cpuRegs.CP0.n.EntryHi = (addr & 0xFFFFE000) | (cpuRegs.CP0.n.EntryHi & 0x1FFF);
|
|
|
|
cpuRegs.CP0.n.Cause = excode;
|
|
if (!(cpuRegs.CP0.n.Status.val & 0x2)) { // EXL bit
|
|
cpuRegs.CP0.n.EPC = cpuRegs.pc - 4;
|
|
}
|
|
|
|
if ((cpuRegs.CP0.n.Status.val & 0x1) == 0) {
|
|
cpuRegs.pc = 0x80000000;
|
|
} else {
|
|
cpuRegs.pc = 0x80000180;
|
|
}
|
|
|
|
cpuRegs.CP0.n.Status.b.EXL = 1;
|
|
UpdateCP0Status();
|
|
// Log=1; varLog|= 0x40000000;
|
|
}
|
|
|
|
void cpuTlbMissR(u32 addr, u32 bd) {
|
|
cpuTlbMiss(addr, bd, EXC_CODE_TLBL);
|
|
}
|
|
|
|
void cpuTlbMissW(u32 addr, u32 bd) {
|
|
cpuTlbMiss(addr, bd, EXC_CODE_TLBS);
|
|
}
|
|
|
|
void JumpCheckSym(u32 addr, u32 pc) {
|
|
#if 0
|
|
// if (addr == 0x80051770) { SysPrintf("Log!: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); Log=1; varLog|= 0x40000000; }
|
|
if (addr == 0x8002f150) { SysPrintf("printk: %s\n", PSM(cpuRegs.GPR.n.a0.UL[0])); }
|
|
if (addr == 0x8002aba0) return;
|
|
if (addr == 0x8002f450) return;
|
|
if (addr == 0x800dd520) return;
|
|
// if (addr == 0x80049300) SysPrintf("register_blkdev: %x\n", cpuRegs.GPR.n.a0.UL[0]);
|
|
if (addr == 0x8013cb70) { SysPrintf("change_root: %x\n", cpuRegs.GPR.n.a0.UL[0]); }
|
|
// if (addr == 0x8013d1e8) { SysPrintf("Log!\n"); Log++; if (Log==2) exit(0); varLog|= 0x40000000; }
|
|
// if (addr == 0x00234e88) { SysPrintf("StoreImage\n"); Log=1; /*psMu32(0x234e88) = 0x03e00008; psMu32(0x234e8c) = 0;*/ }
|
|
#endif
|
|
/* if ((pc >= 0x00131D50 &&
|
|
pc < 0x00132454) ||
|
|
(pc >= 0x00786a90 &&
|
|
pc < 0x00786ac8))*/
|
|
/*if (varLog & 0x40000000) {
|
|
char *str;
|
|
char *strf;
|
|
|
|
str = disR5900GetSym(addr);
|
|
if (str != NULL) {
|
|
strf = disR5900GetUpperSym(pc);
|
|
if (strf) {
|
|
SysPrintf("Func %8.8x: %s (called by %8.8x: %s)\n", addr, str, pc, strf);
|
|
} else {
|
|
SysPrintf("Func %8.8x: %s (called by %x)\n", addr, str, pc);
|
|
}
|
|
if (!strcmp(str, "printf")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); }
|
|
if (!strcmp(str, "printk")) { SysPrintf("%s\n", (char*)PSM(cpuRegs.GPR.n.a0.UL[0])); }
|
|
}
|
|
}*/
|
|
}
|
|
|
|
void JumpCheckSymRet(u32 addr) {
|
|
/*if (varLog & 0x40000000) {
|
|
char *str;
|
|
str = disR5900GetUpperSym(addr);
|
|
if (str != NULL) {
|
|
SysPrintf("Return : %s, v0=%8.8x\n", str, cpuRegs.GPR.n.v0.UL[0]);
|
|
}
|
|
}*/
|
|
}
|
|
|
|
__inline void _cpuTestMissingINTC() {
|
|
if (cpuRegs.CP0.n.Status.val & 0x400 &&
|
|
psHu32(INTC_STAT) & psHu32(INTC_MASK)) {
|
|
if ((cpuRegs.interrupt & (1 << 30)) == 0) {
|
|
SysPrintf("*PCSX2*: Error, missing INTC Interrupt\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
__inline void _cpuTestMissingDMAC() {
|
|
if (cpuRegs.CP0.n.Status.val & 0x800 &&
|
|
(psHu16(0xe012) & psHu16(0xe010) ||
|
|
psHu16(0xe010) & 0x8000)) {
|
|
if ((cpuRegs.interrupt & (1 << 31)) == 0) {
|
|
SysPrintf("*PCSX2*: Error, missing DMAC Interrupt\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
void cpuTestMissingHwInts() {
|
|
if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {
|
|
_cpuTestMissingINTC();
|
|
_cpuTestMissingDMAC();
|
|
// _cpuTestTIMR();
|
|
}
|
|
}
|
|
|
|
#define TESTINT(n, callback) { \
|
|
if ( (cpuRegs.interrupt & (1 << n)) ) { \
|
|
if( ((int)(cpuRegs.cycle - cpuRegs.sCycle[n]) >= cpuRegs.eCycle[n]) ) { \
|
|
if (callback() == 1) { \
|
|
cpuRegs.interrupt &= ~(1 << n); \
|
|
} \
|
|
} \
|
|
else if( (int)(g_nextBranchCycle - cpuRegs.sCycle[n]) > cpuRegs.eCycle[n] ) { \
|
|
g_nextBranchCycle = cpuRegs.sCycle[n] + cpuRegs.eCycle[n]; \
|
|
} \
|
|
} \
|
|
} \
|
|
|
|
void _cpuTestInterrupts() {
|
|
|
|
inter = cpuRegs.interrupt;
|
|
/* These are 'pcsx2 interrupts', they handle asynchronous stuff
|
|
that depends on the cycle timings */
|
|
|
|
TESTINT(0, vif0Interrupt);
|
|
TESTINT(10, vifMFIFOInterrupt);
|
|
TESTINT(1, vif1Interrupt);
|
|
TESTINT(11, gifMFIFOInterrupt);
|
|
TESTINT(2, gsInterrupt);
|
|
TESTINT(3, ipu0Interrupt);
|
|
TESTINT(4, ipu1Interrupt);
|
|
TESTINT(5, EEsif0Interrupt);
|
|
TESTINT(6, EEsif1Interrupt);
|
|
TESTINT(8, SPRFROMinterrupt);
|
|
TESTINT(9, SPRTOinterrupt);
|
|
|
|
if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return;
|
|
TESTINT(30, intcInterrupt);
|
|
TESTINT(31, dmacInterrupt);
|
|
}
|
|
|
|
u32 s_iLastCOP0Cycle = 0;
|
|
u32 s_iLastPERFCycle[2] = {0,0};
|
|
|
|
static void _cpuTestTIMR() {
|
|
cpuRegs.CP0.n.Count += cpuRegs.cycle-s_iLastCOP0Cycle;
|
|
s_iLastCOP0Cycle = cpuRegs.cycle;
|
|
|
|
if((cpuRegs.PERF.n.pccr & 0x800003E0) == 0x80000020) {
|
|
cpuRegs.PERF.n.pcr0 += cpuRegs.cycle-s_iLastPERFCycle[0];
|
|
s_iLastPERFCycle[0] = cpuRegs.cycle;
|
|
}
|
|
if((cpuRegs.PERF.n.pccr & 0x800F8000) == 0x80008000) {
|
|
cpuRegs.PERF.n.pcr1 += cpuRegs.cycle-s_iLastPERFCycle[1];
|
|
s_iLastPERFCycle[1] = cpuRegs.cycle;
|
|
}
|
|
|
|
if ( (cpuRegs.CP0.n.Status.val & 0x8000) &&
|
|
cpuRegs.CP0.n.Count >= cpuRegs.CP0.n.Compare && cpuRegs.CP0.n.Count < cpuRegs.CP0.n.Compare+1000 ) {
|
|
SysPrintf("timr intr: %x, %x\n", cpuRegs.CP0.n.Count, cpuRegs.CP0.n.Compare);
|
|
cpuException(0x808000, cpuRegs.branch);
|
|
}
|
|
}
|
|
|
|
#define EE_WAIT_CYCLE 512
|
|
|
|
// if cpuRegs.cycle is greater than this cycle, should check cpuBranchTest for updates
|
|
u32 g_nextBranchCycle = 0;
|
|
u32 s_lastvsync[2];
|
|
extern u8 g_globalXMMSaved, g_globalMMXSaved;
|
|
u32 loaded = 0;
|
|
|
|
void IntcpuBranchTest()
|
|
{
|
|
assert( !g_globalXMMSaved && !g_globalMMXSaved );
|
|
g_EEFreezeRegs = 0;
|
|
|
|
g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE;
|
|
|
|
if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter)
|
|
rcntUpdate();
|
|
|
|
if (cpuRegs.interrupt)
|
|
_cpuTestInterrupts();
|
|
|
|
if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter )
|
|
g_nextBranchCycle = nextsCounter+nextCounter;
|
|
|
|
//#ifdef CPU_LOG
|
|
// cpuTestMissingHwInts();
|
|
//#endif
|
|
_cpuTestTIMR();
|
|
|
|
EEsCycle += cpuRegs.cycle - EEoCycle;
|
|
EEoCycle = cpuRegs.cycle;
|
|
|
|
psxCpu->ExecuteBlock();
|
|
|
|
if (VU0.VI[REG_VPU_STAT].UL & 0x1) {
|
|
Cpu->ExecuteVU0Block();
|
|
}
|
|
if (VU0.VI[REG_VPU_STAT].UL & 0x100) {
|
|
Cpu->ExecuteVU1Block();
|
|
}
|
|
|
|
if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 )
|
|
g_nextBranchCycle = cpuRegs.cycle+1;
|
|
|
|
assert( !g_globalXMMSaved && !g_globalMMXSaved );
|
|
g_EEFreezeRegs = 1;
|
|
}
|
|
|
|
void cpuBranchTest()
|
|
{
|
|
assert( !g_globalXMMSaved && !g_globalMMXSaved );
|
|
g_EEFreezeRegs = 0;
|
|
|
|
// if( !loaded && cpuRegs.cycle > 0x08000000 ) {
|
|
// char strstate[255];
|
|
// sprintf(strstate, "sstates/%8.8x.000", ElfCRC);
|
|
// LoadState(strstate);
|
|
// loaded = 1;
|
|
// }
|
|
|
|
g_nextBranchCycle = cpuRegs.cycle + EE_WAIT_CYCLE;
|
|
|
|
if ((int)(cpuRegs.cycle - nextsCounter) >= nextCounter)
|
|
rcntUpdate();
|
|
|
|
if (cpuRegs.interrupt)
|
|
_cpuTestInterrupts();
|
|
|
|
if( (int)(g_nextBranchCycle-nextsCounter) >= nextCounter )
|
|
g_nextBranchCycle = nextsCounter+nextCounter;
|
|
|
|
//#ifdef CPU_LOG
|
|
// cpuTestMissingHwInts();
|
|
//#endif
|
|
_cpuTestTIMR();
|
|
|
|
EEsCycle += cpuRegs.cycle - EEoCycle;
|
|
EEoCycle = cpuRegs.cycle;
|
|
|
|
psxCpu->ExecuteBlock();
|
|
|
|
if (VU0.VI[REG_VPU_STAT].UL & 0x1) {
|
|
Cpu->ExecuteVU0Block();
|
|
}
|
|
|
|
if( (int)cpuRegs.cycle-(int)g_nextBranchCycle > 0 )
|
|
g_nextBranchCycle = cpuRegs.cycle+1;
|
|
|
|
assert( !g_globalXMMSaved && !g_globalMMXSaved );
|
|
g_EEFreezeRegs = 1;
|
|
}
|
|
|
|
static void _cpuTestINTC() {
|
|
if (cpuRegs.CP0.n.Status.val & 0x400 ){
|
|
if (psHu32(INTC_STAT) & psHu32(INTC_MASK)) {
|
|
if ((cpuRegs.interrupt & (1 << 30)) == 0) {
|
|
INT(30,4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void _cpuTestDMAC() {
|
|
if (cpuRegs.CP0.n.Status.val & 0x800 ){
|
|
if (psHu16(0xe012) & psHu16(0xe010) ||
|
|
psHu16(0xe010) & 0x8000) {
|
|
if ( (cpuRegs.interrupt & (1 << 31)) == 0) {
|
|
INT(31, 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void cpuTestHwInts() {
|
|
if ((cpuRegs.CP0.n.Status.val & 0x10007) != 0x10001) return;
|
|
_cpuTestINTC();
|
|
_cpuTestDMAC();
|
|
_cpuTestTIMR();
|
|
}
|
|
|
|
void cpuTestINTCInts() {
|
|
if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {
|
|
_cpuTestINTC();
|
|
}
|
|
}
|
|
|
|
void cpuTestDMACInts() {
|
|
if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {
|
|
_cpuTestDMAC();
|
|
}
|
|
}
|
|
|
|
void cpuTestTIMRInts() {
|
|
if ((cpuRegs.CP0.n.Status.val & 0x10007) == 0x10001) {
|
|
_cpuTestTIMR();
|
|
}
|
|
}
|
|
|
|
extern BOOL bExecBIOS;
|
|
void cpuExecuteBios()
|
|
{
|
|
// filter CPU options
|
|
if( CHECK_EEREC ) Config.Options |= PCSX2_COP2REC;
|
|
else Config.Options &= ~PCSX2_COP2REC;
|
|
|
|
if( !cpucaps.hasStreamingSIMDExtensions ) {
|
|
Config.Options &= ~(PCSX2_VU1REC|PCSX2_VU0REC);
|
|
}
|
|
|
|
// remove frame skipping if GS doesn't support it
|
|
switch(CHECK_FRAMELIMIT) {
|
|
case PCSX2_FRAMELIMIT_SKIP:
|
|
case PCSX2_FRAMELIMIT_VUSKIP:
|
|
if( GSsetFrameSkip == NULL )
|
|
Config.Options &= ~PCSX2_FRAMELIMIT_MASK;
|
|
break;
|
|
}
|
|
|
|
SysPrintf("Using Frame Skipping: ");
|
|
switch(CHECK_FRAMELIMIT) {
|
|
case PCSX2_FRAMELIMIT_NORMAL: SysPrintf("Normal\n"); break;
|
|
case PCSX2_FRAMELIMIT_LIMIT: SysPrintf("Limit\n"); break;
|
|
case PCSX2_FRAMELIMIT_SKIP: SysPrintf("Skip\n"); break;
|
|
case PCSX2_FRAMELIMIT_VUSKIP: SysPrintf("VU Skip\n"); break;
|
|
}
|
|
|
|
|
|
SysPrintf("* PCSX2 *: ExecuteBios\n");
|
|
|
|
bExecBIOS = TRUE;
|
|
while (cpuRegs.pc != 0x00200008 &&
|
|
cpuRegs.pc != 0x00100008) {
|
|
Cpu->ExecuteBlock();
|
|
}
|
|
|
|
bExecBIOS = FALSE;
|
|
// REC_CLEARM(0x00200008);
|
|
// REC_CLEARM(0x00100008);
|
|
// REC_CLEARM(cpuRegs.pc);
|
|
if( CHECK_EEREC ) Cpu->Reset();
|
|
|
|
SysPrintf("* PCSX2 *: ExecuteBios Complete\n");
|
|
GSprintf(5, "PCSX2 v" PCSX2_VERSION "\nExecuteBios Complete\n");
|
|
}
|
|
|
|
void cpuRestartCPU()
|
|
{
|
|
Cpu = CHECK_EEREC ? &recCpu : &intCpu;
|
|
|
|
// restart vus
|
|
if (Cpu->Init() == -1) {
|
|
SysClose();
|
|
exit(1);
|
|
}
|
|
|
|
vu0Init();
|
|
vu1Init();
|
|
Cpu->Reset();
|
|
psxRestartCPU();
|
|
}
|
|
|