SPU2: clang-format, spu close before cdvd and remove unused refs

This commit is contained in:
Gauvain 'GovanifY' Roussel-Tarbouriech 2020-10-01 08:04:10 +02:00 committed by refractionpcsx2
parent b11ad72473
commit 655748f2d9
9 changed files with 1504 additions and 1342 deletions

View File

@ -34,8 +34,8 @@
HBlank 15.73426573 KHz */ HBlank 15.73426573 KHz */
// Misc IOP Clocks // Misc IOP Clocks
#define PSXPIXEL ((int)(PSXCLK / 13500000)) #define PSXPIXEL ((int)(PSXCLK / 13500000))
#define PSXSOUNDCLK ((int)(48000)) #define PSXSOUNDCLK ((int)(48000))
psxCounter psxCounters[NUM_COUNTERS]; psxCounter psxCounters[NUM_COUNTERS];
s32 psxNextCounter; s32 psxNextCounter;
@ -44,19 +44,19 @@ u8 psxhblankgate = 0;
u8 psxvblankgate = 0; u8 psxvblankgate = 0;
// flags when the gate is off or counter disabled. (do not count) // flags when the gate is off or counter disabled. (do not count)
#define IOPCNT_STOPPED (0x10000000ul) #define IOPCNT_STOPPED (0x10000000ul)
// used to disable targets until after an overflow // used to disable targets until after an overflow
#define IOPCNT_FUTURE_TARGET (0x1000000000ULL) #define IOPCNT_FUTURE_TARGET (0x1000000000ULL)
#define IOPCNT_ENABLE_GATE (1<<0) // enables gate-based counters #define IOPCNT_ENABLE_GATE (1 << 0) // enables gate-based counters
#define IOPCNT_MODE_GATE (3<<1) // 0x6 Gate mode (dependant on counter) #define IOPCNT_MODE_GATE (3 << 1) // 0x6 Gate mode (dependant on counter)
#define IOPCNT_MODE_RESET (1<<3) // 0x8 resets the counter on target (if interrupt only?) #define IOPCNT_MODE_RESET (1 << 3) // 0x8 resets the counter on target (if interrupt only?)
#define IOPCNT_INT_TARGET (1<<4) // 0x10 triggers an interrupt on targets #define IOPCNT_INT_TARGET (1 << 4) // 0x10 triggers an interrupt on targets
#define IOPCNT_INT_OVERFLOW (1<<5) // 0x20 triggers an interrupt on overflows #define IOPCNT_INT_OVERFLOW (1 << 5) // 0x20 triggers an interrupt on overflows
#define IOPCNT_INT_TOGGLE (1<<7) // 0x80 0=Pulse (reset on read), 1=toggle each interrupt condition (in 1 shot not reset after fired) #define IOPCNT_INT_TOGGLE (1 << 7) // 0x80 0=Pulse (reset on read), 1=toggle each interrupt condition (in 1 shot not reset after fired)
#define IOPCNT_ALT_SOURCE (1<<8) // 0x100 uses hblank on counters 1 and 3, and PSXCLOCK on counter 0 #define IOPCNT_ALT_SOURCE (1 << 8) // 0x100 uses hblank on counters 1 and 3, and PSXCLOCK on counter 0
#define IOPCNT_INT_REQ (1<<10) // 0x400 1=Can fire interrupt, 0=Interrupt Fired (reset on read if not 1 shot) #define IOPCNT_INT_REQ (1 << 10) // 0x400 1=Can fire interrupt, 0=Interrupt Fired (reset on read if not 1 shot)
// Use an arbitrary value to flag HBLANK counters. // Use an arbitrary value to flag HBLANK counters.
// These counters will be counted by the hblank gates coming from the EE, // These counters will be counted by the hblank gates coming from the EE,
@ -66,13 +66,13 @@ u8 psxvblankgate = 0;
static void psxRcntReset(int index) static void psxRcntReset(int index)
{ {
psxCounters[index].count = 0; psxCounters[index].count = 0;
psxCounters[index].mode&= ~0x18301C00; psxCounters[index].mode &= ~0x18301C00;
psxCounters[index].sCycleT = psxRegs.cycle; psxCounters[index].sCycleT = psxRegs.cycle;
} }
static void _rcntSet( int cntidx ) static void _rcntSet(int cntidx)
{ {
u64 overflowCap = (cntidx>=3) ? 0x100000000ULL : 0x10000; u64 overflowCap = (cntidx >= 3) ? 0x100000000ULL : 0x10000;
u64 c; u64 c;
const psxCounter& counter = psxCounters[cntidx]; const psxCounter& counter = psxCounters[cntidx];
@ -82,52 +82,57 @@ static void _rcntSet( int cntidx )
// that into account. Adding the difference from that cycle count to the current one // that into account. Adding the difference from that cycle count to the current one
// will do the trick! // will do the trick!
if( counter.mode & IOPCNT_STOPPED || counter.rate == PSXHBLANK) return; if (counter.mode & IOPCNT_STOPPED || counter.rate == PSXHBLANK)
return;
// check for special cases where the overflow or target has just passed // check for special cases where the overflow or target has just passed
// (we probably missed it because we're doing/checking other things) // (we probably missed it because we're doing/checking other things)
if( counter.count > overflowCap || counter.count > counter.target ) if (counter.count > overflowCap || counter.count > counter.target)
{ {
psxNextCounter = 4; psxNextCounter = 4;
return; return;
} }
c = (u64)((overflowCap - counter.count) * counter.rate) - (psxRegs.cycle - counter.sCycleT); c = (u64)((overflowCap - counter.count) * counter.rate) - (psxRegs.cycle - counter.sCycleT);
c += psxRegs.cycle - psxNextsCounter; // adjust for time passed since last rcntUpdate(); c += psxRegs.cycle - psxNextsCounter; // adjust for time passed since last rcntUpdate();
if(c < (u64)psxNextCounter) if (c < (u64)psxNextCounter)
{ {
psxNextCounter = (u32)c; psxNextCounter = (u32)c;
psxSetNextBranch( psxNextsCounter, psxNextCounter ); //Need to update on counter resets/target changes psxSetNextBranch(psxNextsCounter, psxNextCounter); //Need to update on counter resets/target changes
} }
//if((counter.mode & 0x10) == 0 || psxCounters[i].target > 0xffff) continue; //if((counter.mode & 0x10) == 0 || psxCounters[i].target > 0xffff) continue;
if( counter.target & IOPCNT_FUTURE_TARGET ) return; if (counter.target & IOPCNT_FUTURE_TARGET)
return;
c = (s64)((counter.target - counter.count) * counter.rate) - (psxRegs.cycle - counter.sCycleT); c = (s64)((counter.target - counter.count) * counter.rate) - (psxRegs.cycle - counter.sCycleT);
c += psxRegs.cycle - psxNextsCounter; // adjust for time passed since last rcntUpdate(); c += psxRegs.cycle - psxNextsCounter; // adjust for time passed since last rcntUpdate();
if(c < (u64)psxNextCounter) if (c < (u64)psxNextCounter)
{ {
psxNextCounter = (u32)c; psxNextCounter = (u32)c;
psxSetNextBranch( psxNextsCounter, psxNextCounter ); //Need to update on counter resets/target changes psxSetNextBranch(psxNextsCounter, psxNextCounter); //Need to update on counter resets/target changes
} }
} }
void psxRcntInit() { void psxRcntInit()
{
int i; int i;
memzero( psxCounters ); memzero(psxCounters);
for (i=0; i<3; i++) { for (i = 0; i < 3; i++)
{
psxCounters[i].rate = 1; psxCounters[i].rate = 1;
psxCounters[i].mode|= 0x0400; psxCounters[i].mode |= 0x0400;
psxCounters[i].target = IOPCNT_FUTURE_TARGET; psxCounters[i].target = IOPCNT_FUTURE_TARGET;
} }
for (i=3; i<6; i++) { for (i = 3; i < 6; i++)
{
psxCounters[i].rate = 1; psxCounters[i].rate = 1;
psxCounters[i].mode|= 0x0400; psxCounters[i].mode |= 0x0400;
psxCounters[i].target = IOPCNT_FUTURE_TARGET; psxCounters[i].target = IOPCNT_FUTURE_TARGET;
} }
@ -139,18 +144,18 @@ void psxRcntInit() {
psxCounters[4].interrupt = 0x08000; psxCounters[4].interrupt = 0x08000;
psxCounters[5].interrupt = 0x10000; psxCounters[5].interrupt = 0x10000;
psxCounters[6].rate = 768*12; psxCounters[6].rate = 768 * 12;
psxCounters[6].CycleT = psxCounters[6].rate; psxCounters[6].CycleT = psxCounters[6].rate;
psxCounters[6].mode = 0x8; psxCounters[6].mode = 0x8;
if (USBasync != NULL) if (USBasync != NULL)
{ {
psxCounters[7].rate = PSXCLK/1000; psxCounters[7].rate = PSXCLK / 1000;
psxCounters[7].CycleT = psxCounters[7].rate; psxCounters[7].CycleT = psxCounters[7].rate;
psxCounters[7].mode = 0x8; psxCounters[7].mode = 0x8;
} }
for (i=0; i<8; i++) for (i = 0; i < 8; i++)
psxCounters[i].sCycleT = psxRegs.cycle; psxCounters[i].sCycleT = psxRegs.cycle;
// Tell the IOP to branch ASAP, so that timers can get // Tell the IOP to branch ASAP, so that timers can get
@ -159,16 +164,19 @@ void psxRcntInit() {
psxNextsCounter = psxRegs.cycle; psxNextsCounter = psxRegs.cycle;
} }
static bool __fastcall _rcntFireInterrupt(int i, bool isOverflow) { static bool __fastcall _rcntFireInterrupt(int i, bool isOverflow)
{
bool ret; bool ret;
if (psxCounters[i].mode & 0x400) { //IRQ fired if (psxCounters[i].mode & 0x400)
{ //IRQ fired
//DevCon.Warning("Counter %d %s IRQ Fired count %x", i, isOverflow ? "Overflow" : "Target", psxCounters[i].count); //DevCon.Warning("Counter %d %s IRQ Fired count %x", i, isOverflow ? "Overflow" : "Target", psxCounters[i].count);
psxHu32(0x1070) |= psxCounters[i].interrupt; psxHu32(0x1070) |= psxCounters[i].interrupt;
iopTestIntc(); iopTestIntc();
ret = true; ret = true;
} }
else { else
{
//DevCon.Warning("Counter %d IRQ not fired count %x", i, psxCounters[i].count); //DevCon.Warning("Counter %d IRQ not fired count %x", i, psxCounters[i].count);
ret = false; ret = false;
if (!(psxCounters[i].mode & 0x40)) //One shot if (!(psxCounters[i].mode & 0x40)) //One shot
@ -178,27 +186,30 @@ static bool __fastcall _rcntFireInterrupt(int i, bool isOverflow) {
} }
} }
if (psxCounters[i].mode & 0x80) { //Toggle mode if (psxCounters[i].mode & 0x80)
{ //Toggle mode
psxCounters[i].mode ^= 0x400; // Interrupt flag inverted psxCounters[i].mode ^= 0x400; // Interrupt flag inverted
} }
else { else
{
psxCounters[i].mode &= ~0x0400; // Interrupt flag set low psxCounters[i].mode &= ~0x0400; // Interrupt flag set low
} }
return ret; return ret;
} }
static void __fastcall _rcntTestTarget( int i ) static void __fastcall _rcntTestTarget(int i)
{ {
if( psxCounters[i].count < psxCounters[i].target ) return; if (psxCounters[i].count < psxCounters[i].target)
return;
PSXCNT_LOG("IOP Counter[%d] target 0x%I64x >= 0x%I64x (mode: %x)", PSXCNT_LOG("IOP Counter[%d] target 0x%I64x >= 0x%I64x (mode: %x)",
i, psxCounters[i].count, psxCounters[i].target, psxCounters[i].mode); i, psxCounters[i].count, psxCounters[i].target, psxCounters[i].mode);
if (psxCounters[i].mode & IOPCNT_INT_TARGET) if (psxCounters[i].mode & IOPCNT_INT_TARGET)
{ {
// Target interrupt // Target interrupt
if(_rcntFireInterrupt(i, false)) if (_rcntFireInterrupt(i, false))
psxCounters[i].mode |= 0x0800; // Target flag psxCounters[i].mode |= 0x0800; // Target flag
} }
@ -209,37 +220,39 @@ static void __fastcall _rcntTestTarget( int i )
} }
else else
psxCounters[i].target |= IOPCNT_FUTURE_TARGET; psxCounters[i].target |= IOPCNT_FUTURE_TARGET;
} }
static __fi void _rcntTestOverflow( int i ) static __fi void _rcntTestOverflow(int i)
{ {
u64 maxTarget = ( i < 3 ) ? 0xffff : 0xfffffffful; u64 maxTarget = (i < 3) ? 0xffff : 0xfffffffful;
if( psxCounters[i].count <= maxTarget ) return; if (psxCounters[i].count <= maxTarget)
return;
PSXCNT_LOG("IOP Counter[%d] overflow 0x%I64x >= 0x%I64x (mode: %x)", PSXCNT_LOG("IOP Counter[%d] overflow 0x%I64x >= 0x%I64x (mode: %x)",
i, psxCounters[i].count, maxTarget, psxCounters[i].mode ); i, psxCounters[i].count, maxTarget, psxCounters[i].mode);
if (!(psxCounters[i].mode & 0x40)) //One shot, whichever condition is met first if (!(psxCounters[i].mode & 0x40)) //One shot, whichever condition is met first
{ {
if (psxCounters[i].target < IOPCNT_FUTURE_TARGET) { //Target didn't trigger so we can overflow if (psxCounters[i].target < IOPCNT_FUTURE_TARGET)
{ //Target didn't trigger so we can overflow
// Overflow interrupt // Overflow interrupt
if ((psxCounters[i].mode & IOPCNT_INT_OVERFLOW)) { if ((psxCounters[i].mode & IOPCNT_INT_OVERFLOW))
{
if (_rcntFireInterrupt(i, true)) if (_rcntFireInterrupt(i, true))
psxCounters[i].mode |= 0x1000; // Overflow flag psxCounters[i].mode |= 0x1000; // Overflow flag
} }
} }
psxCounters[i].target |= IOPCNT_FUTURE_TARGET; psxCounters[i].target |= IOPCNT_FUTURE_TARGET;
} }
else else
{ {
// Overflow interrupt // Overflow interrupt
if ((psxCounters[i].mode & IOPCNT_INT_OVERFLOW)) { if ((psxCounters[i].mode & IOPCNT_INT_OVERFLOW))
{
if (_rcntFireInterrupt(i, true)) if (_rcntFireInterrupt(i, true))
psxCounters[i].mode |= 0x1000; // Overflow flag psxCounters[i].mode |= 0x1000; // Overflow flag
} }
psxCounters[i].target &= maxTarget; psxCounters[i].target &= maxTarget;
} }
// Update count. // Update count.
@ -248,9 +261,6 @@ static __fi void _rcntTestOverflow( int i )
// the counter value, and thus should not be flagged until after an overflow) // the counter value, and thus should not be flagged until after an overflow)
psxCounters[i].count -= maxTarget; psxCounters[i].count -= maxTarget;
} }
/* /*
@ -286,121 +296,125 @@ Gate:
<---->0==========================>============ <---->0==========================>============
*/ */
static void _psxCheckStartGate( int i ) static void _psxCheckStartGate(int i)
{ {
if(!(psxCounters[i].mode & IOPCNT_ENABLE_GATE)) return; //Ignore Gate if (!(psxCounters[i].mode & IOPCNT_ENABLE_GATE))
return; //Ignore Gate
switch((psxCounters[i].mode & 0x6) >> 1) switch ((psxCounters[i].mode & 0x6) >> 1)
{ {
case 0x0: //GATE_ON_count - stop count on gate start: case 0x0: //GATE_ON_count - stop count on gate start:
// get the current count at the time of stoppage: // get the current count at the time of stoppage:
psxCounters[i].count = ( i < 3 ) ? psxCounters[i].count = (i < 3) ?
psxRcntRcount16( i ) : psxRcntRcount32( i ); psxRcntRcount16(i) :
psxRcntRcount32(i);
psxCounters[i].mode |= IOPCNT_STOPPED; psxCounters[i].mode |= IOPCNT_STOPPED;
return; return;
case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate
// do nothing - All counting will be done on a need-to-count basis. // do nothing - All counting will be done on a need-to-count basis.
return; return;
case 0x2: //GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end case 0x2: //GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end
psxCounters[i].count = 0; psxCounters[i].count = 0;
psxCounters[i].sCycleT = psxRegs.cycle; psxCounters[i].sCycleT = psxRegs.cycle;
psxCounters[i].mode &= ~IOPCNT_STOPPED; psxCounters[i].mode &= ~IOPCNT_STOPPED;
break; break;
case 0x3: //GATE_ON_Start - start and count normally on gate end (no restarts or stops or clears) case 0x3: //GATE_ON_Start - start and count normally on gate end (no restarts or stops or clears)
// do nothing! // do nothing!
return; return;
} }
_rcntSet( i ); _rcntSet(i);
} }
static void _psxCheckEndGate(int i) static void _psxCheckEndGate(int i)
{ {
if(!(psxCounters[i].mode & IOPCNT_ENABLE_GATE)) return; //Ignore Gate if (!(psxCounters[i].mode & IOPCNT_ENABLE_GATE))
return; //Ignore Gate
switch((psxCounters[i].mode & 0x6) >> 1) switch ((psxCounters[i].mode & 0x6) >> 1)
{ {
case 0x0: //GATE_ON_count - reset and start counting case 0x0: //GATE_ON_count - reset and start counting
case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate case 0x1: //GATE_ON_ClearStart - count normally with resets after every end gate
psxCounters[i].count = 0; psxCounters[i].count = 0;
psxCounters[i].sCycleT = psxRegs.cycle; psxCounters[i].sCycleT = psxRegs.cycle;
psxCounters[i].mode &= ~IOPCNT_STOPPED; psxCounters[i].mode &= ~IOPCNT_STOPPED;
break; break;
case 0x2: //GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end case 0x2: //GATE_ON_Clear_OFF_Start - start counting on gate start, stop on gate end
psxCounters[i].count = ( i < 3 ) ? psxCounters[i].count = (i < 3) ?
psxRcntRcount16( i ) : psxRcntRcount32( i ); psxRcntRcount16(i) :
psxRcntRcount32(i);
psxCounters[i].mode |= IOPCNT_STOPPED; psxCounters[i].mode |= IOPCNT_STOPPED;
return; // do not set the counter return; // do not set the counter
case 0x3: //GATE_ON_Start - start and count normally (no restarts or stops or clears) case 0x3: //GATE_ON_Start - start and count normally (no restarts or stops or clears)
if( psxCounters[i].mode & IOPCNT_STOPPED ) if (psxCounters[i].mode & IOPCNT_STOPPED)
{ {
psxCounters[i].count = 0; psxCounters[i].count = 0;
psxCounters[i].sCycleT = psxRegs.cycle; psxCounters[i].sCycleT = psxRegs.cycle;
psxCounters[i].mode &= ~IOPCNT_STOPPED; psxCounters[i].mode &= ~IOPCNT_STOPPED;
} }
break; break;
} }
_rcntSet( i ); _rcntSet(i);
} }
void psxCheckStartGate16(int i) void psxCheckStartGate16(int i)
{ {
pxAssert( i < 3 ); pxAssert(i < 3);
if(i == 0) // hSync counting... if (i == 0) // hSync counting...
{ {
// AlternateSource/scanline counters for Gates 1 and 3. // AlternateSource/scanline counters for Gates 1 and 3.
// We count them here so that they stay nicely synced with the EE's hsync. // We count them here so that they stay nicely synced with the EE's hsync.
const u32 altSourceCheck = IOPCNT_ALT_SOURCE | IOPCNT_ENABLE_GATE; const u32 altSourceCheck = IOPCNT_ALT_SOURCE | IOPCNT_ENABLE_GATE;
const u32 stoppedGateCheck = (IOPCNT_STOPPED | altSourceCheck ); const u32 stoppedGateCheck = (IOPCNT_STOPPED | altSourceCheck);
// count if alt source is enabled and either: // count if alt source is enabled and either:
// * the gate is enabled and not stopped. // * the gate is enabled and not stopped.
// * the gate is disabled. // * the gate is disabled.
if( (psxCounters[1].mode & altSourceCheck) == IOPCNT_ALT_SOURCE || if ((psxCounters[1].mode & altSourceCheck) == IOPCNT_ALT_SOURCE ||
(psxCounters[1].mode & stoppedGateCheck ) == altSourceCheck ) (psxCounters[1].mode & stoppedGateCheck) == altSourceCheck)
{ {
psxCounters[1].count++; psxCounters[1].count++;
_rcntTestTarget( 1 ); _rcntTestTarget(1);
_rcntTestOverflow( 1 ); _rcntTestOverflow(1);
} }
if( (psxCounters[3].mode & altSourceCheck) == IOPCNT_ALT_SOURCE || if ((psxCounters[3].mode & altSourceCheck) == IOPCNT_ALT_SOURCE ||
(psxCounters[3].mode & stoppedGateCheck ) == altSourceCheck ) (psxCounters[3].mode & stoppedGateCheck) == altSourceCheck)
{ {
psxCounters[3].count++; psxCounters[3].count++;
_rcntTestTarget( 3 ); _rcntTestTarget(3);
_rcntTestOverflow( 3 ); _rcntTestOverflow(3);
} }
} }
_psxCheckStartGate( i ); _psxCheckStartGate(i);
} }
void psxCheckEndGate16(int i) void psxCheckEndGate16(int i)
{ {
pxAssert(i < 3); pxAssert(i < 3);
_psxCheckEndGate( i ); _psxCheckEndGate(i);
} }
static void psxCheckStartGate32(int i) static void psxCheckStartGate32(int i)
{ {
// 32 bit gate is called for gate 3 only. Ever. // 32 bit gate is called for gate 3 only. Ever.
pxAssert(i == 3); pxAssert(i == 3);
_psxCheckStartGate( i ); _psxCheckStartGate(i);
} }
static void psxCheckEndGate32(int i) static void psxCheckEndGate32(int i)
{ {
pxAssert(i == 3); pxAssert(i == 3);
_psxCheckEndGate( i ); _psxCheckEndGate(i);
} }
@ -408,15 +422,19 @@ void psxVBlankStart()
{ {
cdvdVsync(); cdvdVsync();
iopIntcIrq(0); iopIntcIrq(0);
if(psxvblankgate & (1 << 1)) psxCheckStartGate16(1); if (psxvblankgate & (1 << 1))
if(psxvblankgate & (1 << 3)) psxCheckStartGate32(3); psxCheckStartGate16(1);
if (psxvblankgate & (1 << 3))
psxCheckStartGate32(3);
} }
void psxVBlankEnd() void psxVBlankEnd()
{ {
iopIntcIrq(11); iopIntcIrq(11);
if(psxvblankgate & (1 << 1)) psxCheckEndGate16(1); if (psxvblankgate & (1 << 1))
if(psxvblankgate & (1 << 3)) psxCheckEndGate32(3); psxCheckEndGate16(1);
if (psxvblankgate & (1 << 3))
psxCheckEndGate32(3);
} }
void psxRcntUpdate() void psxRcntUpdate()
@ -429,26 +447,30 @@ void psxRcntUpdate()
psxNextCounter = 0x7fffffff; psxNextCounter = 0x7fffffff;
psxNextsCounter = psxRegs.cycle; psxNextsCounter = psxRegs.cycle;
for (i=0; i<=5; i++) for (i = 0; i <= 5; i++)
{ {
s32 change = psxRegs.cycle - psxCounters[i].sCycleT; s32 change = psxRegs.cycle - psxCounters[i].sCycleT;
// don't count disabled or hblank counters... // don't count disabled or hblank counters...
// We can't check the ALTSOURCE flag because the PSXCLOCK source *should* // We can't check the ALTSOURCE flag because the PSXCLOCK source *should*
// be counted here. // be counted here.
if( psxCounters[i].mode & IOPCNT_STOPPED ) continue;
if ((psxCounters[i].mode & 0x40) && !(psxCounters[i].mode & 0x80)) { //Repeat IRQ mode Pulsed, resets a few cycles after the interrupt, this should do. if (psxCounters[i].mode & IOPCNT_STOPPED)
continue;
if ((psxCounters[i].mode & 0x40) && !(psxCounters[i].mode & 0x80))
{ //Repeat IRQ mode Pulsed, resets a few cycles after the interrupt, this should do.
psxCounters[i].mode |= 0x400; psxCounters[i].mode |= 0x400;
} }
if( psxCounters[i].rate == PSXHBLANK ) continue; if (psxCounters[i].rate == PSXHBLANK)
continue;
if( change <= 0 ) continue;
if (change <= 0)
continue;
psxCounters[i].count += change / psxCounters[i].rate; psxCounters[i].count += change / psxCounters[i].rate;
if(psxCounters[i].rate != 1) if (psxCounters[i].rate != 1)
{ {
change -= (change / psxCounters[i].rate) * psxCounters[i].rate; change -= (change / psxCounters[i].rate) * psxCounters[i].rate;
psxCounters[i].sCycleT = psxRegs.cycle - change; psxCounters[i].sCycleT = psxRegs.cycle - change;
@ -461,15 +483,17 @@ void psxRcntUpdate()
// Optimization Note: This approach is very sound. Please do not try to unroll it // Optimization Note: This approach is very sound. Please do not try to unroll it
// as the size of the Test functions will cause code cache clutter and slowness. // as the size of the Test functions will cause code cache clutter and slowness.
for( i=0; i<6; i++ ) for (i = 0; i < 6; i++)
{ {
// don't do target/oveflow checks for hblankers. Those // don't do target/oveflow checks for hblankers. Those
// checks are done when the counters are updated. // checks are done when the counters are updated.
if( psxCounters[i].rate == PSXHBLANK ) continue; if (psxCounters[i].rate == PSXHBLANK)
if( psxCounters[i].mode & IOPCNT_STOPPED ) continue; continue;
if (psxCounters[i].mode & IOPCNT_STOPPED)
continue;
_rcntTestTarget( i ); _rcntTestTarget(i);
_rcntTestOverflow( i ); _rcntTestOverflow(i);
// perform second target test because if we overflowed above it's possible we // perform second target test because if we overflowed above it's possible we
// already shot past our target if it was very near zero. // already shot past our target if it was very near zero.
@ -478,37 +502,41 @@ void psxRcntUpdate()
} }
const s32 difference = psxRegs.cycle - psxCounters[6].sCycleT; const s32 difference = psxRegs.cycle - psxCounters[6].sCycleT;
s32 c = psxCounters[6].CycleT; s32 c = psxCounters[6].CycleT;
if(difference >= psxCounters[6].CycleT) if (difference >= psxCounters[6].CycleT)
{ {
SPU2async(difference); SPU2async(difference);
psxCounters[6].sCycleT = psxRegs.cycle; psxCounters[6].sCycleT = psxRegs.cycle;
psxCounters[6].CycleT = psxCounters[6].rate; psxCounters[6].CycleT = psxCounters[6].rate;
} }
else c -= difference; else
psxNextCounter = c; c -= difference;
psxNextCounter = c;
if (DEV9async) if (DEV9async)
{ {
DEV9async(1); DEV9async(1);
} }
if(USBasync) if (USBasync)
{ {
const s32 difference = psxRegs.cycle - psxCounters[7].sCycleT; const s32 difference = psxRegs.cycle - psxCounters[7].sCycleT;
s32 c = psxCounters[7].CycleT; s32 c = psxCounters[7].CycleT;
if(difference >= psxCounters[7].CycleT) if (difference >= psxCounters[7].CycleT)
{ {
USBasync(difference); USBasync(difference);
psxCounters[7].sCycleT = psxRegs.cycle; psxCounters[7].sCycleT = psxRegs.cycle;
psxCounters[7].CycleT = psxCounters[7].rate; psxCounters[7].CycleT = psxCounters[7].rate;
} }
else c -= difference; else
if (c < psxNextCounter) psxNextCounter = c; c -= difference;
if (c < psxNextCounter)
psxNextCounter = c;
} }
for (i=0; i<6; i++) _rcntSet( i ); for (i = 0; i < 6; i++)
_rcntSet(i);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -517,10 +545,10 @@ void psxRcntWcount16(int index, u16 value)
{ {
u32 change; u32 change;
pxAssert( index < 3 ); pxAssert(index < 3);
//DevCon.Warning("16bit IOP Counter[%d] writeCount16 = %x", index, value); //DevCon.Warning("16bit IOP Counter[%d] writeCount16 = %x", index, value);
if(psxCounters[index].rate != PSXHBLANK) if (psxCounters[index].rate != PSXHBLANK)
{ {
// Re-adjust the sCycleT to match where the counter is currently // Re-adjust the sCycleT to match where the counter is currently
// (remainder of the rate divided into the time passed will do the trick) // (remainder of the rate divided into the time passed will do the trick)
@ -530,14 +558,16 @@ void psxRcntWcount16(int index, u16 value)
} }
psxCounters[index].count = value & 0xffff; psxCounters[index].count = value & 0xffff;
if ((psxCounters[index].mode & 0x400) || (psxCounters[index].mode & 0x40)) { if ((psxCounters[index].mode & 0x400) || (psxCounters[index].mode & 0x40))
{
psxCounters[index].target &= 0xffff; psxCounters[index].target &= 0xffff;
} }
if (value > psxCounters[index].target) {//Count already higher than Target if (value > psxCounters[index].target)
// DevCon.Warning("16bit Count already higher than target"); { //Count already higher than Target
// DevCon.Warning("16bit Count already higher than target");
psxCounters[index].target |= IOPCNT_FUTURE_TARGET; psxCounters[index].target |= IOPCNT_FUTURE_TARGET;
} }
_rcntSet( index ); _rcntSet(index);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -546,10 +576,10 @@ void psxRcntWcount32(int index, u32 value)
{ {
u32 change; u32 change;
pxAssert( index >= 3 && index < 6 ); pxAssert(index >= 3 && index < 6);
PSXCNT_LOG("32bit IOP Counter[%d] writeCount32 = %x", index, value); PSXCNT_LOG("32bit IOP Counter[%d] writeCount32 = %x", index, value);
if(psxCounters[index].rate != PSXHBLANK) if (psxCounters[index].rate != PSXHBLANK)
{ {
// Re-adjust the sCycleT to match where the counter is currently // Re-adjust the sCycleT to match where the counter is currently
// (remainder of the rate divided into the time passed will do the trick) // (remainder of the rate divided into the time passed will do the trick)
@ -559,14 +589,16 @@ void psxRcntWcount32(int index, u32 value)
} }
psxCounters[index].count = value; psxCounters[index].count = value;
if ((psxCounters[index].mode & 0x400) || (psxCounters[index].mode & 0x40)) { //IRQ not triggered (one shot) or toggle if ((psxCounters[index].mode & 0x400) || (psxCounters[index].mode & 0x40))
{ //IRQ not triggered (one shot) or toggle
psxCounters[index].target &= 0xffffffff; psxCounters[index].target &= 0xffffffff;
} }
if (value > psxCounters[index].target) {//Count already higher than Target if (value > psxCounters[index].target)
{ //Count already higher than Target
//DevCon.Warning("32bit Count already higher than target"); //DevCon.Warning("32bit Count already higher than target");
psxCounters[index].target |= IOPCNT_FUTURE_TARGET; psxCounters[index].target |= IOPCNT_FUTURE_TARGET;
} }
_rcntSet( index ); _rcntSet(index);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
@ -582,35 +614,44 @@ __fi void psxRcntWmode16(int index, u32 value)
counter.mode = value; counter.mode = value;
counter.mode |= 0x0400; //IRQ Enable counter.mode |= 0x0400; //IRQ Enable
if (value & (1 << 4)) { if (value & (1 << 4))
{
irqmode += 1; irqmode += 1;
} }
if (value & (1 << 5)) { if (value & (1 << 5))
{
irqmode += 2; irqmode += 2;
} }
if (value & (1 << 7)) { if (value & (1 << 7))
{
PSXCNT_LOG("16 Counter %d Toggle IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow")); PSXCNT_LOG("16 Counter %d Toggle IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
} }
else else
{ {
PSXCNT_LOG("16 Counter %d Pulsed IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow")); PSXCNT_LOG("16 Counter %d Pulsed IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
} }
if (!(value & (1 << 6))) { if (!(value & (1 << 6)))
{
PSXCNT_LOG("16 Counter %d One Shot", index); PSXCNT_LOG("16 Counter %d One Shot", index);
} }
else { else
{
PSXCNT_LOG("16 Counter %d Repeat", index); PSXCNT_LOG("16 Counter %d Repeat", index);
} }
if( index == 2 ) if (index == 2)
{ {
switch(value & 0x200) switch (value & 0x200)
{ {
case 0x000: psxCounters[2].rate = 1; break; case 0x000:
case 0x200: psxCounters[2].rate = 8; break; psxCounters[2].rate = 1;
jNO_DEFAULT; break;
case 0x200:
psxCounters[2].rate = 8;
break;
jNO_DEFAULT;
} }
if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1) if ((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
{ {
counter.mode |= IOPCNT_STOPPED; counter.mode |= IOPCNT_STOPPED;
} }
@ -620,26 +661,26 @@ __fi void psxRcntWmode16(int index, u32 value)
// Counters 0 and 1 can select PIXEL or HSYNC as an alternate source: // Counters 0 and 1 can select PIXEL or HSYNC as an alternate source:
counter.rate = 1; counter.rate = 1;
if(value & IOPCNT_ALT_SOURCE) if (value & IOPCNT_ALT_SOURCE)
counter.rate = (index==0) ? PSXPIXEL : PSXHBLANK; counter.rate = (index == 0) ? PSXPIXEL : PSXHBLANK;
if(counter.mode & IOPCNT_ENABLE_GATE) if (counter.mode & IOPCNT_ENABLE_GATE)
{ {
// gated counters are added up as per the h/vblank timers. // gated counters are added up as per the h/vblank timers.
// (the PIXEL alt source becomes a vsync gate) // (the PIXEL alt source becomes a vsync gate)
counter.mode |= IOPCNT_STOPPED; counter.mode |= IOPCNT_STOPPED;
PSXCNT_LOG( "IOP Counter[%d] Gate Check set, value = 0x%04X", index, value ); PSXCNT_LOG("IOP Counter[%d] Gate Check set, value = 0x%04X", index, value);
if( index == 0 ) if (index == 0)
psxhblankgate |= 1; // fixme: these gate flags should be one var >_< psxhblankgate |= 1; // fixme: these gate flags should be one var >_<
else else
psxvblankgate |= 1<<1; psxvblankgate |= 1 << 1;
} }
else else
{ {
if( index == 0 ) if (index == 0)
psxhblankgate &= ~1; psxhblankgate &= ~1;
else else
psxvblankgate &= ~(1<<1); psxvblankgate &= ~(1 << 1);
} }
} }
@ -647,70 +688,84 @@ __fi void psxRcntWmode16(int index, u32 value)
counter.sCycleT = psxRegs.cycle; counter.sCycleT = psxRegs.cycle;
counter.target &= 0xffff; counter.target &= 0xffff;
_rcntSet( index ); _rcntSet(index);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //
__fi void psxRcntWmode32( int index, u32 value ) __fi void psxRcntWmode32(int index, u32 value)
{ {
PSXCNT_LOG("32bit IOP Counter[%d] writeMode = 0x%04x", index, value ); PSXCNT_LOG("32bit IOP Counter[%d] writeMode = 0x%04x", index, value);
int irqmode = 0; int irqmode = 0;
pxAssume( index >= 3 && index < 6 ); pxAssume(index >= 3 && index < 6);
psxCounter& counter = psxCounters[index]; psxCounter& counter = psxCounters[index];
counter.mode = value; counter.mode = value;
counter.mode |= 0x0400; //IRQ enable counter.mode |= 0x0400; //IRQ enable
if (value & (1 << 4)) { if (value & (1 << 4))
{
irqmode += 1; irqmode += 1;
} }
if (value & (1 << 5)) { if (value & (1 << 5))
{
irqmode += 2; irqmode += 2;
} }
if (value & (1 << 7)) { if (value & (1 << 7))
{
PSXCNT_LOG("32 Counter %d Toggle IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow")); PSXCNT_LOG("32 Counter %d Toggle IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
} }
else else
{ {
PSXCNT_LOG("32 Counter %d Pulsed IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow")); PSXCNT_LOG("32 Counter %d Pulsed IRQ on %s", index, (irqmode & 3) == 1 ? "Target" : ((irqmode & 3) == 2 ? "Overflow" : "Target and Overflow"));
} }
if (!(value & (1 << 6))) { if (!(value & (1 << 6)))
PSXCNT_LOG("32 Counter %d One Shot", index);
}
else {
PSXCNT_LOG("32 Counter %d Repeat", index);
}
if( index == 3 )
{ {
// Counter 3 has the HBlank as an alternate source. PSXCNT_LOG("32 Counter %d One Shot", index);
counter.rate = 1;
if(value & IOPCNT_ALT_SOURCE)
counter.rate = PSXHBLANK;
if(counter.mode & IOPCNT_ENABLE_GATE)
{
PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
counter.mode |= IOPCNT_STOPPED;
psxvblankgate |= 1<<3;
}
else psxvblankgate &= ~(1<<3);
} }
else else
{ {
switch(value & 0x6000) PSXCNT_LOG("32 Counter %d Repeat", index);
}
if (index == 3)
{
// Counter 3 has the HBlank as an alternate source.
counter.rate = 1;
if (value & IOPCNT_ALT_SOURCE)
counter.rate = PSXHBLANK;
if (counter.mode & IOPCNT_ENABLE_GATE)
{ {
case 0x0000: counter.rate = 1; break; PSXCNT_LOG("IOP Counter[3] Gate Check set, value = %x", value);
case 0x2000: counter.rate = 8; break; counter.mode |= IOPCNT_STOPPED;
case 0x4000: counter.rate = 16; break; psxvblankgate |= 1 << 3;
case 0x6000: counter.rate = 256; break; }
else
psxvblankgate &= ~(1 << 3);
}
else
{
switch (value & 0x6000)
{
case 0x0000:
counter.rate = 1;
break;
case 0x2000:
counter.rate = 8;
break;
case 0x4000:
counter.rate = 16;
break;
case 0x6000:
counter.rate = 256;
break;
} }
// Need to set a rate and target // Need to set a rate and target
if((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1) if ((counter.mode & 0x7) == 0x7 || (counter.mode & 0x7) == 0x1)
{ {
Console.WriteLn( "Gate set on IOP Counter %d, disabling", index ); Console.WriteLn("Gate set on IOP Counter %d, disabling", index);
counter.mode |= IOPCNT_STOPPED; counter.mode |= IOPCNT_STOPPED;
} }
} }
@ -718,14 +773,14 @@ __fi void psxRcntWmode32( int index, u32 value )
counter.count = 0; counter.count = 0;
counter.sCycleT = psxRegs.cycle; counter.sCycleT = psxRegs.cycle;
counter.target &= 0xffffffff; counter.target &= 0xffffffff;
_rcntSet( index ); _rcntSet(index);
} }
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
// //
void psxRcntWtarget16(int index, u32 value) void psxRcntWtarget16(int index, u32 value)
{ {
pxAssert( index < 3 ); pxAssert(index < 3);
//DevCon.Warning("IOP Counter[%d] writeTarget16 = %lx", index, value); //DevCon.Warning("IOP Counter[%d] writeTarget16 = %lx", index, value);
psxCounters[index].target = value & 0xffff; psxCounters[index].target = value & 0xffff;
@ -733,19 +788,20 @@ void psxRcntWtarget16(int index, u32 value)
// if the target is behind the current count, then set the target overflow // if the target is behind the current count, then set the target overflow
// flag, so that the target won't be active until after the next overflow. // flag, so that the target won't be active until after the next overflow.
if(psxCounters[index].target <= psxRcntCycles(index) || ((psxCounters[index].mode & 0x400) == 0 && !(psxCounters[index].mode & 0x40))) if (psxCounters[index].target <= psxRcntCycles(index) || ((psxCounters[index].mode & 0x400) == 0 && !(psxCounters[index].mode & 0x40)))
psxCounters[index].target |= IOPCNT_FUTURE_TARGET; psxCounters[index].target |= IOPCNT_FUTURE_TARGET;
_rcntSet( index ); _rcntSet(index);
} }
void psxRcntWtarget32(int index, u32 value) void psxRcntWtarget32(int index, u32 value)
{ {
pxAssert( index >= 3 && index < 6); pxAssert(index >= 3 && index < 6);
//DevCon.Warning("IOP Counter[%d] writeTarget32 = %lx mode %x", index, value, psxCounters[index].mode); //DevCon.Warning("IOP Counter[%d] writeTarget32 = %lx mode %x", index, value, psxCounters[index].mode);
psxCounters[index].target = value; psxCounters[index].target = value;
if (!(psxCounters[index].mode & 0x80)) { //Toggle mode if (!(psxCounters[index].mode & 0x80))
{ //Toggle mode
psxCounters[index].mode |= 0x0400; // Interrupt flag set low psxCounters[index].mode |= 0x0400; // Interrupt flag set low
} }
// protect the target from an early arrival. // protect the target from an early arrival.
@ -755,26 +811,26 @@ void psxRcntWtarget32(int index, u32 value)
if (psxCounters[index].target <= psxRcntCycles(index) || ((psxCounters[index].mode & 0x400) == 0 && !(psxCounters[index].mode & 0x40))) if (psxCounters[index].target <= psxRcntCycles(index) || ((psxCounters[index].mode & 0x400) == 0 && !(psxCounters[index].mode & 0x40)))
psxCounters[index].target |= IOPCNT_FUTURE_TARGET; psxCounters[index].target |= IOPCNT_FUTURE_TARGET;
_rcntSet( index ); _rcntSet(index);
} }
u16 psxRcntRcount16(int index) u16 psxRcntRcount16(int index)
{ {
u32 retval = (u32)psxCounters[index].count; u32 retval = (u32)psxCounters[index].count;
pxAssert( index < 3 ); pxAssert(index < 3);
PSXCNT_LOG("IOP Counter[%d] readCount16 = %lx", index, (u16)retval ); PSXCNT_LOG("IOP Counter[%d] readCount16 = %lx", index, (u16)retval);
// Don't count HBLANK timers // Don't count HBLANK timers
// Don't count stopped gates either. // Don't count stopped gates either.
if( !( psxCounters[index].mode & IOPCNT_STOPPED ) && if (!(psxCounters[index].mode & IOPCNT_STOPPED) &&
( psxCounters[index].rate != PSXHBLANK ) ) (psxCounters[index].rate != PSXHBLANK))
{ {
u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate);
retval += delta; retval += delta;
PSXCNT_LOG(" (delta = %lx)", delta ); PSXCNT_LOG(" (delta = %lx)", delta);
} }
return (u16)retval; return (u16)retval;
@ -784,16 +840,16 @@ u32 psxRcntRcount32(int index)
{ {
u32 retval = (u32)psxCounters[index].count; u32 retval = (u32)psxCounters[index].count;
pxAssert( index >= 3 && index < 6 ); pxAssert(index >= 3 && index < 6);
PSXCNT_LOG("IOP Counter[%d] readCount32 = %lx", index, retval ); PSXCNT_LOG("IOP Counter[%d] readCount32 = %lx", index, retval);
if( !( psxCounters[index].mode & IOPCNT_STOPPED ) && if (!(psxCounters[index].mode & IOPCNT_STOPPED) &&
( psxCounters[index].rate != PSXHBLANK ) ) (psxCounters[index].rate != PSXHBLANK))
{ {
u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate); u32 delta = (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate);
retval += delta; retval += delta;
PSXCNT_LOG(" (delta = %lx)", delta ); PSXCNT_LOG(" (delta = %lx)", delta);
} }
return retval; return retval;
@ -801,36 +857,37 @@ u32 psxRcntRcount32(int index)
u64 psxRcntCycles(int index) u64 psxRcntCycles(int index)
{ {
if(psxCounters[index].mode & IOPCNT_STOPPED || psxCounters[index].rate == PSXHBLANK ) return psxCounters[index].count; if (psxCounters[index].mode & IOPCNT_STOPPED || psxCounters[index].rate == PSXHBLANK)
return psxCounters[index].count;
return (u64)(psxCounters[index].count + (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate)); return (u64)(psxCounters[index].count + (u32)((psxRegs.cycle - psxCounters[index].sCycleT) / psxCounters[index].rate));
} }
void psxRcntSetGates() void psxRcntSetGates()
{ {
if(psxCounters[0].mode & IOPCNT_ENABLE_GATE) if (psxCounters[0].mode & IOPCNT_ENABLE_GATE)
psxhblankgate |= 1; psxhblankgate |= 1;
else else
psxhblankgate &= ~1; psxhblankgate &= ~1;
if(psxCounters[1].mode & IOPCNT_ENABLE_GATE) if (psxCounters[1].mode & IOPCNT_ENABLE_GATE)
psxvblankgate |= 1<<1; psxvblankgate |= 1 << 1;
else else
psxvblankgate &= ~(1<<1); psxvblankgate &= ~(1 << 1);
if(psxCounters[3].mode & IOPCNT_ENABLE_GATE) if (psxCounters[3].mode & IOPCNT_ENABLE_GATE)
psxvblankgate |= 1<<3; psxvblankgate |= 1 << 3;
else else
psxvblankgate &= ~(1<<3); psxvblankgate &= ~(1 << 3);
} }
void SaveStateBase::psxRcntFreeze() void SaveStateBase::psxRcntFreeze()
{ {
FreezeTag( "iopCounters" ); FreezeTag("iopCounters");
Freeze(psxCounters); Freeze(psxCounters);
Freeze(psxNextCounter); Freeze(psxNextCounter);
Freeze(psxNextsCounter); Freeze(psxNextsCounter);
if( IsLoading() ) if (IsLoading())
psxRcntSetGates(); psxRcntSetGates();
} }

View File

@ -43,12 +43,6 @@ namespace soundtouch
#include "Pcsx2Defs.h" #include "Pcsx2Defs.h"
#include "Pcsx2Types.h" #include "Pcsx2Types.h"
namespace VersionInfo
{
static const u8 Release = 2;
static const u8 Revision = 0; // increase that with each version
} // namespace VersionInfo
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Override Win32 min/max macros with the STL's type safe and macro // Override Win32 min/max macros with the STL's type safe and macro
// free varieties (much safer!) // free varieties (much safer!)

View File

@ -37,7 +37,7 @@
#include "IopBios.h" #include "IopBios.h"
#ifdef __WXMSW__ #ifdef __WXMSW__
# include <wx/msw/wrapwin.h> #include <wx/msw/wrapwin.h>
#endif #endif
#include "x86emitter/x86_intrin.h" #include "x86emitter/x86_intrin.h"
@ -49,35 +49,36 @@
SysCoreThread::SysCoreThread() SysCoreThread::SysCoreThread()
{ {
m_name = L"EE Core"; m_name = L"EE Core";
m_resetRecompilers = true; m_resetRecompilers = true;
m_resetProfilers = true; m_resetProfilers = true;
m_resetVsyncTimers = true; m_resetVsyncTimers = true;
m_resetVirtualMachine = true; m_resetVirtualMachine = true;
m_hasActiveMachine = false; m_hasActiveMachine = false;
} }
SysCoreThread::~SysCoreThread() SysCoreThread::~SysCoreThread()
{ {
try { try
{
SysCoreThread::Cancel(); SysCoreThread::Cancel();
} }
DESTRUCTOR_CATCHALL DESTRUCTOR_CATCHALL
} }
void SysCoreThread::Cancel( bool isBlocking ) void SysCoreThread::Cancel(bool isBlocking)
{ {
m_hasActiveMachine = false; m_hasActiveMachine = false;
R3000A::ioman::reset(); R3000A::ioman::reset();
_parent::Cancel(); _parent::Cancel();
} }
bool SysCoreThread::Cancel( const wxTimeSpan& span ) bool SysCoreThread::Cancel(const wxTimeSpan& span)
{ {
m_hasActiveMachine = false; m_hasActiveMachine = false;
R3000A::ioman::reset(); R3000A::ioman::reset();
return _parent::Cancel( span ); return _parent::Cancel(span);
} }
void SysCoreThread::OnStart() void SysCoreThread::OnStart()
@ -87,9 +88,10 @@ void SysCoreThread::OnStart()
void SysCoreThread::Start() void SysCoreThread::Start()
{ {
if( !GetCorePlugins().AreLoaded() ) return; if (!GetCorePlugins().AreLoaded())
return;
GetCorePlugins().Init(); GetCorePlugins().Init();
SPU2init(); SPU2init();
_parent::Start(); _parent::Start();
} }
@ -104,17 +106,17 @@ void SysCoreThread::Start()
// //
void SysCoreThread::OnResumeReady() void SysCoreThread::OnResumeReady()
{ {
if( m_resetVirtualMachine ) if (m_resetVirtualMachine)
m_hasActiveMachine = false; m_hasActiveMachine = false;
if( !m_hasActiveMachine ) if (!m_hasActiveMachine)
m_resetRecompilers = true; m_resetRecompilers = true;
} }
// This function *will* reset the emulator in order to allow the specified elf file to // This function *will* reset the emulator in order to allow the specified elf file to
// take effect. This is because it really doesn't make sense to change the elf file outside // take effect. This is because it really doesn't make sense to change the elf file outside
// the context of a reset/restart. // the context of a reset/restart.
void SysCoreThread::SetElfOverride( const wxString& elf ) void SysCoreThread::SetElfOverride(const wxString& elf)
{ {
//pxAssertDev( !m_hasValidMachine, "Thread synchronization error while assigning ELF override." ); //pxAssertDev( !m_hasValidMachine, "Thread synchronization error while assigning ELF override." );
m_elf_override = elf; m_elf_override = elf;
@ -129,8 +131,8 @@ void SysCoreThread::ResetQuick()
{ {
Suspend(); Suspend();
m_resetVirtualMachine = true; m_resetVirtualMachine = true;
m_hasActiveMachine = false; m_hasActiveMachine = false;
R3000A::ioman::reset(); R3000A::ioman::reset();
} }
@ -139,7 +141,7 @@ void SysCoreThread::Reset()
ResetQuick(); ResetQuick();
GetVmMemory().DecommitAll(); GetVmMemory().DecommitAll();
SysClearExecutionCache(); SysClearExecutionCache();
sApp.PostAppMethod( &Pcsx2App::leaveDebugMode ); sApp.PostAppMethod(&Pcsx2App::leaveDebugMode);
g_FrameCount = 0; g_FrameCount = 0;
} }
@ -148,24 +150,27 @@ void SysCoreThread::Reset()
// resets of the core and components (including plugins, if needed). The scope of resetting // resets of the core and components (including plugins, if needed). The scope of resetting
// is determined by comparing the current settings against the new settings, so that only // is determined by comparing the current settings against the new settings, so that only
// real differences are applied. // real differences are applied.
void SysCoreThread::ApplySettings( const Pcsx2Config& src ) void SysCoreThread::ApplySettings(const Pcsx2Config& src)
{ {
if( src == EmuConfig ) return; if (src == EmuConfig)
return;
if( !pxAssertDev( IsPaused(), "CoreThread is not paused; settings cannot be applied." ) ) return; if (!pxAssertDev(IsPaused(), "CoreThread is not paused; settings cannot be applied."))
return;
m_resetRecompilers = ( src.Cpu != EmuConfig.Cpu ) || ( src.Gamefixes != EmuConfig.Gamefixes ) || ( src.Speedhacks != EmuConfig.Speedhacks ); m_resetRecompilers = (src.Cpu != EmuConfig.Cpu) || (src.Gamefixes != EmuConfig.Gamefixes) || (src.Speedhacks != EmuConfig.Speedhacks);
m_resetProfilers = ( src.Profiler != EmuConfig.Profiler ); m_resetProfilers = (src.Profiler != EmuConfig.Profiler);
m_resetVsyncTimers = ( src.GS != EmuConfig.GS ); m_resetVsyncTimers = (src.GS != EmuConfig.GS);
const_cast<Pcsx2Config&>(EmuConfig) = src; const_cast<Pcsx2Config&>(EmuConfig) = src;
} }
void SysCoreThread::UploadStateCopy( const VmStateBuffer& copy ) void SysCoreThread::UploadStateCopy(const VmStateBuffer& copy)
{ {
if( !pxAssertDev( IsPaused(), "CoreThread is not paused; new VM state cannot be uploaded." ) ) return; if (!pxAssertDev(IsPaused(), "CoreThread is not paused; new VM state cannot be uploaded."))
return;
memLoadingState loadme( copy ); memLoadingState loadme(copy);
loadme.FreezeAll(); loadme.FreezeAll();
m_resetVirtualMachine = false; m_resetVirtualMachine = false;
} }
@ -187,38 +192,38 @@ void SysCoreThread::_reset_stuff_as_needed()
GetVmMemory().CommitAll(); GetVmMemory().CommitAll();
if( m_resetVirtualMachine || m_resetRecompilers || m_resetProfilers ) if (m_resetVirtualMachine || m_resetRecompilers || m_resetProfilers)
{ {
SysClearExecutionCache(); SysClearExecutionCache();
memBindConditionalHandlers(); memBindConditionalHandlers();
SetCPUState( EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR ); SetCPUState(EmuConfig.Cpu.sseMXCSR, EmuConfig.Cpu.sseVUMXCSR);
m_resetRecompilers = false; m_resetRecompilers = false;
m_resetProfilers = false; m_resetProfilers = false;
} }
if( m_resetVirtualMachine ) if (m_resetVirtualMachine)
{ {
DoCpuReset(); DoCpuReset();
m_resetVirtualMachine = false; m_resetVirtualMachine = false;
m_resetVsyncTimers = false; m_resetVsyncTimers = false;
ForgetLoadedPatches(); ForgetLoadedPatches();
} }
if( m_resetVsyncTimers ) if (m_resetVsyncTimers)
{ {
UpdateVSyncRate(); UpdateVSyncRate();
frameLimitReset(); frameLimitReset();
m_resetVsyncTimers = false; m_resetVsyncTimers = false;
} }
} }
void SysCoreThread::DoCpuReset() void SysCoreThread::DoCpuReset()
{ {
AffinityAssert_AllowFromSelf( pxDiagSpot ); AffinityAssert_AllowFromSelf(pxDiagSpot);
cpuReset(); cpuReset();
} }
@ -240,7 +245,7 @@ void SysCoreThread::GameStartingInThread()
{ {
GetMTGS().SendGameCRC(ElfCRC); GetMTGS().SendGameCRC(ElfCRC);
MIPSAnalyst::ScanForFunctions(ElfTextRange.first,ElfTextRange.first+ElfTextRange.second,true); MIPSAnalyst::ScanForFunctions(ElfTextRange.first, ElfTextRange.first + ElfTextRange.second, true);
symbolMap.UpdateActiveSymbols(); symbolMap.UpdateActiveSymbols();
sApp.PostAppMethod(&Pcsx2App::resetDebugger); sApp.PostAppMethod(&Pcsx2App::resetDebugger);
@ -280,12 +285,15 @@ void SysCoreThread::ExecuteTaskInThread()
m_mxcsr_saved.bitmask = _mm_getcsr(); m_mxcsr_saved.bitmask = _mm_getcsr();
PCSX2_PAGEFAULT_PROTECT { PCSX2_PAGEFAULT_PROTECT
while(true) { {
while (true)
{
StateCheckInThread(); StateCheckInThread();
DoCpuExecute(); DoCpuExecute();
} }
} PCSX2_PAGEFAULT_EXCEPT; }
PCSX2_PAGEFAULT_EXCEPT;
} }
void SysCoreThread::OnSuspendInThread() void SysCoreThread::OnSuspendInThread()
@ -293,41 +301,40 @@ void SysCoreThread::OnSuspendInThread()
GetCorePlugins().Close(); GetCorePlugins().Close();
DoCDVDclose(); DoCDVDclose();
FWclose(); FWclose();
SPU2close(); SPU2close();
} }
void SysCoreThread::OnResumeInThread( bool isSuspended ) void SysCoreThread::OnResumeInThread(bool isSuspended)
{ {
GetCorePlugins().Open(); GetCorePlugins().Open();
if (isSuspended || !g_GameStarted) if (isSuspended || !g_GameStarted)
DoCDVDopen(); DoCDVDopen();
FWopen(); FWopen();
SPU2open((void*)pDsp); SPU2open((void*)pDsp);
} }
// Invoked by the pthread_exit or pthread_cancel. // Invoked by the pthread_exit or pthread_cancel.
void SysCoreThread::OnCleanupInThread() void SysCoreThread::OnCleanupInThread()
{ {
m_ExecMode = ExecMode_Closing; m_ExecMode = ExecMode_Closing;
m_hasActiveMachine = false; m_hasActiveMachine = false;
m_resetVirtualMachine = true; m_resetVirtualMachine = true;
R3000A::ioman::reset(); R3000A::ioman::reset();
// FIXME: temporary workaround for deadlock on exit, which actually should be a crash // FIXME: temporary workaround for deadlock on exit, which actually should be a crash
vu1Thread.WaitVU(); vu1Thread.WaitVU();
SPU2close();
DoCDVDclose(); DoCDVDclose();
FWclose(); FWclose();
SPU2close();
GetCorePlugins().Close(); GetCorePlugins().Close();
GetCorePlugins().Shutdown(); GetCorePlugins().Shutdown();
SPU2shutdown(); SPU2shutdown();
_mm_setcsr( m_mxcsr_saved.bitmask ); _mm_setcsr(m_mxcsr_saved.bitmask);
Threading::DisableHiresScheduler(); Threading::DisableHiresScheduler();
_parent::OnCleanupInThread(); _parent::OnCleanupInThread();
m_ExecMode = ExecMode_NoThreadYet; m_ExecMode = ExecMode_NoThreadYet;
} }

View File

@ -45,8 +45,8 @@ typedef void (AppCoreThread::*FnPtr_CoreThreadMethod)();
class SysExecEvent_InvokeCoreThreadMethod : public SysExecEvent class SysExecEvent_InvokeCoreThreadMethod : public SysExecEvent
{ {
protected: protected:
FnPtr_CoreThreadMethod m_method; FnPtr_CoreThreadMethod m_method;
bool m_IsCritical; bool m_IsCritical;
public: public:
wxString GetEventName() const { return L"CoreThreadMethod"; } wxString GetEventName() const { return L"CoreThreadMethod"; }
@ -56,7 +56,7 @@ public:
bool AllowCancelOnExit() const { return false; } bool AllowCancelOnExit() const { return false; }
bool IsCriticalEvent() const { return m_IsCritical; } bool IsCriticalEvent() const { return m_IsCritical; }
SysExecEvent_InvokeCoreThreadMethod( FnPtr_CoreThreadMethod method, bool critical=false ) SysExecEvent_InvokeCoreThreadMethod(FnPtr_CoreThreadMethod method, bool critical = false)
{ {
m_method = method; m_method = method;
m_IsCritical = critical; m_IsCritical = critical;
@ -71,27 +71,30 @@ public:
protected: protected:
void InvokeEvent() void InvokeEvent()
{ {
if( m_method ) (CoreThread.*m_method)(); if (m_method)
(CoreThread.*m_method)();
} }
}; };
static void PostCoreStatus( CoreThreadStatus pevt ) static void PostCoreStatus(CoreThreadStatus pevt)
{ {
sApp.PostAction( CoreThreadStatusEvent( pevt ) ); sApp.PostAction(CoreThreadStatusEvent(pevt));
} }
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// AppCoreThread Implementations // AppCoreThread Implementations
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
AppCoreThread::AppCoreThread() : SysCoreThread() AppCoreThread::AppCoreThread()
: SysCoreThread()
{ {
m_resetCdvd = false; m_resetCdvd = false;
} }
AppCoreThread::~AppCoreThread() AppCoreThread::~AppCoreThread()
{ {
try { try
_parent::Cancel(); // use parent's, skips thread affinity check. {
_parent::Cancel(); // use parent's, skips thread affinity check.
} }
DESTRUCTOR_CATCHALL DESTRUCTOR_CATCHALL
} }
@ -101,17 +104,17 @@ static void _Cancel()
GetCoreThread().Cancel(); GetCoreThread().Cancel();
} }
void AppCoreThread::Cancel( bool isBlocking ) void AppCoreThread::Cancel(bool isBlocking)
{ {
if (GetSysExecutorThread().IsRunning() && !GetSysExecutorThread().Rpc_TryInvoke( _Cancel, L"AppCoreThread::Cancel" )) if (GetSysExecutorThread().IsRunning() && !GetSysExecutorThread().Rpc_TryInvoke(_Cancel, L"AppCoreThread::Cancel"))
_parent::Cancel( wxTimeSpan(0, 0, 4, 0) ); _parent::Cancel(wxTimeSpan(0, 0, 4, 0));
} }
void AppCoreThread::Reset() void AppCoreThread::Reset()
{ {
if( !GetSysExecutorThread().IsSelf() ) if (!GetSysExecutorThread().IsSelf())
{ {
GetSysExecutorThread().PostEvent( SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::Reset) ); GetSysExecutorThread().PostEvent(SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::Reset));
return; return;
} }
@ -120,9 +123,9 @@ void AppCoreThread::Reset()
void AppCoreThread::ResetQuick() void AppCoreThread::ResetQuick()
{ {
if( !GetSysExecutorThread().IsSelf() ) if (!GetSysExecutorThread().IsSelf())
{ {
GetSysExecutorThread().PostEvent( SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::ResetQuick) ); GetSysExecutorThread().PostEvent(SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::ResetQuick));
return; return;
} }
@ -139,48 +142,50 @@ static void _Suspend()
GetCoreThread().Suspend(true); GetCoreThread().Suspend(true);
} }
void AppCoreThread::Suspend( bool isBlocking ) void AppCoreThread::Suspend(bool isBlocking)
{ {
if (IsClosed()) return; if (IsClosed())
return;
if (IsSelf()) if (IsSelf())
{ {
// this should never fail... // this should never fail...
bool result = GetSysExecutorThread().Rpc_TryInvokeAsync( _Suspend, L"AppCoreThread::Suspend" ); bool result = GetSysExecutorThread().Rpc_TryInvokeAsync(_Suspend, L"AppCoreThread::Suspend");
pxAssert(result); pxAssert(result);
} }
else if (!GetSysExecutorThread().Rpc_TryInvoke( _Suspend, L"AppCoreThread::Suspend" )) else if (!GetSysExecutorThread().Rpc_TryInvoke(_Suspend, L"AppCoreThread::Suspend"))
_parent::Suspend(true); _parent::Suspend(true);
} }
void AppCoreThread::Resume() void AppCoreThread::Resume()
{ {
if( !GetSysExecutorThread().IsSelf() ) if (!GetSysExecutorThread().IsSelf())
{ {
GetSysExecutorThread().PostEvent( SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::Resume) ); GetSysExecutorThread().PostEvent(SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::Resume));
return; return;
} }
GetCorePlugins().Init(); GetCorePlugins().Init();
SPU2init(); SPU2init();
_parent::Resume(); _parent::Resume();
} }
void AppCoreThread::ChangeCdvdSource() void AppCoreThread::ChangeCdvdSource()
{ {
if( !GetSysExecutorThread().IsSelf() ) if (!GetSysExecutorThread().IsSelf())
{ {
GetSysExecutorThread().PostEvent( new SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::ChangeCdvdSource) ); GetSysExecutorThread().PostEvent(new SysExecEvent_InvokeCoreThreadMethod(&AppCoreThread::ChangeCdvdSource));
return; return;
} }
CDVD_SourceType cdvdsrc( g_Conf->CdvdSource ); CDVD_SourceType cdvdsrc(g_Conf->CdvdSource);
if( cdvdsrc == CDVDsys_GetSourceType() ) return; if (cdvdsrc == CDVDsys_GetSourceType())
return;
// Fast change of the CDVD source only -- a Pause will suffice. // Fast change of the CDVD source only -- a Pause will suffice.
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
CDVDsys_ChangeSource( cdvdsrc ); CDVDsys_ChangeSource(cdvdsrc);
paused_core.AllowResume(); paused_core.AllowResume();
// TODO: Add a listener for CDVDsource changes? Or should we bother? // TODO: Add a listener for CDVDsource changes? Or should we bother?
@ -188,24 +193,25 @@ void AppCoreThread::ChangeCdvdSource()
void Pcsx2App::SysApplySettings() void Pcsx2App::SysApplySettings()
{ {
if( AppRpc_TryInvoke(&Pcsx2App::SysApplySettings) ) return; if (AppRpc_TryInvoke(&Pcsx2App::SysApplySettings))
CoreThread.ApplySettings( g_Conf->EmuOptions ); return;
CoreThread.ApplySettings(g_Conf->EmuOptions);
CDVD_SourceType cdvdsrc( g_Conf->CdvdSource ); CDVD_SourceType cdvdsrc(g_Conf->CdvdSource);
if( cdvdsrc != CDVDsys_GetSourceType() || (cdvdsrc == CDVD_SourceType::Iso && (CDVDsys_GetFile(cdvdsrc) != g_Conf->CurrentIso)) ) if (cdvdsrc != CDVDsys_GetSourceType() || (cdvdsrc == CDVD_SourceType::Iso && (CDVDsys_GetFile(cdvdsrc) != g_Conf->CurrentIso)))
{ {
CoreThread.ResetCdvd(); CoreThread.ResetCdvd();
} }
CDVDsys_SetFile(CDVD_SourceType::Iso, g_Conf->CurrentIso ); CDVDsys_SetFile(CDVD_SourceType::Iso, g_Conf->CurrentIso);
} }
void AppCoreThread::OnResumeReady() void AppCoreThread::OnResumeReady()
{ {
wxGetApp().SysApplySettings(); wxGetApp().SysApplySettings();
wxGetApp().PostMethod( AppSaveSettings ); wxGetApp().PostMethod(AppSaveSettings);
sApp.PostAppMethod( &Pcsx2App::leaveDebugMode ); sApp.PostAppMethod(&Pcsx2App::leaveDebugMode);
_parent::OnResumeReady(); _parent::OnResumeReady();
} }
@ -224,10 +230,12 @@ void AppCoreThread::OnPauseDebug()
// Load Game Settings found in database // Load Game Settings found in database
// (game fixes, round modes, clamp modes, etc...) // (game fixes, round modes, clamp modes, etc...)
// Returns number of gamefixes set // Returns number of gamefixes set
static int loadGameSettings(Pcsx2Config& dest, const Game_Data& game) { static int loadGameSettings(Pcsx2Config& dest, const Game_Data& game)
if( !game.IsOk() ) return 0; {
if (!game.IsOk())
return 0;
int gf = 0; int gf = 0;
if (game.keyExists("eeRoundMode")) if (game.keyExists("eeRoundMode"))
{ {
@ -251,35 +259,38 @@ static int loadGameSettings(Pcsx2Config& dest, const Game_Data& game) {
} }
} }
if (game.keyExists("eeClampMode")) { if (game.keyExists("eeClampMode"))
{
int clampMode = game.getInt("eeClampMode"); int clampMode = game.getInt("eeClampMode");
PatchesCon->WriteLn("(GameDB) Changing EE/FPU clamp mode [mode=%d]", clampMode); PatchesCon->WriteLn("(GameDB) Changing EE/FPU clamp mode [mode=%d]", clampMode);
dest.Cpu.Recompiler.fpuOverflow = (clampMode >= 1); dest.Cpu.Recompiler.fpuOverflow = (clampMode >= 1);
dest.Cpu.Recompiler.fpuExtraOverflow = (clampMode >= 2); dest.Cpu.Recompiler.fpuExtraOverflow = (clampMode >= 2);
dest.Cpu.Recompiler.fpuFullMode = (clampMode >= 3); dest.Cpu.Recompiler.fpuFullMode = (clampMode >= 3);
gf++; gf++;
} }
if (game.keyExists("vuClampMode")) { if (game.keyExists("vuClampMode"))
{
int clampMode = game.getInt("vuClampMode"); int clampMode = game.getInt("vuClampMode");
PatchesCon->WriteLn("(GameDB) Changing VU0/VU1 clamp mode [mode=%d]", clampMode); PatchesCon->WriteLn("(GameDB) Changing VU0/VU1 clamp mode [mode=%d]", clampMode);
dest.Cpu.Recompiler.vuOverflow = (clampMode >= 1); dest.Cpu.Recompiler.vuOverflow = (clampMode >= 1);
dest.Cpu.Recompiler.vuExtraOverflow = (clampMode >= 2); dest.Cpu.Recompiler.vuExtraOverflow = (clampMode >= 2);
dest.Cpu.Recompiler.vuSignOverflow = (clampMode >= 3); dest.Cpu.Recompiler.vuSignOverflow = (clampMode >= 3);
gf++; gf++;
} }
if (game.keyExists("mvuFlagSpeedHack")) { if (game.keyExists("mvuFlagSpeedHack"))
{
bool vuFlagHack = game.getInt("mvuFlagSpeedHack") ? 1 : 0; bool vuFlagHack = game.getInt("mvuFlagSpeedHack") ? 1 : 0;
PatchesCon->WriteLn("(GameDB) Changing mVU flag speed hack [mode=%d]", vuFlagHack); PatchesCon->WriteLn("(GameDB) Changing mVU flag speed hack [mode=%d]", vuFlagHack);
dest.Speedhacks.vuFlagHack = vuFlagHack; dest.Speedhacks.vuFlagHack = vuFlagHack;
gf++; gf++;
} }
for( GamefixId id=GamefixId_FIRST; id<pxEnumEnd; ++id ) for (GamefixId id = GamefixId_FIRST; id < pxEnumEnd; ++id)
{ {
wxString key( EnumToString(id) ); wxString key(EnumToString(id));
key += L"Hack"; key += L"Hack";
if (game.keyExists(key)) if (game.keyExists(key))
@ -313,7 +324,7 @@ void PatchesVerboseReset()
// PatchesCon points to either Console or ConsoleWriter_Null, such that if we're in Devel mode // PatchesCon points to either Console or ConsoleWriter_Null, such that if we're in Devel mode
// or the user enabled the devel/verbose console it prints all patching info whenever it's applied, // or the user enabled the devel/verbose console it prints all patching info whenever it's applied,
// else it prints the patching info only once - right after boot. // else it prints the patching info only once - right after boot.
const IConsoleWriter *PatchesCon = &Console; const IConsoleWriter* PatchesCon = &Console;
static void SetupPatchesCon(bool verbose) static void SetupPatchesCon(bool verbose)
{ {
@ -335,7 +346,7 @@ static void SetupPatchesCon(bool verbose)
// It doesn't require that the emulation is paused, and console writes/title should // It doesn't require that the emulation is paused, and console writes/title should
// be thread safe, but it's best if things don't move around much while it runs. // be thread safe, but it's best if things don't move around much while it runs.
static Threading::Mutex mtx__ApplySettings; static Threading::Mutex mtx__ApplySettings;
static void _ApplySettings( const Pcsx2Config& src, Pcsx2Config& fixup ) static void _ApplySettings(const Pcsx2Config& src, Pcsx2Config& fixup)
{ {
Threading::ScopedLock lock(mtx__ApplySettings); Threading::ScopedLock lock(mtx__ApplySettings);
// 'fixup' is the EmuConfig we're going to upload to the emulator, which very well may // 'fixup' is the EmuConfig we're going to upload to the emulator, which very well may
@ -348,19 +359,19 @@ static void _ApplySettings( const Pcsx2Config& src, Pcsx2Config& fixup )
fixup = src; fixup = src;
const CommandlineOverrides& overrides( wxGetApp().Overrides ); const CommandlineOverrides& overrides(wxGetApp().Overrides);
if( overrides.DisableSpeedhacks || !g_Conf->EnableSpeedHacks ) if (overrides.DisableSpeedhacks || !g_Conf->EnableSpeedHacks)
fixup.Speedhacks.DisableAll(); fixup.Speedhacks.DisableAll();
if( overrides.ApplyCustomGamefixes ) if (overrides.ApplyCustomGamefixes)
{ {
for (GamefixId id=GamefixId_FIRST; id < pxEnumEnd; ++id) for (GamefixId id = GamefixId_FIRST; id < pxEnumEnd; ++id)
fixup.Gamefixes.Set( id, overrides.Gamefixes.Get(id) ); fixup.Gamefixes.Set(id, overrides.Gamefixes.Get(id));
} }
else if( !g_Conf->EnableGameFixes ) else if (!g_Conf->EnableGameFixes)
fixup.Gamefixes.DisableAll(); fixup.Gamefixes.DisableAll();
if( overrides.ProfilingMode ) if (overrides.ProfilingMode)
{ {
fixup.GS.FrameLimitEnable = false; fixup.GS.FrameLimitEnable = false;
fixup.GS.VsyncEnable = VsyncMode::Off; fixup.GS.VsyncEnable = VsyncMode::Off;
@ -383,11 +394,12 @@ static void _ApplySettings( const Pcsx2Config& src, Pcsx2Config& fixup )
// settings as if the game is already running (title, loadeding patches, etc). // settings as if the game is already running (title, loadeding patches, etc).
bool ingame = (ElfCRC && (g_GameLoading || g_GameStarted)); bool ingame = (ElfCRC && (g_GameLoading || g_GameStarted));
if (ingame) if (ingame)
gameCRC.Printf( L"%8.8x", ElfCRC ); gameCRC.Printf(L"%8.8x", ElfCRC);
if (ingame && !DiscSerial.IsEmpty()) gameSerial = L" [" + DiscSerial + L"]"; if (ingame && !DiscSerial.IsEmpty())
gameSerial = L" [" + DiscSerial + L"]";
const wxString newGameKey(ingame ? SysGetDiscID() : SysGetBiosDiscID()); const wxString newGameKey(ingame ? SysGetDiscID() : SysGetBiosDiscID());
const bool verbose( newGameKey != curGameKey && ingame ); const bool verbose(newGameKey != curGameKey && ingame);
//Console.WriteLn(L"------> patches verbose: %d prev: '%s' new: '%s'", (int)verbose, WX_STR(curGameKey), WX_STR(newGameKey)); //Console.WriteLn(L"------> patches verbose: %d prev: '%s' new: '%s'", (int)verbose, WX_STR(curGameKey), WX_STR(newGameKey));
SetupPatchesCon(verbose); SetupPatchesCon(verbose);
@ -397,15 +409,15 @@ static void _ApplySettings( const Pcsx2Config& src, Pcsx2Config& fixup )
if (!curGameKey.IsEmpty()) if (!curGameKey.IsEmpty())
{ {
if (IGameDatabase* GameDB = AppHost_GetGameDatabase() ) if (IGameDatabase* GameDB = AppHost_GetGameDatabase())
{ {
Game_Data game; Game_Data game;
if (GameDB->findGame(game, curGameKey)) if (GameDB->findGame(game, curGameKey))
{ {
int compat = game.getInt("Compat"); int compat = game.getInt("Compat");
gameName = game.getString("Name"); gameName = game.getString("Name");
gameName += L" (" + game.getString("Region") + L")"; gameName += L" (" + game.getString("Region") + L")";
gameCompat = L" [Status = "+compatToStringWX(compat)+L"]"; gameCompat = L" [Status = " + compatToStringWX(compat) + L"]";
gameMemCardFilter = game.getString("MemCardFilter"); gameMemCardFilter = game.getString("MemCardFilter");
} }
@ -499,7 +511,7 @@ void LoadAllPatchesAndStuff(const Pcsx2Config& cfg)
#endif #endif
} }
void AppCoreThread::ApplySettings( const Pcsx2Config& src ) void AppCoreThread::ApplySettings(const Pcsx2Config& src)
{ {
// Re-entry guard protects against cases where code wants to manually set core settings // Re-entry guard protects against cases where code wants to manually set core settings
// which are not part of g_Conf. The subsequent call to apply g_Conf settings (which is // which are not part of g_Conf. The subsequent call to apply g_Conf settings (which is
@ -508,19 +520,21 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
_ApplySettings(src, fixup); _ApplySettings(src, fixup);
static int localc = 0; static int localc = 0;
RecursionGuard guard( localc ); RecursionGuard guard(localc);
if( guard.IsReentrant() ) return; if (guard.IsReentrant())
if( fixup == EmuConfig ) return; return;
if (fixup == EmuConfig)
return;
if( m_ExecMode >= ExecMode_Opened ) if (m_ExecMode >= ExecMode_Opened)
{ {
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
_parent::ApplySettings( fixup ); _parent::ApplySettings(fixup);
paused_core.AllowResume(); paused_core.AllowResume();
} }
else else
{ {
_parent::ApplySettings( fixup ); _parent::ApplySettings(fixup);
} }
if (m_ExecMode >= ExecMode_Paused) if (m_ExecMode >= ExecMode_Paused)
@ -534,27 +548,27 @@ void AppCoreThread::ApplySettings( const Pcsx2Config& src )
void AppCoreThread::DoCpuReset() void AppCoreThread::DoCpuReset()
{ {
PostCoreStatus( CoreThread_Reset ); PostCoreStatus(CoreThread_Reset);
_parent::DoCpuReset(); _parent::DoCpuReset();
} }
void AppCoreThread::OnResumeInThread( bool isSuspended ) void AppCoreThread::OnResumeInThread(bool isSuspended)
{ {
if( m_resetCdvd ) if (m_resetCdvd)
{ {
CDVDsys_ChangeSource( g_Conf->CdvdSource ); CDVDsys_ChangeSource(g_Conf->CdvdSource);
cdvdCtrlTrayOpen(); cdvdCtrlTrayOpen();
m_resetCdvd = false; m_resetCdvd = false;
} }
_parent::OnResumeInThread( isSuspended ); _parent::OnResumeInThread(isSuspended);
PostCoreStatus( CoreThread_Resumed ); PostCoreStatus(CoreThread_Resumed);
} }
void AppCoreThread::OnSuspendInThread() void AppCoreThread::OnSuspendInThread()
{ {
_parent::OnSuspendInThread(); _parent::OnSuspendInThread();
PostCoreStatus( CoreThread_Suspended ); PostCoreStatus(CoreThread_Suspended);
} }
// Called whenever the thread has terminated, for either regular or irregular reasons. // Called whenever the thread has terminated, for either regular or irregular reasons.
@ -564,7 +578,7 @@ void AppCoreThread::OnSuspendInThread()
void AppCoreThread::OnCleanupInThread() void AppCoreThread::OnCleanupInThread()
{ {
m_ExecMode = ExecMode_Closing; m_ExecMode = ExecMode_Closing;
PostCoreStatus( CoreThread_Stopped ); PostCoreStatus(CoreThread_Stopped);
_parent::OnCleanupInThread(); _parent::OnCleanupInThread();
} }
@ -593,10 +607,10 @@ bool AppCoreThread::StateCheckInThread()
return _parent::StateCheckInThread(); return _parent::StateCheckInThread();
} }
void AppCoreThread::UploadStateCopy( const VmStateBuffer& copy ) void AppCoreThread::UploadStateCopy(const VmStateBuffer& copy)
{ {
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
_parent::UploadStateCopy( copy ); _parent::UploadStateCopy(copy);
paused_core.AllowResume(); paused_core.AllowResume();
} }
@ -604,23 +618,24 @@ static uint m_except_threshold = 0;
void AppCoreThread::ExecuteTaskInThread() void AppCoreThread::ExecuteTaskInThread()
{ {
PostCoreStatus( CoreThread_Started ); PostCoreStatus(CoreThread_Started);
m_except_threshold = 0; m_except_threshold = 0;
_parent::ExecuteTaskInThread(); _parent::ExecuteTaskInThread();
} }
void AppCoreThread::DoCpuExecute() void AppCoreThread::DoCpuExecute()
{ {
try { try
{
_parent::DoCpuExecute(); _parent::DoCpuExecute();
} }
catch (BaseR5900Exception& ex) catch (BaseR5900Exception& ex)
{ {
Console.Error( ex.FormatMessage() ); Console.Error(ex.FormatMessage());
// [TODO] : Debugger Hook! // [TODO] : Debugger Hook!
if( ++m_except_threshold > 6 ) if (++m_except_threshold > 6)
{ {
// If too many TLB Misses occur, we're probably going to crash and // If too many TLB Misses occur, we're probably going to crash and
// the game is probably running miserably. // the game is probably running miserably.
@ -629,7 +644,7 @@ void AppCoreThread::DoCpuExecute()
//Suspend(); //Suspend();
// [TODO] Issue error dialog to the user here... // [TODO] Issue error dialog to the user here...
Console.Error( "Too many execution errors. VM execution has been suspended!" ); Console.Error("Too many execution errors. VM execution has been suspended!");
// Hack: this keeps the EE thread from running more code while the SysExecutor // Hack: this keeps the EE thread from running more code while the SysExecutor
// thread catches up and signals it for suspension. // thread catches up and signals it for suspension.
@ -641,33 +656,34 @@ void AppCoreThread::DoCpuExecute()
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// BaseSysExecEvent_ScopedCore / SysExecEvent_CoreThreadClose / SysExecEvent_CoreThreadPause // BaseSysExecEvent_ScopedCore / SysExecEvent_CoreThreadClose / SysExecEvent_CoreThreadPause
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
void BaseSysExecEvent_ScopedCore::_post_and_wait( IScopedCoreThread& core ) void BaseSysExecEvent_ScopedCore::_post_and_wait(IScopedCoreThread& core)
{ {
DoScopedTask(); DoScopedTask();
ScopedLock lock( m_mtx_resume ); ScopedLock lock(m_mtx_resume);
PostResult(); PostResult();
if( m_resume ) if (m_resume)
{ {
// If the sender of the message requests a non-blocking resume, then we need // If the sender of the message requests a non-blocking resume, then we need
// to deallocate the m_sync object, since the sender will likely leave scope and // to deallocate the m_sync object, since the sender will likely leave scope and
// invalidate it. // invalidate it.
switch( m_resume->WaitForResult() ) switch (m_resume->WaitForResult())
{ {
case ScopedCore_BlockingResume: case ScopedCore_BlockingResume:
if( m_sync ) m_sync->ClearResult(); if (m_sync)
m_sync->ClearResult();
core.AllowResume(); core.AllowResume();
break; break;
case ScopedCore_NonblockingResume: case ScopedCore_NonblockingResume:
m_sync = NULL; m_sync = NULL;
core.AllowResume(); core.AllowResume();
break; break;
case ScopedCore_SkipResume: case ScopedCore_SkipResume:
m_sync = NULL; m_sync = NULL;
break; break;
} }
} }
} }
@ -691,10 +707,10 @@ void SysExecEvent_CoreThreadPause::InvokeEvent()
// All plugins should be initialized and opened upon resuming from // All plugins should be initialized and opened upon resuming from
// a paused state. If the thread that puased us changed plugin status, it should // a paused state. If the thread that puased us changed plugin status, it should
// have used Close instead. // have used Close instead.
if( CorePluginsAreOpen ) if (CorePluginsAreOpen)
{ {
CorePluginsAreOpen = GetCorePlugins().AreOpen(); CorePluginsAreOpen = GetCorePlugins().AreOpen();
pxAssertDev( CorePluginsAreOpen, "Invalid plugin close/shutdown detected during paused CoreThread; please Stop/Suspend the core instead." ); pxAssertDev(CorePluginsAreOpen, "Invalid plugin close/shutdown detected during paused CoreThread; please Stop/Suspend the core instead.");
} }
paused_core.AllowResume(); paused_core.AllowResume();
@ -712,16 +728,16 @@ void SysExecEvent_CoreThreadPause::InvokeEvent()
// ScopedCoreThreadClose / ScopedCoreThreadPause // ScopedCoreThreadClose / ScopedCoreThreadPause
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
static DeclareTls(bool) ScopedCore_IsPaused = false; static DeclareTls(bool) ScopedCore_IsPaused = false;
static DeclareTls(bool) ScopedCore_IsFullyClosed = false; static DeclareTls(bool) ScopedCore_IsFullyClosed = false;
BaseScopedCoreThread::BaseScopedCoreThread() BaseScopedCoreThread::BaseScopedCoreThread()
{ {
//AffinityAssert_AllowFrom_MainUI(); //AffinityAssert_AllowFrom_MainUI();
m_allowResume = false; m_allowResume = false;
m_alreadyStopped = false; m_alreadyStopped = false;
m_alreadyScoped = false; m_alreadyScoped = false;
} }
BaseScopedCoreThread::~BaseScopedCoreThread() = default; BaseScopedCoreThread::~BaseScopedCoreThread() = default;
@ -741,11 +757,12 @@ void BaseScopedCoreThread::DisallowResume()
void BaseScopedCoreThread::DoResume() void BaseScopedCoreThread::DoResume()
{ {
if( m_alreadyStopped ) return; if (m_alreadyStopped)
if( !GetSysExecutorThread().IsSelf() ) return;
if (!GetSysExecutorThread().IsSelf())
{ {
//DbgCon.WriteLn("(ScopedCoreThreadPause) Threaded Scope Created!"); //DbgCon.WriteLn("(ScopedCoreThreadPause) Threaded Scope Created!");
m_sync_resume.PostResult( m_allowResume ? ScopedCore_NonblockingResume : ScopedCore_SkipResume ); m_sync_resume.PostResult(m_allowResume ? ScopedCore_NonblockingResume : ScopedCore_SkipResume);
m_mtx_resume.Wait(); m_mtx_resume.Wait();
} }
else else
@ -755,15 +772,16 @@ void BaseScopedCoreThread::DoResume()
// Returns TRUE if the event is posted to the SysExecutor. // Returns TRUE if the event is posted to the SysExecutor.
// Returns FALSE if the thread *is* the SysExecutor (no message is posted, calling code should // Returns FALSE if the thread *is* the SysExecutor (no message is posted, calling code should
// handle the code directly). // handle the code directly).
bool BaseScopedCoreThread::PostToSysExec( BaseSysExecEvent_ScopedCore* msg ) bool BaseScopedCoreThread::PostToSysExec(BaseSysExecEvent_ScopedCore* msg)
{ {
std::unique_ptr<BaseSysExecEvent_ScopedCore> smsg( msg ); std::unique_ptr<BaseSysExecEvent_ScopedCore> smsg(msg);
if( !smsg || GetSysExecutorThread().IsSelf()) return false; if (!smsg || GetSysExecutorThread().IsSelf())
return false;
msg->SetSyncState(m_sync); msg->SetSyncState(m_sync);
msg->SetResumeStates(m_sync_resume, m_mtx_resume); msg->SetResumeStates(m_sync_resume, m_mtx_resume);
GetSysExecutorThread().PostEvent( smsg.release() ); GetSysExecutorThread().PostEvent(smsg.release());
m_sync.WaitForResult(); m_sync.WaitForResult();
m_sync.RethrowException(); m_sync.RethrowException();
@ -772,17 +790,17 @@ bool BaseScopedCoreThread::PostToSysExec( BaseSysExecEvent_ScopedCore* msg )
ScopedCoreThreadClose::ScopedCoreThreadClose() ScopedCoreThreadClose::ScopedCoreThreadClose()
{ {
if( ScopedCore_IsFullyClosed ) if (ScopedCore_IsFullyClosed)
{ {
// tracks if we're already in scope or not. // tracks if we're already in scope or not.
m_alreadyScoped = true; m_alreadyScoped = true;
return; return;
} }
if( !PostToSysExec(new SysExecEvent_CoreThreadClose()) ) if (!PostToSysExec(new SysExecEvent_CoreThreadClose()))
{ {
m_alreadyStopped = CoreThread.IsClosed(); m_alreadyStopped = CoreThread.IsClosed();
if ( !m_alreadyStopped ) if (!m_alreadyStopped)
CoreThread.Suspend(); CoreThread.Suspend();
} }
@ -791,28 +809,31 @@ ScopedCoreThreadClose::ScopedCoreThreadClose()
ScopedCoreThreadClose::~ScopedCoreThreadClose() ScopedCoreThreadClose::~ScopedCoreThreadClose()
{ {
if( m_alreadyScoped ) return; if (m_alreadyScoped)
try { return;
try
{
_parent::DoResume(); _parent::DoResume();
ScopedCore_IsFullyClosed = false; ScopedCore_IsFullyClosed = false;
} }
DESTRUCTOR_CATCHALL DESTRUCTOR_CATCHALL
} }
ScopedCoreThreadPause::ScopedCoreThreadPause( BaseSysExecEvent_ScopedCore* abuse_me ) ScopedCoreThreadPause::ScopedCoreThreadPause(BaseSysExecEvent_ScopedCore* abuse_me)
{ {
if( ScopedCore_IsFullyClosed || ScopedCore_IsPaused ) if (ScopedCore_IsFullyClosed || ScopedCore_IsPaused)
{ {
// tracks if we're already in scope or not. // tracks if we're already in scope or not.
m_alreadyScoped = true; m_alreadyScoped = true;
return; return;
} }
if( !abuse_me ) abuse_me = new SysExecEvent_CoreThreadPause(); if (!abuse_me)
if( !PostToSysExec( abuse_me ) ) abuse_me = new SysExecEvent_CoreThreadPause();
if (!PostToSysExec(abuse_me))
{ {
m_alreadyStopped = CoreThread.IsPaused(); m_alreadyStopped = CoreThread.IsPaused();
if( !m_alreadyStopped ) if (!m_alreadyStopped)
CoreThread.Pause(); CoreThread.Pause();
} }
@ -821,8 +842,10 @@ ScopedCoreThreadPause::ScopedCoreThreadPause( BaseSysExecEvent_ScopedCore* abuse
ScopedCoreThreadPause::~ScopedCoreThreadPause() ScopedCoreThreadPause::~ScopedCoreThreadPause()
{ {
if( m_alreadyScoped ) return; if (m_alreadyScoped)
try { return;
try
{
_parent::DoResume(); _parent::DoResume();
ScopedCore_IsPaused = false; ScopedCore_IsPaused = false;
} }
@ -835,7 +858,7 @@ ScopedCoreThreadPopup::ScopedCoreThreadPopup()
// ensure that the GS window isn't blocking the popup, and to avoid crashes if the GS window // ensure that the GS window isn't blocking the popup, and to avoid crashes if the GS window
// is maximized or fullscreen. // is maximized or fullscreen.
if( !GSopen2 ) if (!GSopen2)
m_scoped_core = std::unique_ptr<BaseScopedCoreThread>(new ScopedCoreThreadClose()); m_scoped_core = std::unique_ptr<BaseScopedCoreThread>(new ScopedCoreThreadClose());
else else
m_scoped_core = std::unique_ptr<BaseScopedCoreThread>(new ScopedCoreThreadPause()); m_scoped_core = std::unique_ptr<BaseScopedCoreThread>(new ScopedCoreThreadPause());
@ -843,10 +866,12 @@ ScopedCoreThreadPopup::ScopedCoreThreadPopup()
void ScopedCoreThreadPopup::AllowResume() void ScopedCoreThreadPopup::AllowResume()
{ {
if( m_scoped_core ) m_scoped_core->AllowResume(); if (m_scoped_core)
m_scoped_core->AllowResume();
} }
void ScopedCoreThreadPopup::DisallowResume() void ScopedCoreThreadPopup::DisallowResume()
{ {
if( m_scoped_core ) m_scoped_core->DisallowResume(); if (m_scoped_core)
m_scoped_core->DisallowResume();
} }

View File

@ -23,8 +23,8 @@
#include "AppSaveStates.h" #include "AppSaveStates.h"
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
# include "Recording/InputRecordingControls.h" #include "Recording/InputRecordingControls.h"
# include "Recording/InputRecording.h" #include "Recording/InputRecording.h"
#endif #endif
// Various includes needed for dumping... // Various includes needed for dumping...
@ -43,15 +43,18 @@ extern bool switchAR;
static int g_Pcsx2Recording = 0; // true 1 if recording video and sound static int g_Pcsx2Recording = 0; // true 1 if recording video and sound
KeyAcceleratorCode::KeyAcceleratorCode( const wxKeyEvent& evt ) KeyAcceleratorCode::KeyAcceleratorCode(const wxKeyEvent& evt)
{ {
val32 = 0; val32 = 0;
keycode = evt.GetKeyCode(); keycode = evt.GetKeyCode();
if( evt.AltDown() ) Alt(); if (evt.AltDown())
if( evt.CmdDown() ) Cmd(); Alt();
if( evt.ShiftDown() ) Shift(); if (evt.CmdDown())
Cmd();
if (evt.ShiftDown())
Shift();
} }
wxString KeyAcceleratorCode::ToString() const wxString KeyAcceleratorCode::ToString() const
@ -59,11 +62,11 @@ wxString KeyAcceleratorCode::ToString() const
// Let's use wx's string formatter: // Let's use wx's string formatter:
return wxAcceleratorEntry( return wxAcceleratorEntry(
(cmd ? wxACCEL_CMD : 0) | (cmd ? wxACCEL_CMD : 0) |
(shift ? wxACCEL_SHIFT : 0) | (shift ? wxACCEL_SHIFT : 0) |
(alt ? wxACCEL_ALT : 0), (alt ? wxACCEL_ALT : 0),
keycode keycode)
).ToString(); .ToString();
} }
LimiterModeType g_LimiterMode = Limit_Nominal; LimiterModeType g_LimiterMode = Limit_Nominal;
@ -75,11 +78,14 @@ namespace Implementations
g_Conf->EmuOptions.GS.FrameSkipEnable = !g_Conf->EmuOptions.GS.FrameSkipEnable; g_Conf->EmuOptions.GS.FrameSkipEnable = !g_Conf->EmuOptions.GS.FrameSkipEnable;
SetGSConfig().FrameSkipEnable = g_Conf->EmuOptions.GS.FrameSkipEnable; SetGSConfig().FrameSkipEnable = g_Conf->EmuOptions.GS.FrameSkipEnable;
if( EmuConfig.GS.FrameSkipEnable ) { if (EmuConfig.GS.FrameSkipEnable)
OSDlog( Color_StrongRed, true, "(FrameSkipping) Enabled." ); {
OSDlog( Color_StrongRed, true, " FrameDraws=%d, FrameSkips=%d", g_Conf->EmuOptions.GS.FramesToDraw, g_Conf->EmuOptions.GS.FramesToSkip ); OSDlog(Color_StrongRed, true, "(FrameSkipping) Enabled.");
} else { OSDlog(Color_StrongRed, true, " FrameDraws=%d, FrameSkips=%d", g_Conf->EmuOptions.GS.FramesToDraw, g_Conf->EmuOptions.GS.FramesToSkip);
OSDlog( Color_StrongRed, true, "(FrameSkipping) Disabled." ); }
else
{
OSDlog(Color_StrongRed, true, "(FrameSkipping) Disabled.");
} }
} }
@ -87,25 +93,25 @@ namespace Implementations
{ {
ScopedCoreThreadPause pauser; ScopedCoreThreadPause pauser;
if( !g_Conf->EmuOptions.GS.FrameLimitEnable ) if (!g_Conf->EmuOptions.GS.FrameLimitEnable)
{ {
g_Conf->EmuOptions.GS.FrameLimitEnable = true; g_Conf->EmuOptions.GS.FrameLimitEnable = true;
g_LimiterMode = Limit_Turbo; g_LimiterMode = Limit_Turbo;
OSDlog( Color_StrongRed, true, "(FrameLimiter) Turbo + FrameLimit ENABLED." ); OSDlog(Color_StrongRed, true, "(FrameLimiter) Turbo + FrameLimit ENABLED.");
g_Conf->EmuOptions.GS.FrameSkipEnable = !!g_Conf->Framerate.SkipOnTurbo; g_Conf->EmuOptions.GS.FrameSkipEnable = !!g_Conf->Framerate.SkipOnTurbo;
} }
else if( g_LimiterMode == Limit_Turbo ) else if (g_LimiterMode == Limit_Turbo)
{ {
g_LimiterMode = Limit_Nominal; g_LimiterMode = Limit_Nominal;
if ( g_Conf->Framerate.SkipOnLimit) if (g_Conf->Framerate.SkipOnLimit)
{ {
OSDlog( Color_StrongRed, true, "(FrameLimiter) Turbo DISABLED. Frameskip ENABLED" ); OSDlog(Color_StrongRed, true, "(FrameLimiter) Turbo DISABLED. Frameskip ENABLED");
g_Conf->EmuOptions.GS.FrameSkipEnable = true; g_Conf->EmuOptions.GS.FrameSkipEnable = true;
} }
else else
{ {
OSDlog( Color_StrongRed, true, "(FrameLimiter) Turbo DISABLED." ); OSDlog(Color_StrongRed, true, "(FrameLimiter) Turbo DISABLED.");
g_Conf->EmuOptions.GS.FrameSkipEnable = false; g_Conf->EmuOptions.GS.FrameSkipEnable = false;
} }
} }
@ -113,14 +119,14 @@ namespace Implementations
{ {
g_LimiterMode = Limit_Turbo; g_LimiterMode = Limit_Turbo;
if ( g_Conf->Framerate.SkipOnTurbo) if (g_Conf->Framerate.SkipOnTurbo)
{ {
OSDlog( Color_StrongRed, true, "(FrameLimiter) Turbo + Frameskip ENABLED." ); OSDlog(Color_StrongRed, true, "(FrameLimiter) Turbo + Frameskip ENABLED.");
g_Conf->EmuOptions.GS.FrameSkipEnable = true; g_Conf->EmuOptions.GS.FrameSkipEnable = true;
} }
else else
{ {
OSDlog( Color_StrongRed, true, "(FrameLimiter) Turbo ENABLED." ); OSDlog(Color_StrongRed, true, "(FrameLimiter) Turbo ENABLED.");
g_Conf->EmuOptions.GS.FrameSkipEnable = false; g_Conf->EmuOptions.GS.FrameSkipEnable = false;
} }
} }
@ -139,15 +145,15 @@ namespace Implementations
// out a better consistency approach... -air // out a better consistency approach... -air
ScopedCoreThreadPause pauser; ScopedCoreThreadPause pauser;
if( g_LimiterMode == Limit_Slomo ) if (g_LimiterMode == Limit_Slomo)
{ {
g_LimiterMode = Limit_Nominal; g_LimiterMode = Limit_Nominal;
OSDlog( Color_StrongRed, true, "(FrameLimiter) SlowMotion DISABLED." ); OSDlog(Color_StrongRed, true, "(FrameLimiter) SlowMotion DISABLED.");
} }
else else
{ {
g_LimiterMode = Limit_Slomo; g_LimiterMode = Limit_Slomo;
OSDlog( Color_StrongRed, true, "(FrameLimiter) SlowMotion ENABLED." ); OSDlog(Color_StrongRed, true, "(FrameLimiter) SlowMotion ENABLED.");
g_Conf->EmuOptions.GS.FrameLimitEnable = true; g_Conf->EmuOptions.GS.FrameLimitEnable = true;
} }
@ -160,7 +166,7 @@ namespace Implementations
{ {
ScopedCoreThreadPause pauser; ScopedCoreThreadPause pauser;
g_Conf->EmuOptions.GS.FrameLimitEnable = !g_Conf->EmuOptions.GS.FrameLimitEnable; g_Conf->EmuOptions.GS.FrameLimitEnable = !g_Conf->EmuOptions.GS.FrameLimitEnable;
OSDlog( Color_StrongRed, true, "(FrameLimiter) %s.", g_Conf->EmuOptions.GS.FrameLimitEnable ? "ENABLED" : "DISABLED" ); OSDlog(Color_StrongRed, true, "(FrameLimiter) %s.", g_Conf->EmuOptions.GS.FrameLimitEnable ? "ENABLED" : "DISABLED");
// Turbo/Slowmo don't make sense when framelimiter is toggled // Turbo/Slowmo don't make sense when framelimiter is toggled
g_LimiterMode = Limit_Nominal; g_LimiterMode = Limit_Nominal;
@ -181,15 +187,25 @@ namespace Implementations
void GSwindow_CycleAspectRatio() void GSwindow_CycleAspectRatio()
{ {
AspectRatioType& art = g_Conf->GSWindow.AspectRatio; AspectRatioType& art = g_Conf->GSWindow.AspectRatio;
const char *arts = "Not modified"; const char* arts = "Not modified";
if (art == AspectRatio_Stretch && switchAR) //avoids a double 4:3 when coming from FMV aspect ratio switch if (art == AspectRatio_Stretch && switchAR) //avoids a double 4:3 when coming from FMV aspect ratio switch
art = AspectRatio_4_3; art = AspectRatio_4_3;
switch( art ) switch (art)
{ {
case AspectRatio_Stretch: art = AspectRatio_4_3; arts = "4:3"; break; case AspectRatio_Stretch:
case AspectRatio_4_3: art = AspectRatio_16_9; arts = "16:9"; break; art = AspectRatio_4_3;
case AspectRatio_16_9: art = AspectRatio_Stretch; arts = "Stretch"; break; arts = "4:3";
default: break; break;
case AspectRatio_4_3:
art = AspectRatio_16_9;
arts = "16:9";
break;
case AspectRatio_16_9:
art = AspectRatio_Stretch;
arts = "Stretch";
break;
default:
break;
} }
OSDlog(Color_StrongBlue, true, "(GSwindow) Aspect ratio: %s", arts); OSDlog(Color_StrongBlue, true, "(GSwindow) Aspect ratio: %s", arts);
@ -200,66 +216,70 @@ namespace Implementations
{ {
g_Conf->GSWindow.OffsetX = x; g_Conf->GSWindow.OffsetX = x;
g_Conf->GSWindow.OffsetY = y; g_Conf->GSWindow.OffsetY = y;
OSDlog( Color_StrongBlue, true, "(GSwindow) Offset: x=%f, y=%f", x,y); OSDlog(Color_StrongBlue, true, "(GSwindow) Offset: x=%f, y=%f", x, y);
UpdateImagePosition(); UpdateImagePosition();
} }
void GSwindow_OffsetYplus(){ void GSwindow_OffsetYplus()
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat(), g_Conf->GSWindow.OffsetY.ToFloat()+1); {
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat(), g_Conf->GSWindow.OffsetY.ToFloat() + 1);
} }
void GSwindow_OffsetYminus(){ void GSwindow_OffsetYminus()
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat(), g_Conf->GSWindow.OffsetY.ToFloat()-1); {
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat(), g_Conf->GSWindow.OffsetY.ToFloat() - 1);
} }
void GSwindow_OffsetXplus(){ void GSwindow_OffsetXplus()
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat()+1, g_Conf->GSWindow.OffsetY.ToFloat()); {
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat() + 1, g_Conf->GSWindow.OffsetY.ToFloat());
} }
void GSwindow_OffsetXminus(){ void GSwindow_OffsetXminus()
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat()-1, g_Conf->GSWindow.OffsetY.ToFloat()); {
SetOffset(g_Conf->GSWindow.OffsetX.ToFloat() - 1, g_Conf->GSWindow.OffsetY.ToFloat());
} }
void GSwindow_OffsetReset(){ void GSwindow_OffsetReset()
SetOffset(0,0); {
SetOffset(0, 0);
} }
void SetZoomY(float zoom) void SetZoomY(float zoom)
{ {
if( zoom <= 0 ) if (zoom <= 0)
return; return;
g_Conf->GSWindow.StretchY = zoom; g_Conf->GSWindow.StretchY = zoom;
OSDlog( Color_StrongBlue, true, "(GSwindow) Vertical stretch: %f", zoom); OSDlog(Color_StrongBlue, true, "(GSwindow) Vertical stretch: %f", zoom);
UpdateImagePosition(); UpdateImagePosition();
} }
void GSwindow_ZoomInY() void GSwindow_ZoomInY()
{ {
SetZoomY( g_Conf->GSWindow.StretchY.ToFloat()+1 ); SetZoomY(g_Conf->GSWindow.StretchY.ToFloat() + 1);
} }
void GSwindow_ZoomOutY() void GSwindow_ZoomOutY()
{ {
SetZoomY( g_Conf->GSWindow.StretchY.ToFloat()-1 ); SetZoomY(g_Conf->GSWindow.StretchY.ToFloat() - 1);
} }
void GSwindow_ZoomResetY() void GSwindow_ZoomResetY()
{ {
SetZoomY( 100 ); SetZoomY(100);
} }
void SetZoom(float zoom) void SetZoom(float zoom)
{ {
if( zoom < 0 ) if (zoom < 0)
return; return;
g_Conf->GSWindow.Zoom = zoom; g_Conf->GSWindow.Zoom = zoom;
if ( zoom == 0 ) if (zoom == 0)
OSDlog( Color_StrongBlue, true, "(GSwindow) Zoom: 0 (auto, no black bars)"); OSDlog(Color_StrongBlue, true, "(GSwindow) Zoom: 0 (auto, no black bars)");
else else
OSDlog( Color_StrongBlue, true, "(GSwindow) Zoom: %f", zoom); OSDlog(Color_StrongBlue, true, "(GSwindow) Zoom: %f", zoom);
UpdateImagePosition(); UpdateImagePosition();
} }
@ -267,31 +287,36 @@ namespace Implementations
void GSwindow_ZoomIn() void GSwindow_ZoomIn()
{ {
float z = g_Conf->GSWindow.Zoom.ToFloat(); float z = g_Conf->GSWindow.Zoom.ToFloat();
if( z==0 ) z = 100; if (z == 0)
z = 100;
z++; z++;
SetZoom( z ); SetZoom(z);
} }
void GSwindow_ZoomOut() void GSwindow_ZoomOut()
{ {
float z = g_Conf->GSWindow.Zoom.ToFloat(); float z = g_Conf->GSWindow.Zoom.ToFloat();
if( z==0 ) z = 100; if (z == 0)
z = 100;
z--; z--;
SetZoom( z ); SetZoom(z);
} }
void GSwindow_ZoomToggle() void GSwindow_ZoomToggle()
{ {
float z = g_Conf->GSWindow.Zoom.ToFloat(); float z = g_Conf->GSWindow.Zoom.ToFloat();
if( z==100 ) z = 0; if (z == 100)
else z = 100; z = 0;
else
z = 100;
SetZoom( z ); SetZoom(z);
} }
void Sys_Suspend() void Sys_Suspend()
{ {
GSFrame* gsframe = wxGetApp().GetGsFramePtr(); GSFrame* gsframe = wxGetApp().GetGsFramePtr();
if (gsframe && gsframe->IsShown() && gsframe->IsFullScreen()) { if (gsframe && gsframe->IsShown() && gsframe->IsFullScreen())
{
// On some cases, probably due to driver bugs, if we don't exit fullscreen then // On some cases, probably due to driver bugs, if we don't exit fullscreen then
// the content stays on screen. Try to prevent that by first exiting fullscreen, // the content stays on screen. Try to prevent that by first exiting fullscreen,
// but don't update the internal PCSX2 state/config, and PCSX2 will restore // but don't update the internal PCSX2 state/config, and PCSX2 will restore
@ -304,7 +329,8 @@ namespace Implementations
CoreThread.Suspend(); CoreThread.Suspend();
gsframe = wxGetApp().GetGsFramePtr(); // just in case suspend removes this window gsframe = wxGetApp().GetGsFramePtr(); // just in case suspend removes this window
if (gsframe && !wxGetApp().HasGUI() && g_Conf->GSWindow.CloseOnEsc) { if (gsframe && !wxGetApp().HasGUI() && g_Conf->GSWindow.CloseOnEsc)
{
// When we run with --nogui, PCSX2 only knows to exit when the gs window closes. // When we run with --nogui, PCSX2 only knows to exit when the gs window closes.
// However, by default suspend just hides the gs window, so PCSX2 will not exit // However, by default suspend just hides the gs window, so PCSX2 will not exit
// and there will also be no way to exit it even if no windows are left. // and there will also be no way to exit it even if no windows are left.
@ -313,7 +339,7 @@ namespace Implementations
// So if we're set to close on esc and nogui: // So if we're set to close on esc and nogui:
// If the user didn't specify --noguiprompt - exit immediately. // If the user didn't specify --noguiprompt - exit immediately.
// else prompt to either exit or abort the suspend. // else prompt to either exit or abort the suspend.
if (!wxGetApp().ExitPromptWithNoGUI() // configured to exit without a dialog if (!wxGetApp().ExitPromptWithNoGUI() // configured to exit without a dialog
|| (wxOK == wxMessageBox(_("Exit PCSX2?"), // or confirmed exit at the dialog || (wxOK == wxMessageBox(_("Exit PCSX2?"), // or confirmed exit at the dialog
L"PCSX2", L"PCSX2",
wxICON_WARNING | wxOK | wxCANCEL))) wxICON_WARNING | wxOK | wxCANCEL)))
@ -358,14 +384,14 @@ namespace Implementations
void Sys_TakeSnapshot() void Sys_TakeSnapshot()
{ {
GSmakeSnapshot( g_Conf->Folders.Snapshots.ToUTF8() ); GSmakeSnapshot(g_Conf->Folders.Snapshots.ToUTF8());
} }
void Sys_RenderToggle() void Sys_RenderToggle()
{ {
if(renderswitch_delay == 0) if (renderswitch_delay == 0)
{ {
ScopedCoreThreadPause paused_core( new SysExecEvent_SaveSinglePlugin(PluginId_GS) ); ScopedCoreThreadPause paused_core(new SysExecEvent_SaveSinglePlugin(PluginId_GS));
renderswitch = !renderswitch; renderswitch = !renderswitch;
paused_core.AllowResume(); paused_core.AllowResume();
renderswitch_delay = -1; renderswitch_delay = -1;
@ -379,7 +405,7 @@ namespace Implementations
// --arcum42 // --arcum42
// FIXME: Some of the trace logs will require recompiler resets to be activated properly. // FIXME: Some of the trace logs will require recompiler resets to be activated properly.
#ifdef PCSX2_DEVBUILD #ifdef PCSX2_DEVBUILD
SetTraceConfig().Enabled = !EmuConfig.Trace.Enabled; SetTraceConfig().Enabled = !EmuConfig.Trace.Enabled;
Console.WriteLn(EmuConfig.Trace.Enabled ? "Logging Enabled." : "Logging Disabled."); Console.WriteLn(EmuConfig.Trace.Enabled ? "Logging Enabled." : "Logging Disabled.");
#endif #endif
@ -390,28 +416,27 @@ namespace Implementations
// fixme : fix up gsstate mess and make it mtgs compatible -- air // fixme : fix up gsstate mess and make it mtgs compatible -- air
#ifdef _STGS_GSSTATE_CODE #ifdef _STGS_GSSTATE_CODE
wxString Text; wxString Text;
if( strgametitle[0] != 0 ) if (strgametitle[0] != 0)
{ {
// only take the first two words // only take the first two words
wxString gsText; wxString gsText;
wxStringTokenizer parts( strgametitle, L" " ); wxStringTokenizer parts(strgametitle, L" ");
wxString name( parts.GetNextToken() ); // first part wxString name(parts.GetNextToken()); // first part
wxString part2( parts.GetNextToken() ); wxString part2(parts.GetNextToken());
if( !!part2 ) if (!!part2)
name += L"_" + part2; name += L"_" + part2;
gsText.Printf( L"%s.%d.gs", WX_STR(name), StatesC ); gsText.Printf(L"%s.%d.gs", WX_STR(name), StatesC);
Text = Path::Combine( g_Conf->Folders.Savestates, gsText ); Text = Path::Combine(g_Conf->Folders.Savestates, gsText);
} }
else else
{ {
Text = GetGSStateFilename(); Text = GetGSStateFilename();
} }
#endif #endif
} }
void Sys_RecordingToggle() void Sys_RecordingToggle()
@ -421,7 +446,7 @@ namespace Implementations
g_Pcsx2Recording ^= 1; g_Pcsx2Recording ^= 1;
GetMTGS().WaitGS(); // make sure GS is in sync with the audio stream when we start. GetMTGS().WaitGS(); // make sure GS is in sync with the audio stream when we start.
if (g_Pcsx2Recording) if (g_Pcsx2Recording)
{ {
// start recording // start recording
@ -478,8 +503,8 @@ namespace Implementations
void FullscreenToggle() void FullscreenToggle()
{ {
if( GSFrame* gsframe = wxGetApp().GetGsFramePtr() ) if (GSFrame* gsframe = wxGetApp().GetGsFramePtr())
gsframe->ShowFullScreen( !gsframe->IsFullScreen() ); gsframe->ShowFullScreen(!gsframe->IsFullScreen());
} }
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
void FrameAdvance() void FrameAdvance()
@ -618,7 +643,7 @@ namespace Implementations
States_LoadSlot(9); States_LoadSlot(9);
} }
#endif #endif
} } // namespace Implementations
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
// CommandDeclarations table // CommandDeclarations table
@ -629,201 +654,221 @@ namespace Implementations
// goold old fashioned way! :) // goold old fashioned way! :)
static const GlobalCommandDescriptor CommandDeclarations[] = static const GlobalCommandDescriptor CommandDeclarations[] =
{ {
{ "States_FreezeCurrentSlot", {
States_FreezeCurrentSlot, "States_FreezeCurrentSlot",
pxL( "Save state" ), States_FreezeCurrentSlot,
pxL( "Saves the virtual machine state to the current slot." ), pxL("Save state"),
false, pxL("Saves the virtual machine state to the current slot."),
}, false,
},
{ "States_DefrostCurrentSlot", {
States_DefrostCurrentSlot, "States_DefrostCurrentSlot",
pxL( "Load state" ), States_DefrostCurrentSlot,
pxL( "Loads a virtual machine state from the current slot." ), pxL("Load state"),
false, pxL("Loads a virtual machine state from the current slot."),
}, false,
},
{ "States_DefrostCurrentSlotBackup", {
States_DefrostCurrentSlotBackup, "States_DefrostCurrentSlotBackup",
pxL( "Load State Backup" ), States_DefrostCurrentSlotBackup,
pxL( "Loads virtual machine state backup for current slot." ), pxL("Load State Backup"),
false, pxL("Loads virtual machine state backup for current slot."),
}, false,
},
{ "States_CycleSlotForward", {
States_CycleSlotForward, "States_CycleSlotForward",
pxL( "Cycle to next slot" ), States_CycleSlotForward,
pxL( "Cycles the current save slot in +1 fashion!" ), pxL("Cycle to next slot"),
false, pxL("Cycles the current save slot in +1 fashion!"),
}, false,
},
{ "States_CycleSlotBackward", {
States_CycleSlotBackward, "States_CycleSlotBackward",
pxL( "Cycle to prev slot" ), States_CycleSlotBackward,
pxL( "Cycles the current save slot in -1 fashion!" ), pxL("Cycle to prev slot"),
false, pxL("Cycles the current save slot in -1 fashion!"),
}, false,
},
{ "Frameskip_Toggle", {
Implementations::Frameskip_Toggle, "Frameskip_Toggle",
NULL, Implementations::Frameskip_Toggle,
NULL, NULL,
false, NULL,
}, false,
},
{ "Framelimiter_TurboToggle", {
Implementations::Framelimiter_TurboToggle, "Framelimiter_TurboToggle",
NULL, Implementations::Framelimiter_TurboToggle,
NULL, NULL,
false, NULL,
}, false,
},
{ "Framelimiter_SlomoToggle", {
Implementations::Framelimiter_SlomoToggle, "Framelimiter_SlomoToggle",
NULL, Implementations::Framelimiter_SlomoToggle,
NULL, NULL,
false, NULL,
}, false,
},
{ "Framelimiter_MasterToggle", {
Implementations::Framelimiter_MasterToggle, "Framelimiter_MasterToggle",
NULL, Implementations::Framelimiter_MasterToggle,
NULL, NULL,
false, NULL,
}, false,
},
{ "GSwindow_CycleAspectRatio", {
Implementations::GSwindow_CycleAspectRatio, "GSwindow_CycleAspectRatio",
NULL, Implementations::GSwindow_CycleAspectRatio,
NULL, NULL,
true, NULL,
}, true,
},
{ "GSwindow_ZoomIn", {
Implementations::GSwindow_ZoomIn, "GSwindow_ZoomIn",
NULL, Implementations::GSwindow_ZoomIn,
NULL, NULL,
false, NULL,
}, false,
},
{ "GSwindow_ZoomOut", {
Implementations::GSwindow_ZoomOut, "GSwindow_ZoomOut",
NULL, Implementations::GSwindow_ZoomOut,
NULL, NULL,
false, NULL,
}, false,
},
{ "GSwindow_ZoomToggle", {
Implementations::GSwindow_ZoomToggle, "GSwindow_ZoomToggle",
NULL, Implementations::GSwindow_ZoomToggle,
NULL, NULL,
false, NULL,
}, false,
},
{ "GSwindow_ZoomInY" , Implementations::GSwindow_ZoomInY , NULL, NULL, false}, {"GSwindow_ZoomInY", Implementations::GSwindow_ZoomInY, NULL, NULL, false},
{ "GSwindow_ZoomOutY" , Implementations::GSwindow_ZoomOutY , NULL, NULL, false}, {"GSwindow_ZoomOutY", Implementations::GSwindow_ZoomOutY, NULL, NULL, false},
{ "GSwindow_ZoomResetY" , Implementations::GSwindow_ZoomResetY , NULL, NULL, false}, {"GSwindow_ZoomResetY", Implementations::GSwindow_ZoomResetY, NULL, NULL, false},
{ "GSwindow_OffsetYminus", Implementations::GSwindow_OffsetYminus, NULL, NULL, false}, {"GSwindow_OffsetYminus", Implementations::GSwindow_OffsetYminus, NULL, NULL, false},
{ "GSwindow_OffsetYplus" , Implementations::GSwindow_OffsetYplus , NULL, NULL, false}, {"GSwindow_OffsetYplus", Implementations::GSwindow_OffsetYplus, NULL, NULL, false},
{ "GSwindow_OffsetXminus", Implementations::GSwindow_OffsetXminus, NULL, NULL, false}, {"GSwindow_OffsetXminus", Implementations::GSwindow_OffsetXminus, NULL, NULL, false},
{ "GSwindow_OffsetXplus" , Implementations::GSwindow_OffsetXplus , NULL, NULL, false}, {"GSwindow_OffsetXplus", Implementations::GSwindow_OffsetXplus, NULL, NULL, false},
{ "GSwindow_OffsetReset" , Implementations::GSwindow_OffsetReset , NULL, NULL, false}, {"GSwindow_OffsetReset", Implementations::GSwindow_OffsetReset, NULL, NULL, false},
{ "Sys_SuspendResume", {
Implementations::Sys_SuspendResume, "Sys_SuspendResume",
NULL, Implementations::Sys_SuspendResume,
NULL, NULL,
false, NULL,
}, false,
},
{ "Sys_TakeSnapshot", {
Implementations::Sys_TakeSnapshot, "Sys_TakeSnapshot",
NULL, Implementations::Sys_TakeSnapshot,
NULL, NULL,
false, NULL,
}, false,
},
{ "Sys_RenderswitchToggle", {
Implementations::Sys_RenderToggle, "Sys_RenderswitchToggle",
NULL, Implementations::Sys_RenderToggle,
NULL, NULL,
false, NULL,
}, false,
},
{ "Sys_LoggingToggle", {
Implementations::Sys_LoggingToggle, "Sys_LoggingToggle",
NULL, Implementations::Sys_LoggingToggle,
NULL, NULL,
false, NULL,
}, false,
},
{ "Sys_FreezeGS", {
Implementations::Sys_FreezeGS, "Sys_FreezeGS",
NULL, Implementations::Sys_FreezeGS,
NULL, NULL,
false, NULL,
}, false,
{ "Sys_RecordingToggle", },
Implementations::Sys_RecordingToggle, {
NULL, "Sys_RecordingToggle",
NULL, Implementations::Sys_RecordingToggle,
false, NULL,
}, NULL,
false,
},
{ "FullscreenToggle", {
Implementations::FullscreenToggle, "FullscreenToggle",
NULL, Implementations::FullscreenToggle,
NULL, NULL,
false, NULL,
}, false,
},
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
{ "FrameAdvance" , Implementations::FrameAdvance, NULL, NULL, false }, {"FrameAdvance", Implementations::FrameAdvance, NULL, NULL, false},
{ "TogglePause" , Implementations::TogglePause, NULL, NULL, false }, {"TogglePause", Implementations::TogglePause, NULL, NULL, false},
{ "InputRecordingModeToggle" , Implementations::InputRecordingModeToggle, NULL, NULL, false }, {"InputRecordingModeToggle", Implementations::InputRecordingModeToggle, NULL, NULL, false},
{ "States_SaveSlot0" , Implementations::States_SaveSlot0, NULL, NULL, false }, {"States_SaveSlot0", Implementations::States_SaveSlot0, NULL, NULL, false},
{ "States_SaveSlot1" , Implementations::States_SaveSlot1, NULL, NULL, false }, {"States_SaveSlot1", Implementations::States_SaveSlot1, NULL, NULL, false},
{ "States_SaveSlot2" , Implementations::States_SaveSlot2, NULL, NULL, false }, {"States_SaveSlot2", Implementations::States_SaveSlot2, NULL, NULL, false},
{ "States_SaveSlot3" , Implementations::States_SaveSlot3, NULL, NULL, false }, {"States_SaveSlot3", Implementations::States_SaveSlot3, NULL, NULL, false},
{ "States_SaveSlot4" , Implementations::States_SaveSlot4, NULL, NULL, false }, {"States_SaveSlot4", Implementations::States_SaveSlot4, NULL, NULL, false},
{ "States_SaveSlot5" , Implementations::States_SaveSlot5, NULL, NULL, false }, {"States_SaveSlot5", Implementations::States_SaveSlot5, NULL, NULL, false},
{ "States_SaveSlot6" , Implementations::States_SaveSlot6, NULL, NULL, false }, {"States_SaveSlot6", Implementations::States_SaveSlot6, NULL, NULL, false},
{ "States_SaveSlot7" , Implementations::States_SaveSlot7, NULL, NULL, false }, {"States_SaveSlot7", Implementations::States_SaveSlot7, NULL, NULL, false},
{ "States_SaveSlot8" , Implementations::States_SaveSlot8, NULL, NULL, false }, {"States_SaveSlot8", Implementations::States_SaveSlot8, NULL, NULL, false},
{ "States_SaveSlot9" , Implementations::States_SaveSlot9, NULL, NULL, false }, {"States_SaveSlot9", Implementations::States_SaveSlot9, NULL, NULL, false},
{ "States_LoadSlot0" , Implementations::States_LoadSlot0, NULL, NULL, false }, {"States_LoadSlot0", Implementations::States_LoadSlot0, NULL, NULL, false},
{ "States_LoadSlot1" , Implementations::States_LoadSlot1, NULL, NULL, false }, {"States_LoadSlot1", Implementations::States_LoadSlot1, NULL, NULL, false},
{ "States_LoadSlot2" , Implementations::States_LoadSlot2, NULL, NULL, false }, {"States_LoadSlot2", Implementations::States_LoadSlot2, NULL, NULL, false},
{ "States_LoadSlot3" , Implementations::States_LoadSlot3, NULL, NULL, false }, {"States_LoadSlot3", Implementations::States_LoadSlot3, NULL, NULL, false},
{ "States_LoadSlot4" , Implementations::States_LoadSlot4, NULL, NULL, false }, {"States_LoadSlot4", Implementations::States_LoadSlot4, NULL, NULL, false},
{ "States_LoadSlot5" , Implementations::States_LoadSlot5, NULL, NULL, false }, {"States_LoadSlot5", Implementations::States_LoadSlot5, NULL, NULL, false},
{ "States_LoadSlot6" , Implementations::States_LoadSlot6, NULL, NULL, false }, {"States_LoadSlot6", Implementations::States_LoadSlot6, NULL, NULL, false},
{ "States_LoadSlot7" , Implementations::States_LoadSlot7, NULL, NULL, false }, {"States_LoadSlot7", Implementations::States_LoadSlot7, NULL, NULL, false},
{ "States_LoadSlot8" , Implementations::States_LoadSlot8, NULL, NULL, false }, {"States_LoadSlot8", Implementations::States_LoadSlot8, NULL, NULL, false},
{ "States_LoadSlot9" , Implementations::States_LoadSlot9, NULL, NULL, false }, {"States_LoadSlot9", Implementations::States_LoadSlot9, NULL, NULL, false},
#endif #endif
// Command Declarations terminator: // Command Declarations terminator:
// (must always be last in list!!) // (must always be last in list!!)
{ NULL } {NULL}};
};
void AcceleratorDictionary::Map( const KeyAcceleratorCode& _acode, const char *searchfor ) void AcceleratorDictionary::Map(const KeyAcceleratorCode& _acode, const char* searchfor)
{ {
// Search override mapping at ini file // Search override mapping at ini file
KeyAcceleratorCode acode = _acode; KeyAcceleratorCode acode = _acode;
wxString overrideStr; wxString overrideStr;
wxAcceleratorEntry codeParser; //Provides string parsing capabilities wxAcceleratorEntry codeParser; //Provides string parsing capabilities
wxFileConfig cfg(L"", L"", L"" , GetUiKeysFilename(), wxCONFIG_USE_GLOBAL_FILE ); wxFileConfig cfg(L"", L"", L"", GetUiKeysFilename(), wxCONFIG_USE_GLOBAL_FILE);
if( cfg.Read( wxString::FromUTF8(searchfor), &overrideStr) ) if (cfg.Read(wxString::FromUTF8(searchfor), &overrideStr))
{ {
// needs a '\t' prefix (originally used for wxMenu accelerators parsing)... // needs a '\t' prefix (originally used for wxMenu accelerators parsing)...
if (codeParser.FromString(wxString(L"\t") + overrideStr)) if (codeParser.FromString(wxString(L"\t") + overrideStr))
{ {
// ini file contains alternative parsable key combination for current 'searchfor'. // ini file contains alternative parsable key combination for current 'searchfor'.
acode = codeParser; acode = codeParser;
if (acode.keycode >= 'A' && acode.keycode <= 'Z') { if (acode.keycode >= 'A' && acode.keycode <= 'Z')
{
// Note that this needs to match the key event codes at Pcsx2App::PadKeyDispatch // Note that this needs to match the key event codes at Pcsx2App::PadKeyDispatch
// Our canonical representation is the char code (at lower case if // Our canonical representation is the char code (at lower case if
// applicable) with a separate modifier indicator, including shift. // applicable) with a separate modifier indicator, including shift.
@ -833,9 +878,10 @@ void AcceleratorDictionary::Map( const KeyAcceleratorCode& _acode, const char *s
// So we only need to change upper case letters to lower case. // So we only need to change upper case letters to lower case.
acode.keycode += 'a' - 'A'; acode.keycode += 'a' - 'A';
} }
if (_acode.ToString() != acode.ToString()) { if (_acode.ToString() != acode.ToString())
{
Console.WriteLn(Color_StrongGreen, L"Overriding '%s': assigning %s (instead of %s)", Console.WriteLn(Color_StrongGreen, L"Overriding '%s': assigning %s (instead of %s)",
WX_STR(fromUTF8(searchfor)), WX_STR(acode.ToString()), WX_STR(_acode.ToString())); WX_STR(fromUTF8(searchfor)), WX_STR(acode.ToString()), WX_STR(_acode.ToString()));
} }
} }
else else
@ -852,13 +898,12 @@ void AcceleratorDictionary::Map( const KeyAcceleratorCode& _acode, const char *s
if (iter != end()) if (iter != end())
result = iter->second; result = iter->second;
if( result != NULL ) if (result != NULL)
{ {
Console.Warning( Console.Warning(
L"Kbd Accelerator '%s' is mapped multiple times.\n" L"Kbd Accelerator '%s' is mapped multiple times.\n"
L"\t'Command %s' is being replaced by '%s'", L"\t'Command %s' is being replaced by '%s'",
WX_STR(acode.ToString()), WX_STR(fromUTF8( result->Id )), WX_STR(fromUTF8( searchfor )) WX_STR(acode.ToString()), WX_STR(fromUTF8(result->Id)), WX_STR(fromUTF8(searchfor)));
);
} }
std::unordered_map<std::string, const GlobalCommandDescriptor*>::const_iterator acceleratorIter(wxGetApp().GlobalCommands->find(searchfor)); std::unordered_map<std::string, const GlobalCommandDescriptor*>::const_iterator acceleratorIter(wxGetApp().GlobalCommands->find(searchfor));
@ -866,15 +911,15 @@ void AcceleratorDictionary::Map( const KeyAcceleratorCode& _acode, const char *s
if (acceleratorIter != wxGetApp().GlobalCommands->end()) if (acceleratorIter != wxGetApp().GlobalCommands->end())
result = acceleratorIter->second; result = acceleratorIter->second;
if( result == NULL ) if (result == NULL)
{ {
Console.Warning( L"Kbd Accelerator '%s' is mapped to unknown command '%s'", Console.Warning(L"Kbd Accelerator '%s' is mapped to unknown command '%s'",
WX_STR(acode.ToString()), WX_STR(fromUTF8( searchfor )) WX_STR(acode.ToString()), WX_STR(fromUTF8(searchfor)));
);
} }
else else
{ {
if (!strcmp("Sys_TakeSnapshot", searchfor)) { if (!strcmp("Sys_TakeSnapshot", searchfor))
{
// Sys_TakeSnapshot is special in a bad way. On its own it creates a screenshot // Sys_TakeSnapshot is special in a bad way. On its own it creates a screenshot
// but GSdx also checks whether shift or ctrl are held down, and for each of // but GSdx also checks whether shift or ctrl are held down, and for each of
// them it does a different thing (gs dumps). So we need to map a shortcut and // them it does a different thing (gs dumps). So we need to map a shortcut and
@ -885,26 +930,31 @@ void AcceleratorDictionary::Map( const KeyAcceleratorCode& _acode, const char *s
// and ctrl held together, but PCSX2 traditionally mapped f8, shift-f8 and ctrl-shift-f8 // and ctrl held together, but PCSX2 traditionally mapped f8, shift-f8 and ctrl-shift-f8
// to Sys_TakeSnapshot, so let's not change it - we'll keep adding only shift and // to Sys_TakeSnapshot, so let's not change it - we'll keep adding only shift and
// ctrl-shift to the base shortcut. // ctrl-shift to the base shortcut.
if (acode.cmd || acode.shift) { if (acode.cmd || acode.shift)
{
Console.Error(L"Cannot map %s to Sys_TakeSnapshot - must not include Shift or Ctrl - these modifiers will be added automatically.", Console.Error(L"Cannot map %s to Sys_TakeSnapshot - must not include Shift or Ctrl - these modifiers will be added automatically.",
WX_STR(acode.ToString())); WX_STR(acode.ToString()));
} }
else { else
KeyAcceleratorCode shifted(acode); shifted.Shift(); {
KeyAcceleratorCode controlledShifted(shifted); controlledShifted.Cmd(); KeyAcceleratorCode shifted(acode);
shifted.Shift();
KeyAcceleratorCode controlledShifted(shifted);
controlledShifted.Cmd();
operator[](acode.val32) = result; operator[](acode.val32) = result;
operator[](shifted.val32) = result; operator[](shifted.val32) = result;
operator[](controlledShifted.val32) = result; operator[](controlledShifted.val32) = result;
if (_acode.val32 != acode.val32) { // overriding default if (_acode.val32 != acode.val32)
{ // overriding default
Console.WriteLn(Color_Green, L"Sys_TakeSnapshot: automatically mapping also %s and %s", Console.WriteLn(Color_Green, L"Sys_TakeSnapshot: automatically mapping also %s and %s",
WX_STR(shifted.ToString()), WX_STR(shifted.ToString()),
WX_STR(controlledShifted.ToString()) WX_STR(controlledShifted.ToString()));
);
} }
} }
} }
else { else
{
operator[](acode.val32) = result; operator[](acode.val32) = result;
} }
} }
@ -925,10 +975,11 @@ KeyAcceleratorCode AcceleratorDictionary::findKeycodeWithCommandId(const char* c
void Pcsx2App::BuildCommandHash() void Pcsx2App::BuildCommandHash()
{ {
if( !GlobalCommands ) GlobalCommands = std::unique_ptr<CommandDictionary>(new CommandDictionary); if (!GlobalCommands)
GlobalCommands = std::unique_ptr<CommandDictionary>(new CommandDictionary);
const GlobalCommandDescriptor* curcmd = CommandDeclarations; const GlobalCommandDescriptor* curcmd = CommandDeclarations;
while( curcmd->Invoke != NULL ) while (curcmd->Invoke != NULL)
{ {
(*GlobalCommands)[curcmd->Id] = curcmd; (*GlobalCommands)[curcmd->Id] = curcmd;
curcmd++; curcmd++;
@ -939,20 +990,21 @@ void Pcsx2App::InitDefaultGlobalAccelerators()
{ {
typedef KeyAcceleratorCode AAC; typedef KeyAcceleratorCode AAC;
if( !GlobalAccels ) GlobalAccels = std::unique_ptr<AcceleratorDictionary>(new AcceleratorDictionary); if (!GlobalAccels)
GlobalAccels = std::unique_ptr<AcceleratorDictionary>(new AcceleratorDictionary);
// Why do we even have those here? all of them seem to be overridden // Why do we even have those here? all of them seem to be overridden
// by GSPanel::m_Accels ( GSPanel::InitDefaultAccelerators() ) // by GSPanel::m_Accels ( GSPanel::InitDefaultAccelerators() )
// - One reason is because this is used to initialize shortcuts in the MainFrame's UI (see - MainFrame::AppendShortcutToMenuOption) // - One reason is because this is used to initialize shortcuts in the MainFrame's UI (see - MainFrame::AppendShortcutToMenuOption)
// this is before the GS Window has been initialized. // this is before the GS Window has been initialized.
GlobalAccels->Map( AAC( WXK_F1 ), "States_FreezeCurrentSlot" ); GlobalAccels->Map(AAC(WXK_F1), "States_FreezeCurrentSlot");
GlobalAccels->Map( AAC( WXK_F3 ), "States_DefrostCurrentSlot" ); GlobalAccels->Map(AAC(WXK_F3), "States_DefrostCurrentSlot");
GlobalAccels->Map( AAC( WXK_F2 ), "States_CycleSlotForward" ); GlobalAccels->Map(AAC(WXK_F2), "States_CycleSlotForward");
GlobalAccels->Map( AAC( WXK_F2 ).Shift(), "States_CycleSlotBackward" ); GlobalAccels->Map(AAC(WXK_F2).Shift(), "States_CycleSlotBackward");
GlobalAccels->Map( AAC( WXK_F4 ), "Framelimiter_MasterToggle"); GlobalAccels->Map(AAC(WXK_F4), "Framelimiter_MasterToggle");
GlobalAccels->Map( AAC( WXK_F4 ).Shift(), "Frameskip_Toggle"); GlobalAccels->Map(AAC(WXK_F4).Shift(), "Frameskip_Toggle");
/*GlobalAccels->Map( AAC( WXK_ESCAPE ), "Sys_Suspend"); /*GlobalAccels->Map( AAC( WXK_ESCAPE ), "Sys_Suspend");
GlobalAccels->Map( AAC( WXK_F8 ), "Sys_TakeSnapshot"); GlobalAccels->Map( AAC( WXK_F8 ), "Sys_TakeSnapshot");

View File

@ -31,7 +31,7 @@
#include "Saveslots.h" #include "Saveslots.h"
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
wxMenu* MainEmuFrame::MakeStatesSubMenu( int baseid, int loadBackupId ) const wxMenu* MainEmuFrame::MakeStatesSubMenu(int baseid, int loadBackupId) const
{ {
wxMenu* mnuSubstates = new wxMenu(); wxMenu* mnuSubstates = new wxMenu();
@ -46,10 +46,10 @@ wxMenu* MainEmuFrame::MakeStatesSubMenu( int baseid, int loadBackupId ) const
mnuSubstates->AppendSeparator(); mnuSubstates->AppendSeparator();
wxMenuItem* m = mnuSubstates->Append(loadBackupId, _("Backup")); wxMenuItem* m = mnuSubstates->Append(loadBackupId, _("Backup"));
m->Enable( false ); m->Enable(false);
} }
mnuSubstates->Append( baseid - 1, _("File...") ); mnuSubstates->Append(baseid - 1, _("File..."));
return mnuSubstates; return mnuSubstates;
} }
@ -61,7 +61,7 @@ void MainEmuFrame::UpdateStatusBar()
temp += "Fast Boot - "; temp += "Fast Boot - ";
if (g_Conf->CdvdSource == CDVD_SourceType::Iso) if (g_Conf->CdvdSource == CDVD_SourceType::Iso)
temp += "Load: '" + wxFileName(g_Conf->CurrentIso).GetFullName() +"' "; temp += "Load: '" + wxFileName(g_Conf->CurrentIso).GetFullName() + "' ";
m_statusbar.SetStatusText(temp, 0); m_statusbar.SetStatusText(temp, 0);
m_statusbar.SetStatusText(CDVD_SourceLabels[enum_cast(g_Conf->CdvdSource)], 1); m_statusbar.SetStatusText(CDVD_SourceLabels[enum_cast(g_Conf->CdvdSource)], 1);
@ -77,15 +77,21 @@ void MainEmuFrame::UpdateCdvdSrcSelection()
{ {
MenuIdentifiers cdsrc = MenuId_Src_Iso; MenuIdentifiers cdsrc = MenuId_Src_Iso;
switch( g_Conf->CdvdSource ) switch (g_Conf->CdvdSource)
{ {
case CDVD_SourceType::Iso: cdsrc = MenuId_Src_Iso; break; case CDVD_SourceType::Iso:
case CDVD_SourceType::Disc: cdsrc = MenuId_Src_Disc; break; cdsrc = MenuId_Src_Iso;
case CDVD_SourceType::NoDisc: cdsrc = MenuId_Src_NoDisc; break; break;
case CDVD_SourceType::Disc:
cdsrc = MenuId_Src_Disc;
break;
case CDVD_SourceType::NoDisc:
cdsrc = MenuId_Src_NoDisc;
break;
jNO_DEFAULT jNO_DEFAULT
} }
sMenuBar.Check( cdsrc, true ); sMenuBar.Check(cdsrc, true);
UpdateStatusBar(); UpdateStatusBar();
} }
@ -97,18 +103,19 @@ bool MainEmuFrame::Destroy()
for ( for (
wxWindowList::const_iterator wxWindowList::const_iterator
i = wxTopLevelWindows.begin(), i = wxTopLevelWindows.begin(),
end = wxTopLevelWindows.end(); end = wxTopLevelWindows.end();
i != end; ++i i != end; ++i)
)
{ {
wxTopLevelWindow * const win = wx_static_cast(wxTopLevelWindow *, *i); wxTopLevelWindow* const win = wx_static_cast(wxTopLevelWindow*, *i);
if (win == this) continue; if (win == this)
if (win->GetParent() != this) continue; continue;
if (win->GetParent() != this)
continue;
win->Destroy(); win->Destroy();
} }
return _parent::Destroy(); return _parent::Destroy();
} }
@ -122,13 +129,14 @@ bool MainEmuFrame::Destroy()
// //
void MainEmuFrame::OnCloseWindow(wxCloseEvent& evt) void MainEmuFrame::OnCloseWindow(wxCloseEvent& evt)
{ {
if( IsBeingDeleted() ) return; if (IsBeingDeleted())
return;
CoreThread.Suspend(); CoreThread.Suspend();
//bool isClosing = false; //bool isClosing = false;
if( !evt.CanVeto() ) if (!evt.CanVeto())
{ {
// Mandatory destruction... // Mandatory destruction...
//isClosing = true; //isClosing = true;
@ -142,28 +150,28 @@ void MainEmuFrame::OnCloseWindow(wxCloseEvent& evt)
// however. --air // however. --air
//evt.Veto( true ); //evt.Veto( true );
} }
sApp.OnMainFrameClosed( GetId() ); sApp.OnMainFrameClosed(GetId());
RemoveCdvdMenu(); RemoveCdvdMenu();
RemoveEventHandler( &wxGetApp().GetRecentIsoManager() ); RemoveEventHandler(&wxGetApp().GetRecentIsoManager());
wxGetApp().PostIdleAppMethod( &Pcsx2App::PrepForExit ); wxGetApp().PostIdleAppMethod(&Pcsx2App::PrepForExit);
evt.Skip(); evt.Skip();
} }
void MainEmuFrame::OnMoveAround( wxMoveEvent& evt ) void MainEmuFrame::OnMoveAround(wxMoveEvent& evt)
{ {
if( IsBeingDeleted() || !IsVisible() || IsIconized() ) return; if (IsBeingDeleted() || !IsVisible() || IsIconized())
return;
// Uncomment this when doing logger stress testing (and then move the window around // Uncomment this when doing logger stress testing (and then move the window around
// while the logger spams itself) // while the logger spams itself)
// ... makes for a good test of the message pump's responsiveness. // ... makes for a good test of the message pump's responsiveness.
if( EnableThreadedLoggingTest ) if (EnableThreadedLoggingTest)
Console.Warning( "Threaded Logging Test! (a window move event)" ); Console.Warning("Threaded Logging Test! (a window move event)");
// evt.GetPosition() returns the client area position, not the window frame position. // evt.GetPosition() returns the client area position, not the window frame position.
// So read the window's screen-relative position directly. // So read the window's screen-relative position directly.
@ -173,11 +181,12 @@ void MainEmuFrame::OnMoveAround( wxMoveEvent& evt )
// like selecting or deselecting a window, which muck up docking logic. We filter them // like selecting or deselecting a window, which muck up docking logic. We filter them
// out using 'lastpos' here. :) // out using 'lastpos' here. :)
static wxPoint lastpos( wxDefaultCoord, wxDefaultCoord ); static wxPoint lastpos(wxDefaultCoord, wxDefaultCoord);
if( lastpos == evt.GetPosition() ) return; if (lastpos == evt.GetPosition())
return;
lastpos = evt.GetPosition(); lastpos = evt.GetPosition();
if( g_Conf->ProgLogBox.AutoDock ) if (g_Conf->ProgLogBox.AutoDock)
{ {
if (ConsoleLogFrame* proglog = wxGetApp().GetProgramLog()) if (ConsoleLogFrame* proglog = wxGetApp().GetProgramLog())
{ {
@ -195,7 +204,7 @@ void MainEmuFrame::OnMoveAround( wxMoveEvent& evt )
void MainEmuFrame::OnLogBoxHidden() void MainEmuFrame::OnLogBoxHidden()
{ {
g_Conf->ProgLogBox.Visible = false; g_Conf->ProgLogBox.Visible = false;
m_MenuItem_Console.Check( false ); m_MenuItem_Console.Check(false);
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -285,45 +294,46 @@ void MainEmuFrame::ConnectMenus()
#endif #endif
} }
void MainEmuFrame::InitLogBoxPosition( AppConfig::ConsoleLogOptions& conf ) void MainEmuFrame::InitLogBoxPosition(AppConfig::ConsoleLogOptions& conf)
{ {
conf.DisplaySize.Set( conf.DisplaySize.Set(
std::min( std::max( conf.DisplaySize.GetWidth(), 160 ), wxGetDisplayArea().GetWidth() ), std::min(std::max(conf.DisplaySize.GetWidth(), 160), wxGetDisplayArea().GetWidth()),
std::min( std::max( conf.DisplaySize.GetHeight(), 160 ), wxGetDisplayArea().GetHeight() ) std::min(std::max(conf.DisplaySize.GetHeight(), 160), wxGetDisplayArea().GetHeight()));
);
if( conf.AutoDock ) if (conf.AutoDock)
{ {
conf.DisplayPosition = GetScreenPosition() + wxSize( GetSize().x, 0 ); conf.DisplayPosition = GetScreenPosition() + wxSize(GetSize().x, 0);
} }
else if( conf.DisplayPosition != wxDefaultPosition ) else if (conf.DisplayPosition != wxDefaultPosition)
{ {
if( !wxGetDisplayArea().Contains( wxRect( conf.DisplayPosition, conf.DisplaySize ) ) ) if (!wxGetDisplayArea().Contains(wxRect(conf.DisplayPosition, conf.DisplaySize)))
conf.DisplayPosition = wxDefaultPosition; conf.DisplayPosition = wxDefaultPosition;
} }
} }
void MainEmuFrame::DispatchEvent( const PluginEventType& plugin_evt ) void MainEmuFrame::DispatchEvent(const PluginEventType& plugin_evt)
{ {
if( !pxAssertMsg( GetMenuBar()!=NULL, "Mainframe menu bar is NULL!" ) ) return; if (!pxAssertMsg(GetMenuBar() != NULL, "Mainframe menu bar is NULL!"))
return;
//ApplyCoreStatus(); //ApplyCoreStatus();
if( plugin_evt == CorePlugins_Unloaded ) if (plugin_evt == CorePlugins_Unloaded)
{ {
for( int i=0; i<PluginId_Count; ++i ) for (int i = 0; i < PluginId_Count; ++i)
m_PluginMenuPacks[i].OnUnloaded(); m_PluginMenuPacks[i].OnUnloaded();
} }
else if( plugin_evt == CorePlugins_Loaded ) else if (plugin_evt == CorePlugins_Loaded)
{ {
for( int i=0; i<PluginId_Count; ++i ) for (int i = 0; i < PluginId_Count; ++i)
m_PluginMenuPacks[i].OnLoaded(); m_PluginMenuPacks[i].OnLoaded();
} }
} }
void MainEmuFrame::DispatchEvent( const CoreThreadStatus& status ) void MainEmuFrame::DispatchEvent(const CoreThreadStatus& status)
{ {
if( !pxAssertMsg( GetMenuBar()!=NULL, "Mainframe menu bar is NULL!" ) ) return; if (!pxAssertMsg(GetMenuBar() != NULL, "Mainframe menu bar is NULL!"))
return;
ApplyCoreStatus(); ApplyCoreStatus();
} }
@ -332,12 +342,12 @@ void MainEmuFrame::AppStatusEvent_OnSettingsApplied()
ApplySettings(); ApplySettings();
} }
int GetPluginMenuId_Settings( PluginsEnum_t pid ) int GetPluginMenuId_Settings(PluginsEnum_t pid)
{ {
return MenuId_PluginBase_Settings + ((int)pid * PluginMenuId_Interval); return MenuId_PluginBase_Settings + ((int)pid * PluginMenuId_Interval);
} }
static int GetPluginMenuId_Name( PluginsEnum_t pid ) static int GetPluginMenuId_Name(PluginsEnum_t pid)
{ {
return MenuId_PluginBase_Name + ((int)pid * PluginMenuId_Interval); return MenuId_PluginBase_Name + ((int)pid * PluginMenuId_Interval);
} }
@ -347,74 +357,73 @@ void MainEmuFrame::CreatePcsx2Menu()
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Some of the items in the System menu are configured by the UpdateCoreStatus() method. // Some of the items in the System menu are configured by the UpdateCoreStatus() method.
m_menuSys.Append(MenuId_Boot_CDVD, _("Initializing...")); m_menuSys.Append(MenuId_Boot_CDVD, _("Initializing..."));
m_menuSys.Append(MenuId_Sys_SuspendResume, _("Initializing...")); m_menuSys.Append(MenuId_Sys_SuspendResume, _("Initializing..."));
m_menuSys.Append(MenuId_Sys_Shutdown, _("Shut&down"), m_menuSys.Append(MenuId_Sys_Shutdown, _("Shut&down"),
_("Wipes all internal VM states and shuts down plugins.")); _("Wipes all internal VM states and shuts down plugins."));
m_menuSys.FindItem(MenuId_Sys_Shutdown)->Enable(false); m_menuSys.FindItem(MenuId_Sys_Shutdown)->Enable(false);
m_menuSys.Append(MenuId_Boot_ELF, _("&Run ELF..."), m_menuSys.Append(MenuId_Boot_ELF, _("&Run ELF..."),
_("For running raw PS2 binaries directly")); _("For running raw PS2 binaries directly"));
m_menuSys.AppendSeparator(); m_menuSys.AppendSeparator();
m_menuSys.Append( MenuId_Config_FastBoot,_("Fast Boot"), m_menuSys.Append(MenuId_Config_FastBoot, _("Fast Boot"),
_("Skips PS2 splash screens when booting from ISO or DVD media"), wxITEM_CHECK ); _("Skips PS2 splash screens when booting from ISO or DVD media"), wxITEM_CHECK);
m_menuSys.AppendCheckItem(MenuId_Debug_CreateBlockdump, _("Create &Blockdump"), _("Creates a block dump for debugging purposes.")); m_menuSys.AppendCheckItem(MenuId_Debug_CreateBlockdump, _("Create &Blockdump"), _("Creates a block dump for debugging purposes."));
m_menuSys.Append(MenuId_GameSettingsSubMenu, _("&Game Settings"), &m_GameSettingsSubmenu); m_menuSys.Append(MenuId_GameSettingsSubMenu, _("&Game Settings"), &m_GameSettingsSubmenu);
m_GameSettingsSubmenu.Append(MenuId_EnablePatches, _("Automatic &Gamefixes"), m_GameSettingsSubmenu.Append(MenuId_EnablePatches, _("Automatic &Gamefixes"),
_("Automatically applies needed Gamefixes to known problematic games"), wxITEM_CHECK); _("Automatically applies needed Gamefixes to known problematic games"), wxITEM_CHECK);
m_GameSettingsSubmenu.Append(MenuId_EnableCheats, _("Enable &Cheats"), m_GameSettingsSubmenu.Append(MenuId_EnableCheats, _("Enable &Cheats"),
wxEmptyString, wxITEM_CHECK); wxEmptyString, wxITEM_CHECK);
m_GameSettingsSubmenu.Append(MenuId_EnableIPC, _("Enable &IPC"), m_GameSettingsSubmenu.Append(MenuId_EnableIPC, _("Enable &IPC"),
wxEmptyString, wxITEM_CHECK); wxEmptyString, wxITEM_CHECK);
m_GameSettingsSubmenu.Append(MenuId_EnableWideScreenPatches, _("Enable &Widescreen Patches"), m_GameSettingsSubmenu.Append(MenuId_EnableWideScreenPatches, _("Enable &Widescreen Patches"),
_("Enabling Widescreen Patches may occasionally cause issues."), wxITEM_CHECK); _("Enabling Widescreen Patches may occasionally cause issues."), wxITEM_CHECK);
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
m_GameSettingsSubmenu.Append(MenuId_EnableInputRecording, _("Enable &Input Recording"), m_GameSettingsSubmenu.Append(MenuId_EnableInputRecording, _("Enable &Input Recording"),
wxEmptyString, wxITEM_CHECK); wxEmptyString, wxITEM_CHECK);
#endif #endif
if(IsDebugBuild || IsDevBuild) if (IsDebugBuild || IsDevBuild)
m_GameSettingsSubmenu.Append(MenuId_EnableHostFs, _("Enable &Host Filesystem"), m_GameSettingsSubmenu.Append(MenuId_EnableHostFs, _("Enable &Host Filesystem"),
wxEmptyString, wxITEM_CHECK); wxEmptyString, wxITEM_CHECK);
m_menuSys.AppendSeparator(); m_menuSys.AppendSeparator();
m_menuSys.Append(MenuId_Sys_LoadStates, _("&Load state"), &m_LoadStatesSubmenu); m_menuSys.Append(MenuId_Sys_LoadStates, _("&Load state"), &m_LoadStatesSubmenu);
m_menuSys.Append(MenuId_Sys_SaveStates, _("&Save state"), &m_SaveStatesSubmenu); m_menuSys.Append(MenuId_Sys_SaveStates, _("&Save state"), &m_SaveStatesSubmenu);
m_menuSys.Append(MenuId_EnableBackupStates, _("&Backup before save"), wxEmptyString, wxITEM_CHECK); m_menuSys.Append(MenuId_EnableBackupStates, _("&Backup before save"), wxEmptyString, wxITEM_CHECK);
m_menuSys.AppendSeparator(); m_menuSys.AppendSeparator();
m_menuSys.Append(MenuId_Exit, _("E&xit"), m_menuSys.Append(MenuId_Exit, _("E&xit"),
AddAppName(_("Closing %s may be hazardous to your health"))); AddAppName(_("Closing %s may be hazardous to your health")));
} }
void MainEmuFrame::CreateCdvdMenu() void MainEmuFrame::CreateCdvdMenu()
{ {
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
wxMenu& isoRecents( wxGetApp().GetRecentIsoMenu() ); wxMenu& isoRecents(wxGetApp().GetRecentIsoMenu());
wxMenu& driveList ( wxGetApp().GetDriveListMenu() ); wxMenu& driveList(wxGetApp().GetDriveListMenu());
m_menuItem_RecentIsoMenu = m_menuCDVD.AppendSubMenu(&isoRecents, _("ISO &Selector")); m_menuItem_RecentIsoMenu = m_menuCDVD.AppendSubMenu(&isoRecents, _("ISO &Selector"));
m_menuItem_DriveListMenu = m_menuCDVD.AppendSubMenu(&driveList, _("D&rive Selector")); m_menuItem_DriveListMenu = m_menuCDVD.AppendSubMenu(&driveList, _("D&rive Selector"));
m_menuCDVD.AppendSeparator(); m_menuCDVD.AppendSeparator();
m_menuCDVD.Append( MenuId_Src_Iso, _("&ISO"), _("Makes the specified ISO image the CDVD source."), wxITEM_RADIO ); m_menuCDVD.Append(MenuId_Src_Iso, _("&ISO"), _("Makes the specified ISO image the CDVD source."), wxITEM_RADIO);
m_menuCDVD.Append( MenuId_Src_Disc, _("&Disc"), _("Uses a disc drive as the CDVD source."), wxITEM_RADIO ); m_menuCDVD.Append(MenuId_Src_Disc, _("&Disc"), _("Uses a disc drive as the CDVD source."), wxITEM_RADIO);
m_menuCDVD.Append( MenuId_Src_NoDisc, _("&No disc"), _("Use this to boot into your virtual PS2's BIOS configuration."), wxITEM_RADIO ); m_menuCDVD.Append(MenuId_Src_NoDisc, _("&No disc"), _("Use this to boot into your virtual PS2's BIOS configuration."), wxITEM_RADIO);
#if defined(__FREEBSD__) || defined(__APPLE__) #if defined(__FREEBSD__) || defined(__APPLE__)
m_menuItem_DriveListMenu->Enable(false); m_menuItem_DriveListMenu->Enable(false);
@ -425,37 +434,37 @@ void MainEmuFrame::CreateCdvdMenu()
void MainEmuFrame::CreateConfigMenu() void MainEmuFrame::CreateConfigMenu()
{ {
m_menuConfig.Append(MenuId_Config_SysSettings, _("Emulation &Settings...") ); m_menuConfig.Append(MenuId_Config_SysSettings, _("Emulation &Settings..."));
m_menuConfig.Append(MenuId_Config_McdSettings, _("&Memory Cards...") ); m_menuConfig.Append(MenuId_Config_McdSettings, _("&Memory Cards..."));
m_menuConfig.Append(MenuId_Config_BIOS, _("&Plugin/BIOS Selector...") ); m_menuConfig.Append(MenuId_Config_BIOS, _("&Plugin/BIOS Selector..."));
m_menuConfig.Append(MenuId_Config_SPU2, _("&Audio Settings...") ); m_menuConfig.Append(MenuId_Config_SPU2, _("&Audio Settings..."));
m_menuConfig.AppendSeparator(); m_menuConfig.AppendSeparator();
m_menuConfig.Append(MenuId_Config_GS, _("&Video (GS)"), m_PluginMenuPacks[PluginId_GS]); m_menuConfig.Append(MenuId_Config_GS, _("&Video (GS)"), m_PluginMenuPacks[PluginId_GS]);
m_menuConfig.Append(MenuId_Config_PAD, _("&Controllers (PAD)"),m_PluginMenuPacks[PluginId_PAD]); m_menuConfig.Append(MenuId_Config_PAD, _("&Controllers (PAD)"), m_PluginMenuPacks[PluginId_PAD]);
m_menuConfig.Append(MenuId_Config_DEV9, _("&Dev9"), m_PluginMenuPacks[PluginId_DEV9]); m_menuConfig.Append(MenuId_Config_DEV9, _("&Dev9"), m_PluginMenuPacks[PluginId_DEV9]);
m_menuConfig.Append(MenuId_Config_USB, _("&USB"), m_PluginMenuPacks[PluginId_USB]); m_menuConfig.Append(MenuId_Config_USB, _("&USB"), m_PluginMenuPacks[PluginId_USB]);
m_menuConfig.AppendSeparator(); m_menuConfig.AppendSeparator();
m_menuConfig.Append(MenuId_Config_Multitap0Toggle, _("Multitap &1"), wxEmptyString, wxITEM_CHECK ); m_menuConfig.Append(MenuId_Config_Multitap0Toggle, _("Multitap &1"), wxEmptyString, wxITEM_CHECK);
m_menuConfig.Append(MenuId_Config_Multitap1Toggle, _("Multitap &2"), wxEmptyString, wxITEM_CHECK ); m_menuConfig.Append(MenuId_Config_Multitap1Toggle, _("Multitap &2"), wxEmptyString, wxITEM_CHECK);
m_menuConfig.AppendSeparator(); m_menuConfig.AppendSeparator();
m_menuConfig.Append(MenuId_ChangeLang, L"Change &Language..." ); // Always in English m_menuConfig.Append(MenuId_ChangeLang, L"Change &Language..."); // Always in English
m_menuConfig.Append(MenuId_Config_ResetAll, _("C&lear All Settings..."), m_menuConfig.Append(MenuId_Config_ResetAll, _("C&lear All Settings..."),
AddAppName(_("Clears all %s settings and re-runs the startup wizard."))); AddAppName(_("Clears all %s settings and re-runs the startup wizard.")));
} }
void MainEmuFrame::CreateWindowsMenu() void MainEmuFrame::CreateWindowsMenu()
{ {
m_menuWindow.Append(MenuId_Debug_Open, _("&Show Debug"), wxEmptyString, wxITEM_CHECK ); m_menuWindow.Append(MenuId_Debug_Open, _("&Show Debug"), wxEmptyString, wxITEM_CHECK);
m_menuWindow.Append( &m_MenuItem_Console ); m_menuWindow.Append(&m_MenuItem_Console);
#if defined(__unix__) #if defined(__unix__)
m_menuWindow.AppendSeparator(); m_menuWindow.AppendSeparator();
m_menuWindow.Append( &m_MenuItem_Console_Stdio ); m_menuWindow.Append(&m_MenuItem_Console_Stdio);
#endif #endif
} }
@ -486,64 +495,64 @@ void MainEmuFrame::CreateRecordMenu()
void MainEmuFrame::CreateHelpMenu() void MainEmuFrame::CreateHelpMenu()
{ {
m_menuHelp.Append(MenuId_Help_GetStarted, _("&Getting Started")); m_menuHelp.Append(MenuId_Help_GetStarted, _("&Getting Started"));
m_menuHelp.Append(MenuId_Help_Compatibility, _("&Compatibility")); m_menuHelp.Append(MenuId_Help_Compatibility, _("&Compatibility"));
m_menuHelp.AppendSeparator(); m_menuHelp.AppendSeparator();
m_menuHelp.Append(MenuId_Help_Website, _("&Website")); m_menuHelp.Append(MenuId_Help_Website, _("&Website"));
m_menuHelp.Append(MenuId_Help_Wiki, _("&Wiki")); m_menuHelp.Append(MenuId_Help_Wiki, _("&Wiki"));
m_menuHelp.Append(MenuId_Help_Forums, _("&Support Forums")); m_menuHelp.Append(MenuId_Help_Forums, _("&Support Forums"));
m_menuHelp.Append(MenuId_Help_Github, _("&Github Repository")); m_menuHelp.Append(MenuId_Help_Github, _("&Github Repository"));
m_menuHelp.AppendSeparator(); m_menuHelp.AppendSeparator();
m_menuHelp.Append(MenuId_About, _("&About...")); m_menuHelp.Append(MenuId_About, _("&About..."));
} }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title) MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
: wxFrame(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER) ) : wxFrame(parent, wxID_ANY, title, wxDefaultPosition, wxDefaultSize, wxDEFAULT_FRAME_STYLE & ~(wxMAXIMIZE_BOX | wxRESIZE_BORDER))
, m_statusbar( *CreateStatusBar(2, 0) ) , m_statusbar(*CreateStatusBar(2, 0))
, m_background( new wxStaticBitmap(this, wxID_ANY, wxGetApp().GetLogoBitmap()) ) , m_background(new wxStaticBitmap(this, wxID_ANY, wxGetApp().GetLogoBitmap()))
// All menu components must be created on the heap! // All menu components must be created on the heap!
, m_menubar( *new wxMenuBar() ) , m_menubar(*new wxMenuBar())
, m_menuCDVD ( *new wxMenu() ) , m_menuCDVD(*new wxMenu())
, m_menuSys ( *new wxMenu() ) , m_menuSys(*new wxMenu())
, m_menuConfig ( *new wxMenu() ) , m_menuConfig(*new wxMenu())
, m_menuWindow ( *new wxMenu() ) , m_menuWindow(*new wxMenu())
, m_menuCapture ( *new wxMenu() ) , m_menuCapture(*new wxMenu())
, m_submenuVideoCapture ( *new wxMenu() ) , m_submenuVideoCapture(*new wxMenu())
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
, m_menuRecording(*new wxMenu()) , m_menuRecording(*new wxMenu())
#endif #endif
, m_menuHelp(*new wxMenu()) , m_menuHelp(*new wxMenu())
, m_LoadStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Load01, MenuId_State_LoadBackup ) ) , m_LoadStatesSubmenu(*MakeStatesSubMenu(MenuId_State_Load01, MenuId_State_LoadBackup))
, m_SaveStatesSubmenu( *MakeStatesSubMenu( MenuId_State_Save01 ) ) , m_SaveStatesSubmenu(*MakeStatesSubMenu(MenuId_State_Save01))
, m_GameSettingsSubmenu( *new wxMenu() ) , m_GameSettingsSubmenu(*new wxMenu())
, m_MenuItem_Console( *new wxMenuItem( &m_menuWindow, MenuId_Console, _("&Show Console"), wxEmptyString, wxITEM_CHECK ) ) , m_MenuItem_Console(*new wxMenuItem(&m_menuWindow, MenuId_Console, _("&Show Console"), wxEmptyString, wxITEM_CHECK))
#if defined(__unix__) #if defined(__unix__)
, m_MenuItem_Console_Stdio( *new wxMenuItem( &m_menuWindow, MenuId_Console_Stdio, _("&Console to Stdio"), wxEmptyString, wxITEM_CHECK ) ) , m_MenuItem_Console_Stdio(*new wxMenuItem(&m_menuWindow, MenuId_Console_Stdio, _("&Console to Stdio"), wxEmptyString, wxITEM_CHECK))
#endif #endif
{ {
m_RestartEmuOnDelete = false; m_RestartEmuOnDelete = false;
for( int i=0; i<PluginId_Count; ++i ) for (int i = 0; i < PluginId_Count; ++i)
m_PluginMenuPacks[i].Populate( (PluginsEnum_t)i ); m_PluginMenuPacks[i].Populate((PluginsEnum_t)i);
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// Initial menubar setup. This needs to be done first so that the menu bar's visible size // Initial menubar setup. This needs to be done first so that the menu bar's visible size
// can be factored into the window size (which ends up being background+status+menus) // can be factored into the window size (which ends up being background+status+menus)
m_menubar.Append( &m_menuSys, _("&PCSX2") ); m_menubar.Append(&m_menuSys, _("&PCSX2"));
m_menubar.Append( &m_menuCDVD, _("CD&VD") ); m_menubar.Append(&m_menuCDVD, _("CD&VD"));
m_menubar.Append( &m_menuConfig, _("&Config") ); m_menubar.Append(&m_menuConfig, _("&Config"));
m_menubar.Append( &m_menuWindow, _("&Window") ); m_menubar.Append(&m_menuWindow, _("&Window"));
m_menubar.Append( &m_menuCapture, _("&Capture") ); m_menubar.Append(&m_menuCapture, _("&Capture"));
SetMenuBar( &m_menubar ); SetMenuBar(&m_menubar);
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
// Append the Recording options if previously enabled and setting has been picked up from ini // Append the Recording options if previously enabled and setting has been picked up from ini
@ -552,7 +561,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
m_menubar.Append(&m_menuRecording, _("&Input Record")); m_menubar.Append(&m_menuRecording, _("&Input Record"));
} }
#endif #endif
m_menubar.Append( &m_menuHelp, _("&Help") ); m_menubar.Append(&m_menuHelp, _("&Help"));
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
@ -561,37 +570,40 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
wxSize backsize(m_background->GetBitmap().GetWidth(), m_background->GetBitmap().GetHeight()); wxSize backsize(m_background->GetBitmap().GetWidth(), m_background->GetBitmap().GetHeight());
wxString wintitle; wxString wintitle;
if( PCSX2_isReleaseVersion ) if (PCSX2_isReleaseVersion)
{ {
// stable releases, with a simple title. // stable releases, with a simple title.
wintitle.Printf( L"%s %d.%d.%d", pxGetAppName().c_str(), PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo ); wintitle.Printf(L"%s %d.%d.%d", pxGetAppName().c_str(), PCSX2_VersionHi, PCSX2_VersionMid, PCSX2_VersionLo);
} }
else else
{ {
// beta / development editions, which feature revision number and compile date. // beta / development editions, which feature revision number and compile date.
if (strlen(GIT_REV) > 5) { if (strlen(GIT_REV) > 5)
wintitle.Printf( L"%s %s", pxGetAppName().c_str(), GIT_REV); {
} else { wintitle.Printf(L"%s %s", pxGetAppName().c_str(), GIT_REV);
wintitle.Printf( L"%s %d.%d.%d-%lld%s (git)", pxGetAppName().c_str(), PCSX2_VersionHi, PCSX2_VersionMid, }
PCSX2_VersionLo, SVN_REV, SVN_MODS ? L"m" : wxEmptyString ); else
{
wintitle.Printf(L"%s %d.%d.%d-%lld%s (git)", pxGetAppName().c_str(), PCSX2_VersionHi, PCSX2_VersionMid,
PCSX2_VersionLo, SVN_REV, SVN_MODS ? L"m" : wxEmptyString);
} }
} }
SetTitle( wintitle ); SetTitle(wintitle);
// Ideally the __WXMSW__ port should use the embedded IDI_ICON2 icon, because wxWidgets sucks and // Ideally the __WXMSW__ port should use the embedded IDI_ICON2 icon, because wxWidgets sucks and
// loses the transparency information when loading bitmaps into icons. But for some reason // loses the transparency information when loading bitmaps into icons. But for some reason
// I cannot get it to work despite following various examples to the letter. // I cannot get it to work despite following various examples to the letter.
SetIcons( wxGetApp().GetIconBundle() ); SetIcons(wxGetApp().GetIconBundle());
int m_statusbar_widths[] = { (int)-20, (int)-3, (int) -2 }; int m_statusbar_widths[] = {(int)-20, (int)-3, (int)-2};
m_statusbar.SetFieldsCount(3); m_statusbar.SetFieldsCount(3);
m_statusbar.SetStatusWidths(3, m_statusbar_widths); m_statusbar.SetStatusWidths(3, m_statusbar_widths);
m_statusbar.SetStatusText( wxEmptyString, 0); m_statusbar.SetStatusText(wxEmptyString, 0);
wxBoxSizer& joe( *new wxBoxSizer( wxVERTICAL ) ); wxBoxSizer& joe(*new wxBoxSizer(wxVERTICAL));
joe.Add( m_background ); joe.Add(m_background);
SetSizerAndFit( &joe ); SetSizerAndFit(&joe);
// Makes no sense, but this is needed for the window size to be correct for // Makes no sense, but this is needed for the window size to be correct for
// 200% DPI on Windows. The SetSizerAndFit is supposed to be doing the exact // 200% DPI on Windows. The SetSizerAndFit is supposed to be doing the exact
@ -599,16 +611,16 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
GetSizer()->SetSizeHints(this); GetSizer()->SetSizeHints(this);
// Use default window position if the configured windowpos is invalid (partially offscreen) // Use default window position if the configured windowpos is invalid (partially offscreen)
if( g_Conf->MainGuiPosition == wxDefaultPosition || !pxIsValidWindowPosition( *this, g_Conf->MainGuiPosition) ) if (g_Conf->MainGuiPosition == wxDefaultPosition || !pxIsValidWindowPosition(*this, g_Conf->MainGuiPosition))
g_Conf->MainGuiPosition = GetScreenPosition(); g_Conf->MainGuiPosition = GetScreenPosition();
else else
SetPosition( g_Conf->MainGuiPosition ); SetPosition(g_Conf->MainGuiPosition);
// Updating console log positions after the main window has been fitted to its sizer ensures // Updating console log positions after the main window has been fitted to its sizer ensures
// proper docked positioning, since the main window's size is invalid until after the sizer // proper docked positioning, since the main window's size is invalid until after the sizer
// has been set/fit. // has been set/fit.
InitLogBoxPosition( g_Conf->ProgLogBox ); InitLogBoxPosition(g_Conf->ProgLogBox);
CreatePcsx2Menu(); CreatePcsx2Menu();
CreateCdvdMenu(); CreateCdvdMenu();
CreateConfigMenu(); CreateConfigMenu();
@ -619,7 +631,7 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
#endif #endif
CreateHelpMenu(); CreateHelpMenu();
m_MenuItem_Console.Check( g_Conf->ProgLogBox.Visible ); m_MenuItem_Console.Check(g_Conf->ProgLogBox.Visible);
ConnectMenus(); ConnectMenus();
Bind(wxEVT_MOVE, &MainEmuFrame::OnMoveAround, this); Bind(wxEVT_MOVE, &MainEmuFrame::OnMoveAround, this);
@ -627,8 +639,8 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
Bind(wxEVT_SET_FOCUS, &MainEmuFrame::OnFocus, this); Bind(wxEVT_SET_FOCUS, &MainEmuFrame::OnFocus, this);
Bind(wxEVT_ACTIVATE, &MainEmuFrame::OnActivate, this); Bind(wxEVT_ACTIVATE, &MainEmuFrame::OnActivate, this);
PushEventHandler( &wxGetApp().GetRecentIsoManager() ); PushEventHandler(&wxGetApp().GetRecentIsoManager());
SetDropTarget( new IsoDropTarget( this ) ); SetDropTarget(new IsoDropTarget(this));
ApplyCoreStatus(); ApplyCoreStatus();
ApplySettings(); ApplySettings();
@ -637,11 +649,12 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
MainEmuFrame::~MainEmuFrame() MainEmuFrame::~MainEmuFrame()
{ {
try { try
if( m_RestartEmuOnDelete ) {
if (m_RestartEmuOnDelete)
{ {
sApp.SetExitOnFrameDelete( false ); sApp.SetExitOnFrameDelete(false);
sApp.PostAppMethod( &Pcsx2App::DetectCpuAndUserMode ); sApp.PostAppMethod(&Pcsx2App::DetectCpuAndUserMode);
sApp.WipeUserModeSettings(); sApp.WipeUserModeSettings();
} }
} }
@ -662,18 +675,18 @@ void MainEmuFrame::DoGiveHelp(const wxString& text, bool show)
// not propagate up the window hierarchy, and on Activate events don't always get sent // not propagate up the window hierarchy, and on Activate events don't always get sent
// on the first focusing event after PCSX2 starts. // on the first focusing event after PCSX2 starts.
void MainEmuFrame::OnFocus( wxFocusEvent& evt ) void MainEmuFrame::OnFocus(wxFocusEvent& evt)
{ {
if( ConsoleLogFrame* logframe = wxGetApp().GetProgramLog() ) if (ConsoleLogFrame* logframe = wxGetApp().GetProgramLog())
MSW_SetWindowAfter( logframe->GetHandle(), GetHandle() ); MSW_SetWindowAfter(logframe->GetHandle(), GetHandle());
evt.Skip(); evt.Skip();
} }
void MainEmuFrame::OnActivate( wxActivateEvent& evt ) void MainEmuFrame::OnActivate(wxActivateEvent& evt)
{ {
if( ConsoleLogFrame* logframe = wxGetApp().GetProgramLog() ) if (ConsoleLogFrame* logframe = wxGetApp().GetProgramLog())
MSW_SetWindowAfter( logframe->GetHandle(), GetHandle() ); MSW_SetWindowAfter(logframe->GetHandle(), GetHandle());
evt.Skip(); evt.Skip();
} }
@ -681,14 +694,14 @@ void MainEmuFrame::OnActivate( wxActivateEvent& evt )
void MainEmuFrame::ApplyCoreStatus() void MainEmuFrame::ApplyCoreStatus()
{ {
wxMenuBar& menubar( *GetMenuBar() ); wxMenuBar& menubar(*GetMenuBar());
// [TODO] : Ideally each of these items would bind a listener instance to the AppCoreThread // [TODO] : Ideally each of these items would bind a listener instance to the AppCoreThread
// dispatcher, and modify their states accordingly. This is just a hack (for now) -- air // dispatcher, and modify their states accordingly. This is just a hack (for now) -- air
if (wxMenuItem* susres = menubar.FindItem(MenuId_Sys_SuspendResume)) if (wxMenuItem* susres = menubar.FindItem(MenuId_Sys_SuspendResume))
{ {
if( !CoreThread.IsClosing() ) if (!CoreThread.IsClosing())
{ {
susres->Enable(); susres->Enable();
susres->SetItemLabel(_("Paus&e")); susres->SetItemLabel(_("Paus&e"));
@ -698,7 +711,7 @@ void MainEmuFrame::ApplyCoreStatus()
{ {
bool ActiveVM = SysHasValidState(); bool ActiveVM = SysHasValidState();
susres->Enable(ActiveVM); susres->Enable(ActiveVM);
if( ActiveVM ) if (ActiveVM)
{ {
susres->SetItemLabel(_("R&esume")); susres->SetItemLabel(_("R&esume"));
susres->SetHelp(_("Resumes the suspended emulation state.")); susres->SetHelp(_("Resumes the suspended emulation state."));
@ -713,25 +726,25 @@ void MainEmuFrame::ApplyCoreStatus()
const CDVD_SourceType Source = g_Conf->CdvdSource; const CDVD_SourceType Source = g_Conf->CdvdSource;
wxMenuItem *cdvd_menu = menubar.FindItem(MenuId_Boot_CDVD); wxMenuItem* cdvd_menu = menubar.FindItem(MenuId_Boot_CDVD);
wxString label; wxString label;
wxString help_text = _("Use fast boot to skip PS2 startup and splash screens"); wxString help_text = _("Use fast boot to skip PS2 startup and splash screens");
switch (Source) switch (Source)
{ {
case CDVD_SourceType::Iso: case CDVD_SourceType::Iso:
label = _("Boot ISO"); label = _("Boot ISO");
break; break;
case CDVD_SourceType::Disc: case CDVD_SourceType::Disc:
label = _("Boot CDVD"); label = _("Boot CDVD");
break; break;
case CDVD_SourceType::NoDisc: case CDVD_SourceType::NoDisc:
label = _("Boot Bios"); label = _("Boot Bios");
break; break;
default: default:
label = _("Boot Bios"); label = _("Boot Bios");
break; break;
} }
cdvd_menu->SetItemLabel(label); cdvd_menu->SetItemLabel(label);
@ -748,52 +761,54 @@ void MainEmuFrame::ApplySettings()
//currently only EnablePatches is affected when the settings come from a preset. //currently only EnablePatches is affected when the settings come from a preset.
void MainEmuFrame::ApplyConfigToGui(AppConfig& configToApply, int flags) void MainEmuFrame::ApplyConfigToGui(AppConfig& configToApply, int flags)
{ {
wxMenuBar& menubar( *GetMenuBar() ); wxMenuBar& menubar(*GetMenuBar());
menubar.Check( MenuId_EnablePatches, configToApply.EmuOptions.EnablePatches ); menubar.Check(MenuId_EnablePatches, configToApply.EmuOptions.EnablePatches);
menubar.Enable( MenuId_EnablePatches, !configToApply.EnablePresets ); menubar.Enable(MenuId_EnablePatches, !configToApply.EnablePresets);
if ( !(flags & AppConfig::APPLY_FLAG_FROM_PRESET) ) if (!(flags & AppConfig::APPLY_FLAG_FROM_PRESET))
{//these should not be affected by presets { //these should not be affected by presets
menubar.Check( MenuId_EnableBackupStates, configToApply.EmuOptions.BackupSavestate ); menubar.Check(MenuId_EnableBackupStates, configToApply.EmuOptions.BackupSavestate);
menubar.Check( MenuId_EnableCheats, configToApply.EmuOptions.EnableCheats ); menubar.Check(MenuId_EnableCheats, configToApply.EmuOptions.EnableCheats);
menubar.Check( MenuId_EnableIPC, configToApply.EmuOptions.EnableIPC ); menubar.Check(MenuId_EnableIPC, configToApply.EmuOptions.EnableIPC);
menubar.Check( MenuId_EnableWideScreenPatches, configToApply.EmuOptions.EnableWideScreenPatches ); menubar.Check(MenuId_EnableWideScreenPatches, configToApply.EmuOptions.EnableWideScreenPatches);
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
menubar.Check( MenuId_EnableInputRecording, configToApply.EmuOptions.EnableRecordingTools); menubar.Check(MenuId_EnableInputRecording, configToApply.EmuOptions.EnableRecordingTools);
#endif #endif
menubar.Check( MenuId_EnableHostFs, configToApply.EmuOptions.HostFs ); menubar.Check(MenuId_EnableHostFs, configToApply.EmuOptions.HostFs);
menubar.Check( MenuId_Debug_CreateBlockdump, configToApply.EmuOptions.CdvdDumpBlocks ); menubar.Check(MenuId_Debug_CreateBlockdump, configToApply.EmuOptions.CdvdDumpBlocks);
#if defined(__unix__) #if defined(__unix__)
menubar.Check( MenuId_Console_Stdio, configToApply.EmuOptions.ConsoleToStdio ); menubar.Check(MenuId_Console_Stdio, configToApply.EmuOptions.ConsoleToStdio);
#endif #endif
menubar.Check( MenuId_Config_Multitap0Toggle, configToApply.EmuOptions.MultitapPort0_Enabled ); menubar.Check(MenuId_Config_Multitap0Toggle, configToApply.EmuOptions.MultitapPort0_Enabled);
menubar.Check( MenuId_Config_Multitap1Toggle, configToApply.EmuOptions.MultitapPort1_Enabled ); menubar.Check(MenuId_Config_Multitap1Toggle, configToApply.EmuOptions.MultitapPort1_Enabled);
menubar.Check( MenuId_Config_FastBoot, configToApply.EnableFastBoot ); menubar.Check(MenuId_Config_FastBoot, configToApply.EnableFastBoot);
} }
UpdateCdvdSrcSelection(); //shouldn't be affected by presets but updates from g_Conf anyway and not from configToApply, so no problem here. UpdateCdvdSrcSelection(); //shouldn't be affected by presets but updates from g_Conf anyway and not from configToApply, so no problem here.
} }
//write pending preset settings from the gui to g_Conf, //write pending preset settings from the gui to g_Conf,
// without triggering an overall "settingsApplied" event. // without triggering an overall "settingsApplied" event.
void MainEmuFrame::CommitPreset_noTrigger() void MainEmuFrame::CommitPreset_noTrigger()
{ {
wxMenuBar& menubar( *GetMenuBar() ); wxMenuBar& menubar(*GetMenuBar());
g_Conf->EmuOptions.EnablePatches = menubar.IsChecked( MenuId_EnablePatches ); g_Conf->EmuOptions.EnablePatches = menubar.IsChecked(MenuId_EnablePatches);
} }
static void AppendShortcutToMenuOption( wxMenuItem& item, wxString keyCodeStr ) { static void AppendShortcutToMenuOption(wxMenuItem& item, wxString keyCodeStr)
{
wxString text = item.GetItemLabel(); wxString text = item.GetItemLabel();
const size_t tabPos = text.rfind(L'\t'); const size_t tabPos = text.rfind(L'\t');
item.SetItemLabel(text.Mid(0, tabPos ) + L"\t" + keyCodeStr); item.SetItemLabel(text.Mid(0, tabPos) + L"\t" + keyCodeStr);
} }
void MainEmuFrame::AppendKeycodeNamesToMenuOptions() { void MainEmuFrame::AppendKeycodeNamesToMenuOptions()
{
AppendShortcutToMenuOption(*m_menuSys.FindChildItem( MenuId_Sys_LoadStates ), wxGetApp().GlobalAccels->findKeycodeWithCommandId("States_DefrostCurrentSlot").toTitleizedString());
AppendShortcutToMenuOption(*m_menuSys.FindChildItem( MenuId_Sys_SaveStates ), wxGetApp().GlobalAccels->findKeycodeWithCommandId("States_FreezeCurrentSlot").toTitleizedString()); AppendShortcutToMenuOption(*m_menuSys.FindChildItem(MenuId_Sys_LoadStates), wxGetApp().GlobalAccels->findKeycodeWithCommandId("States_DefrostCurrentSlot").toTitleizedString());
AppendShortcutToMenuOption(*m_menuSys.FindChildItem(MenuId_Sys_SaveStates), wxGetApp().GlobalAccels->findKeycodeWithCommandId("States_FreezeCurrentSlot").toTitleizedString());
} }
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
@ -817,31 +832,31 @@ void MainEmuFrame::enableRecordingMenuItem(MenuIdentifiers menuId, bool enable)
// "Extensible" Plugin Menus // "Extensible" Plugin Menus
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
void PerPluginMenuInfo::Populate( PluginsEnum_t pid ) void PerPluginMenuInfo::Populate(PluginsEnum_t pid)
{ {
if( !pxAssert(pid < PluginId_Count) ) return; if (!pxAssert(pid < PluginId_Count))
return;
PluginId = pid; PluginId = pid;
MyMenu.Append( GetPluginMenuId_Name(PluginId), _("No plugin loaded") )->Enable( false ); MyMenu.Append(GetPluginMenuId_Name(PluginId), _("No plugin loaded"))->Enable(false);
MyMenu.AppendSeparator(); MyMenu.AppendSeparator();
if( PluginId == PluginId_GS ) if (PluginId == PluginId_GS)
{ {
MyMenu.Append( MenuId_Video_CoreSettings, _("&Core GS Settings..."), MyMenu.Append(MenuId_Video_CoreSettings, _("&Core GS Settings..."),
_("Modify hardware emulation settings regulated by the PCSX2 core virtual machine.") ); _("Modify hardware emulation settings regulated by the PCSX2 core virtual machine."));
MyMenu.Append( MenuId_Video_WindowSettings, _("&Window Settings..."), MyMenu.Append(MenuId_Video_WindowSettings, _("&Window Settings..."),
_("Modify window and appearance options, including aspect ratio.") ); _("Modify window and appearance options, including aspect ratio."));
MyMenu.AppendSeparator(); MyMenu.AppendSeparator();
} }
// Populate options from the plugin here. // Populate options from the plugin here.
MyMenu.Append( GetPluginMenuId_Settings(PluginId), _("&Plugin Settings..."), MyMenu.Append(GetPluginMenuId_Settings(PluginId), _("&Plugin Settings..."),
wxsFormat( _("Opens the %s plugin's advanced settings dialog."), tbl_PluginInfo[pid].GetShortname().c_str() ) wxsFormat(_("Opens the %s plugin's advanced settings dialog."), tbl_PluginInfo[pid].GetShortname().c_str()));
);
} }
// deletes menu items belonging to (created by) the plugin. Leaves menu items created // deletes menu items belonging to (created by) the plugin. Leaves menu items created
@ -852,21 +867,21 @@ void PerPluginMenuInfo::OnUnloaded()
// done its own proper cleanup when the plugin was shutdown or unloaded, but lets // done its own proper cleanup when the plugin was shutdown or unloaded, but lets
// not trust them, shall we?) // not trust them, shall we?)
MenuItemAddonList& curlist( m_PluginMenuItems ); MenuItemAddonList& curlist(m_PluginMenuItems);
for( uint mx=0; mx<curlist.size(); ++mx ) for (uint mx = 0; mx < curlist.size(); ++mx)
MyMenu.Delete( curlist[mx].Item ); MyMenu.Delete(curlist[mx].Item);
curlist.clear(); curlist.clear();
MyMenu.SetLabel( GetPluginMenuId_Name(PluginId), _("No plugin loaded") ); MyMenu.SetLabel(GetPluginMenuId_Name(PluginId), _("No plugin loaded"));
MyMenu.Enable( GetPluginMenuId_Settings(PluginId), false ); MyMenu.Enable(GetPluginMenuId_Settings(PluginId), false);
} }
void PerPluginMenuInfo::OnLoaded() void PerPluginMenuInfo::OnLoaded()
{ {
if( !CorePlugins.IsLoaded(PluginId) ) return; if (!CorePlugins.IsLoaded(PluginId))
MyMenu.SetLabel( GetPluginMenuId_Name(PluginId), return;
CorePlugins.GetName( PluginId ) + L" " + CorePlugins.GetVersion( PluginId ) MyMenu.SetLabel(GetPluginMenuId_Name(PluginId),
); CorePlugins.GetName(PluginId) + L" " + CorePlugins.GetVersion(PluginId));
MyMenu.Enable( GetPluginMenuId_Settings(PluginId), true ); MyMenu.Enable(GetPluginMenuId_Settings(PluginId), true);
} }

View File

@ -13,7 +13,7 @@
* If not, see <http://www.gnu.org/licenses/>. * If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once #pragma once
#include "App.h" #include "App.h"
#include "AppSaveStates.h" #include "AppSaveStates.h"
@ -23,17 +23,17 @@
struct PluginMenuAddition struct PluginMenuAddition
{ {
wxString Text; wxString Text;
wxString HelpText; wxString HelpText;
PS2E_MenuItemStyle Flags; PS2E_MenuItemStyle Flags;
wxMenuItem* Item; wxMenuItem* Item;
int ItemId; int ItemId;
// Optional user data pointer (or typecast integer value) // Optional user data pointer (or typecast integer value)
void* UserPtr; void* UserPtr;
void (PS2E_CALLBACK *OnClicked)( PS2E_THISPTR* thisptr, void* userptr ); void(PS2E_CALLBACK* OnClicked)(PS2E_THISPTR* thisptr, void* userptr);
}; };
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -45,18 +45,22 @@ protected:
typedef std::vector<PluginMenuAddition> MenuItemAddonList; typedef std::vector<PluginMenuAddition> MenuItemAddonList;
// A list of menu items belonging to this plugin's menu. // A list of menu items belonging to this plugin's menu.
MenuItemAddonList m_PluginMenuItems; MenuItemAddonList m_PluginMenuItems;
public: public:
wxMenu& MyMenu; wxMenu& MyMenu;
PluginsEnum_t PluginId; PluginsEnum_t PluginId;
public: public:
PerPluginMenuInfo() : MyMenu(*new wxMenu()), PluginId (PluginId_Count) {} PerPluginMenuInfo()
: MyMenu(*new wxMenu())
, PluginId(PluginId_Count)
{
}
virtual ~PerPluginMenuInfo() = default; virtual ~PerPluginMenuInfo() = default;
void Populate( PluginsEnum_t pid ); void Populate(PluginsEnum_t pid);
void OnUnloaded(); void OnUnloaded();
void OnLoaded(); void OnLoaded();
@ -68,23 +72,23 @@ public:
// InvokeMenuCommand_OnSysStateUnlocked // InvokeMenuCommand_OnSysStateUnlocked
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class InvokeMenuCommand_OnSysStateUnlocked class InvokeMenuCommand_OnSysStateUnlocked
: public IEventListener_SysState : public IEventListener_SysState,
, public BaseDeletableObject public BaseDeletableObject
{ {
protected: protected:
MenuIdentifiers m_menu_cmd; MenuIdentifiers m_menu_cmd;
public: public:
InvokeMenuCommand_OnSysStateUnlocked( MenuIdentifiers menu_command ) InvokeMenuCommand_OnSysStateUnlocked(MenuIdentifiers menu_command)
{ {
m_menu_cmd = menu_command; m_menu_cmd = menu_command;
} }
virtual ~InvokeMenuCommand_OnSysStateUnlocked() = default; virtual ~InvokeMenuCommand_OnSysStateUnlocked() = default;
virtual void SaveStateAction_OnCreateFinished() virtual void SaveStateAction_OnCreateFinished()
{ {
wxGetApp().PostMenuAction( m_menu_cmd ); wxGetApp().PostMenuAction(m_menu_cmd);
} }
}; };
@ -92,50 +96,50 @@ public:
// MainEmuFrame // MainEmuFrame
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
class MainEmuFrame : public wxFrame, class MainEmuFrame : public wxFrame,
public EventListener_Plugins, public EventListener_Plugins,
public EventListener_CoreThread, public EventListener_CoreThread,
public EventListener_AppStatus public EventListener_AppStatus
{ {
typedef wxFrame _parent; typedef wxFrame _parent;
protected: protected:
bool m_RestartEmuOnDelete; bool m_RestartEmuOnDelete;
wxStatusBar& m_statusbar; wxStatusBar& m_statusbar;
wxStaticBitmap* m_background; wxStaticBitmap* m_background;
wxMenuBar& m_menubar; wxMenuBar& m_menubar;
wxMenu& m_menuCDVD; wxMenu& m_menuCDVD;
wxMenu& m_menuSys; wxMenu& m_menuSys;
wxMenu& m_menuConfig; wxMenu& m_menuConfig;
wxMenu& m_menuWindow; wxMenu& m_menuWindow;
wxMenu& m_menuCapture; wxMenu& m_menuCapture;
wxMenu& m_submenuVideoCapture; wxMenu& m_submenuVideoCapture;
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
wxMenu& m_menuRecording; wxMenu& m_menuRecording;
#endif #endif
wxMenu& m_menuHelp; wxMenu& m_menuHelp;
wxMenu& m_LoadStatesSubmenu; wxMenu& m_LoadStatesSubmenu;
wxMenu& m_SaveStatesSubmenu; wxMenu& m_SaveStatesSubmenu;
wxMenu& m_GameSettingsSubmenu; wxMenu& m_GameSettingsSubmenu;
wxMenuItem* m_menuItem_RecentIsoMenu; wxMenuItem* m_menuItem_RecentIsoMenu;
wxMenuItem* m_menuItem_DriveListMenu; wxMenuItem* m_menuItem_DriveListMenu;
wxMenuItem& m_MenuItem_Console; wxMenuItem& m_MenuItem_Console;
#if defined(__unix__) #if defined(__unix__)
wxMenuItem& m_MenuItem_Console_Stdio; wxMenuItem& m_MenuItem_Console_Stdio;
#endif #endif
PerPluginMenuInfo m_PluginMenuPacks[PluginId_Count]; PerPluginMenuInfo m_PluginMenuPacks[PluginId_Count];
bool m_capturingVideo; bool m_capturingVideo;
virtual void DispatchEvent( const PluginEventType& plugin_evt ); virtual void DispatchEvent(const PluginEventType& plugin_evt);
virtual void DispatchEvent( const CoreThreadStatus& status ); virtual void DispatchEvent(const CoreThreadStatus& status);
virtual void AppStatusEvent_OnSettingsApplied(); virtual void AppStatusEvent_OnSettingsApplied();
public: public:
@ -144,10 +148,10 @@ public:
void OnLogBoxHidden(); void OnLogBoxHidden();
bool IsPaused() const { return GetMenuBar()->IsChecked( MenuId_Sys_SuspendResume ); } bool IsPaused() const { return GetMenuBar()->IsChecked(MenuId_Sys_SuspendResume); }
void UpdateCdvdSrcSelection(); void UpdateCdvdSrcSelection();
void RemoveCdvdMenu(); void RemoveCdvdMenu();
void EnableMenuItem( int id, bool enable ); void EnableMenuItem(int id, bool enable);
void CheckMenuItem(int id, bool checked); void CheckMenuItem(int id, bool checked);
void SetMenuItemLabel(int id, wxString str); void SetMenuItemLabel(int id, wxString str);
void EnableCdvdPluginSubmenu(bool isEnable = true); void EnableCdvdPluginSubmenu(bool isEnable = true);
@ -159,7 +163,7 @@ public:
void CreateCaptureMenu(); void CreateCaptureMenu();
void CreateRecordMenu(); void CreateRecordMenu();
void CreateHelpMenu(); void CreateHelpMenu();
bool Destroy(); bool Destroy();
void ApplyConfigToGui(AppConfig& configToApply, int flags = 0); void ApplyConfigToGui(AppConfig& configToApply, int flags = 0);
@ -178,77 +182,77 @@ protected:
void ApplySettings(); void ApplySettings();
void ApplyCoreStatus(); void ApplyCoreStatus();
void InitLogBoxPosition( AppConfig::ConsoleLogOptions& conf ); void InitLogBoxPosition(AppConfig::ConsoleLogOptions& conf);
void OnCloseWindow( wxCloseEvent& evt ); void OnCloseWindow(wxCloseEvent& evt);
void OnMoveAround( wxMoveEvent& evt ); void OnMoveAround(wxMoveEvent& evt);
void OnFocus( wxFocusEvent& evt ); void OnFocus(wxFocusEvent& evt);
void OnActivate( wxActivateEvent& evt ); void OnActivate(wxActivateEvent& evt);
void Menu_SysSettings_Click(wxCommandEvent &event); void Menu_SysSettings_Click(wxCommandEvent& event);
void Menu_AudioSettings_Click(wxCommandEvent &event); void Menu_AudioSettings_Click(wxCommandEvent& event);
void Menu_McdSettings_Click(wxCommandEvent &event); void Menu_McdSettings_Click(wxCommandEvent& event);
void Menu_WindowSettings_Click(wxCommandEvent &event); void Menu_WindowSettings_Click(wxCommandEvent& event);
void Menu_GSSettings_Click(wxCommandEvent &event); void Menu_GSSettings_Click(wxCommandEvent& event);
void Menu_SelectPluginsBios_Click(wxCommandEvent &event); void Menu_SelectPluginsBios_Click(wxCommandEvent& event);
void Menu_ResetAllSettings_Click(wxCommandEvent &event); void Menu_ResetAllSettings_Click(wxCommandEvent& event);
void Menu_IsoBrowse_Click(wxCommandEvent &event); void Menu_IsoBrowse_Click(wxCommandEvent& event);
void Menu_IsoClear_Click(wxCommandEvent &event); void Menu_IsoClear_Click(wxCommandEvent& event);
void Menu_EnableBackupStates_Click(wxCommandEvent &event); void Menu_EnableBackupStates_Click(wxCommandEvent& event);
void Menu_EnablePatches_Click(wxCommandEvent &event); void Menu_EnablePatches_Click(wxCommandEvent& event);
void Menu_EnableCheats_Click(wxCommandEvent &event); void Menu_EnableCheats_Click(wxCommandEvent& event);
void Menu_EnableIPC_Click(wxCommandEvent &event); void Menu_EnableIPC_Click(wxCommandEvent& event);
void Menu_EnableWideScreenPatches_Click(wxCommandEvent &event); void Menu_EnableWideScreenPatches_Click(wxCommandEvent& event);
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
void Menu_EnableRecordingTools_Click(wxCommandEvent &event); void Menu_EnableRecordingTools_Click(wxCommandEvent& event);
#endif #endif
void Menu_EnableHostFs_Click(wxCommandEvent &event); void Menu_EnableHostFs_Click(wxCommandEvent& event);
void Menu_BootCdvd_Click(wxCommandEvent &event); void Menu_BootCdvd_Click(wxCommandEvent& event);
void Menu_FastBoot_Click(wxCommandEvent &event); void Menu_FastBoot_Click(wxCommandEvent& event);
void Menu_OpenELF_Click(wxCommandEvent &event); void Menu_OpenELF_Click(wxCommandEvent& event);
void Menu_CdvdSource_Click(wxCommandEvent &event); void Menu_CdvdSource_Click(wxCommandEvent& event);
void Menu_LoadStates_Click(wxCommandEvent &event); void Menu_LoadStates_Click(wxCommandEvent& event);
void Menu_SaveStates_Click(wxCommandEvent &event); void Menu_SaveStates_Click(wxCommandEvent& event);
void Menu_LoadStateFromFile_Click(wxCommandEvent &event); void Menu_LoadStateFromFile_Click(wxCommandEvent& event);
void Menu_SaveStateToFile_Click(wxCommandEvent &event); void Menu_SaveStateToFile_Click(wxCommandEvent& event);
void Menu_Exit_Click(wxCommandEvent &event); void Menu_Exit_Click(wxCommandEvent& event);
void Menu_SuspendResume_Click(wxCommandEvent &event); void Menu_SuspendResume_Click(wxCommandEvent& event);
void Menu_SysShutdown_Click(wxCommandEvent &event); void Menu_SysShutdown_Click(wxCommandEvent& event);
void Menu_ConfigPlugin_Click(wxCommandEvent &event); void Menu_ConfigPlugin_Click(wxCommandEvent& event);
void Menu_MultitapToggle_Click(wxCommandEvent &event); void Menu_MultitapToggle_Click(wxCommandEvent& event);
void Menu_Debug_Open_Click(wxCommandEvent &event); void Menu_Debug_Open_Click(wxCommandEvent& event);
void Menu_Debug_MemoryDump_Click(wxCommandEvent &event); void Menu_Debug_MemoryDump_Click(wxCommandEvent& event);
void Menu_Debug_CreateBlockdump_Click(wxCommandEvent &event); void Menu_Debug_CreateBlockdump_Click(wxCommandEvent& event);
void Menu_Ask_On_Boot_Click(wxCommandEvent &event); void Menu_Ask_On_Boot_Click(wxCommandEvent& event);
void Menu_ShowConsole(wxCommandEvent &event); void Menu_ShowConsole(wxCommandEvent& event);
void Menu_ChangeLang(wxCommandEvent &event); void Menu_ChangeLang(wxCommandEvent& event);
void Menu_ShowConsole_Stdio(wxCommandEvent &event); void Menu_ShowConsole_Stdio(wxCommandEvent& event);
void Menu_GetStarted(wxCommandEvent &event); void Menu_GetStarted(wxCommandEvent& event);
void Menu_Compatibility(wxCommandEvent &event); void Menu_Compatibility(wxCommandEvent& event);
void Menu_Forums(wxCommandEvent &event); void Menu_Forums(wxCommandEvent& event);
void Menu_Website(wxCommandEvent &event); void Menu_Website(wxCommandEvent& event);
void Menu_Github(wxCommandEvent &event); void Menu_Github(wxCommandEvent& event);
void Menu_Wiki(wxCommandEvent &event); void Menu_Wiki(wxCommandEvent& event);
void Menu_ShowAboutBox(wxCommandEvent &event); void Menu_ShowAboutBox(wxCommandEvent& event);
void Menu_Capture_Video_Record_Click(wxCommandEvent &event); void Menu_Capture_Video_Record_Click(wxCommandEvent& event);
void Menu_Capture_Video_Stop_Click(wxCommandEvent &event); void Menu_Capture_Video_Stop_Click(wxCommandEvent& event);
void VideoCaptureUpdate(); void VideoCaptureUpdate();
void Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent &event); void Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent& event);
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
void Menu_Recording_New_Click(wxCommandEvent &event); void Menu_Recording_New_Click(wxCommandEvent& event);
void Menu_Recording_Play_Click(wxCommandEvent &event); void Menu_Recording_Play_Click(wxCommandEvent& event);
void Menu_Recording_Stop_Click(wxCommandEvent &event); void Menu_Recording_Stop_Click(wxCommandEvent& event);
void Menu_Recording_TogglePause_Click(wxCommandEvent &event); void Menu_Recording_TogglePause_Click(wxCommandEvent &event);
void Menu_Recording_FrameAdvance_Click(wxCommandEvent &event); void Menu_Recording_FrameAdvance_Click(wxCommandEvent &event);
void Menu_Recording_ToggleRecordingMode_Click(wxCommandEvent &event); void Menu_Recording_ToggleRecordingMode_Click(wxCommandEvent &event);
@ -256,18 +260,18 @@ protected:
#endif #endif
void _DoBootCdvd(); void _DoBootCdvd();
bool _DoSelectIsoBrowser( wxString& dest ); bool _DoSelectIsoBrowser(wxString& dest);
bool _DoSelectELFBrowser(); bool _DoSelectELFBrowser();
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
// MainEmuFram Internal API for Populating Main Menu Contents // MainEmuFram Internal API for Populating Main Menu Contents
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
wxMenu* MakeStatesSubMenu( int baseid, int loadBackupId=-1 ) const; wxMenu* MakeStatesSubMenu(int baseid, int loadBackupId = -1) const;
void ConnectMenus(); void ConnectMenus();
friend class Pcsx2App; friend class Pcsx2App;
}; };
extern int GetPluginMenuId_Settings( PluginsEnum_t pid ); extern int GetPluginMenuId_Settings(PluginsEnum_t pid);

View File

@ -32,51 +32,51 @@
#include "Utilities/IniInterface.h" #include "Utilities/IniInterface.h"
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
# include "Recording/InputRecording.h" #include "Recording/InputRecording.h"
# include "Recording/InputRecordingControls.h" #include "Recording/InputRecordingControls.h"
# include "Recording/VirtualPad/VirtualPad.h" #include "Recording/VirtualPad/VirtualPad.h"
#endif #endif
using namespace Dialogs; using namespace Dialogs;
void MainEmuFrame::Menu_SysSettings_Click(wxCommandEvent &event) void MainEmuFrame::Menu_SysSettings_Click(wxCommandEvent& event)
{ {
AppOpenDialog<SysConfigDialog>( this ); AppOpenDialog<SysConfigDialog>(this);
} }
void MainEmuFrame::Menu_AudioSettings_Click(wxCommandEvent &event) void MainEmuFrame::Menu_AudioSettings_Click(wxCommandEvent& event)
{ {
SPU2configure(); SPU2configure();
} }
void MainEmuFrame::Menu_McdSettings_Click(wxCommandEvent &event) void MainEmuFrame::Menu_McdSettings_Click(wxCommandEvent& event)
{ {
ScopedCoreThreadClose closed_core; ScopedCoreThreadClose closed_core;
closed_core.AllowResume(); closed_core.AllowResume();
AppOpenModalDialog<McdConfigDialog>(wxEmptyString, this); AppOpenModalDialog<McdConfigDialog>(wxEmptyString, this);
} }
void MainEmuFrame::Menu_WindowSettings_Click(wxCommandEvent &event) void MainEmuFrame::Menu_WindowSettings_Click(wxCommandEvent& event)
{ {
wxCommandEvent evt( pxEvt_SetSettingsPage ); wxCommandEvent evt(pxEvt_SetSettingsPage);
evt.SetString( L"GS Window" ); evt.SetString(L"GS Window");
AppOpenDialog<SysConfigDialog>( this )->GetEventHandler()->ProcessEvent( evt ); AppOpenDialog<SysConfigDialog>(this)->GetEventHandler()->ProcessEvent(evt);
} }
void MainEmuFrame::Menu_GSSettings_Click(wxCommandEvent &event) void MainEmuFrame::Menu_GSSettings_Click(wxCommandEvent& event)
{ {
wxCommandEvent evt( pxEvt_SetSettingsPage ); wxCommandEvent evt(pxEvt_SetSettingsPage);
evt.SetString( L"GS" ); evt.SetString(L"GS");
AppOpenDialog<SysConfigDialog>( this )->GetEventHandler()->ProcessEvent( evt ); AppOpenDialog<SysConfigDialog>(this)->GetEventHandler()->ProcessEvent(evt);
} }
void MainEmuFrame::Menu_SelectPluginsBios_Click(wxCommandEvent &event) void MainEmuFrame::Menu_SelectPluginsBios_Click(wxCommandEvent& event)
{ {
AppOpenDialog<ComponentsConfigDialog>( this ); AppOpenDialog<ComponentsConfigDialog>(this);
} }
void MainEmuFrame::Menu_ChangeLang(wxCommandEvent &event) // Always in English void MainEmuFrame::Menu_ChangeLang(wxCommandEvent& event) // Always in English
{ {
AppOpenDialog<InterfaceLanguageDialog>(this); AppOpenDialog<InterfaceLanguageDialog>(this);
} }
@ -86,8 +86,8 @@ static void WipeSettings()
wxGetApp().CleanupRestartable(); wxGetApp().CleanupRestartable();
wxGetApp().CleanupResources(); wxGetApp().CleanupResources();
wxRemoveFile( GetUiSettingsFilename() ); wxRemoveFile(GetUiSettingsFilename());
wxRemoveFile( GetVmSettingsFilename() ); wxRemoveFile(GetVmSettingsFilename());
// FIXME: wxRmdir doesn't seem to work here for some reason (possible file sharing issue // FIXME: wxRmdir doesn't seem to work here for some reason (possible file sharing issue
// with a plugin that leaves a file handle dangling maybe?). But deleting the inis folder // with a plugin that leaves a file handle dangling maybe?). But deleting the inis folder
@ -111,16 +111,16 @@ void MainEmuFrame::RemoveCdvdMenu()
m_menuItem_RecentIsoMenu = nullptr; m_menuItem_RecentIsoMenu = nullptr;
} }
void MainEmuFrame::Menu_ResetAllSettings_Click(wxCommandEvent &event) void MainEmuFrame::Menu_ResetAllSettings_Click(wxCommandEvent& event)
{ {
if( IsBeingDeleted() || m_RestartEmuOnDelete ) return; if (IsBeingDeleted() || m_RestartEmuOnDelete)
return;
{ {
ScopedCoreThreadPopup suspender; ScopedCoreThreadPopup suspender;
if( !Msgbox::OkCancel( pxsFmt( if (!Msgbox::OkCancel(pxsFmt(
pxE( L"This command clears %s settings and allows you to re-run the First-Time Wizard. You will need to manually restart %s after this operation.\n\nWARNING!! Click OK to delete *ALL* settings for %s and force-close the app, losing any current emulation progress. Are you absolutely sure?\n\n(note: settings for plugins are unaffected)" pxE(L"This command clears %s settings and allows you to re-run the First-Time Wizard. You will need to manually restart %s after this operation.\n\nWARNING!! Click OK to delete *ALL* settings for %s and force-close the app, losing any current emulation progress. Are you absolutely sure?\n\n(note: settings for plugins are unaffected)"), WX_STR(pxGetAppName()), WX_STR(pxGetAppName()), WX_STR(pxGetAppName())),
), WX_STR(pxGetAppName()), WX_STR(pxGetAppName()), WX_STR(pxGetAppName()) ), _("Reset all settings?")))
_("Reset all settings?") ) )
{ {
suspender.AllowResume(); suspender.AllowResume();
return; return;
@ -128,27 +128,27 @@ void MainEmuFrame::Menu_ResetAllSettings_Click(wxCommandEvent &event)
} }
WipeSettings(); WipeSettings();
wxGetApp().PostMenuAction( MenuId_Exit ); wxGetApp().PostMenuAction(MenuId_Exit);
} }
// Return values: // Return values:
// wxID_CANCEL - User canceled the action outright. // wxID_CANCEL - User canceled the action outright.
// wxID_RESET - User wants to reset the emu in addition to swap discs // wxID_RESET - User wants to reset the emu in addition to swap discs
// (anything else) - Standard swap, no reset. (hotswap!) // (anything else) - Standard swap, no reset. (hotswap!)
wxWindowID SwapOrReset_Iso( wxWindow* owner, IScopedCoreThread& core_control, const wxString& isoFilename, const wxString& descpart1 ) wxWindowID SwapOrReset_Iso(wxWindow* owner, IScopedCoreThread& core_control, const wxString& isoFilename, const wxString& descpart1)
{ {
wxWindowID result = wxID_CANCEL; wxWindowID result = wxID_CANCEL;
if( (g_Conf->CdvdSource == CDVD_SourceType::Iso) && (isoFilename == g_Conf->CurrentIso) ) if ((g_Conf->CdvdSource == CDVD_SourceType::Iso) && (isoFilename == g_Conf->CurrentIso))
{ {
core_control.AllowResume(); core_control.AllowResume();
return result; return result;
} }
if( SysHasValidState() ) if (SysHasValidState())
{ {
core_control.DisallowResume(); core_control.DisallowResume();
wxDialogWithHelpers dialog( owner, _("Confirm ISO image change") ); wxDialogWithHelpers dialog(owner, _("Confirm ISO image change"));
dialog += dialog.Heading(descpart1); dialog += dialog.Heading(descpart1);
dialog += dialog.GetCharHeight(); dialog += dialog.GetCharHeight();
@ -156,8 +156,8 @@ wxWindowID SwapOrReset_Iso( wxWindow* owner, IScopedCoreThread& core_control, co
dialog += dialog.GetCharHeight(); dialog += dialog.GetCharHeight();
dialog += dialog.Heading(_("Do you want to swap discs or boot the new image (via system reset)?")); dialog += dialog.Heading(_("Do you want to swap discs or boot the new image (via system reset)?"));
result = pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap")); result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
if( result == wxID_CANCEL ) if (result == wxID_CANCEL)
{ {
core_control.AllowResume(); core_control.AllowResume();
return result; return result;
@ -165,16 +165,16 @@ wxWindowID SwapOrReset_Iso( wxWindow* owner, IScopedCoreThread& core_control, co
} }
g_Conf->CdvdSource = CDVD_SourceType::Iso; g_Conf->CdvdSource = CDVD_SourceType::Iso;
SysUpdateIsoSrcFile( isoFilename ); SysUpdateIsoSrcFile(isoFilename);
if( result == wxID_RESET ) if (result == wxID_RESET)
{ {
core_control.DisallowResume(); core_control.DisallowResume();
sApp.SysExecute(CDVD_SourceType::Iso); sApp.SysExecute(CDVD_SourceType::Iso);
} }
else else
{ {
Console.Indent().WriteLn( "HotSwapping to new ISO src image!" ); Console.Indent().WriteLn("HotSwapping to new ISO src image!");
//g_Conf->CdvdSource = CDVDsrc_Iso; //g_Conf->CdvdSource = CDVDsrc_Iso;
//CoreThread.ChangeCdvdSource(); //CoreThread.ChangeCdvdSource();
core_control.AllowResume(); core_control.AllowResume();
@ -187,7 +187,7 @@ wxWindowID SwapOrReset_Iso( wxWindow* owner, IScopedCoreThread& core_control, co
// wxID_CANCEL - User canceled the action outright. // wxID_CANCEL - User canceled the action outright.
// wxID_RESET - User wants to reset the emu in addition to swap discs // wxID_RESET - User wants to reset the emu in addition to swap discs
// (anything else) - Standard swap, no reset. (hotswap!) // (anything else) - Standard swap, no reset. (hotswap!)
wxWindowID SwapOrReset_Disc( wxWindow* owner, IScopedCoreThread& core, const wxString driveLetter) wxWindowID SwapOrReset_Disc(wxWindow* owner, IScopedCoreThread& core, const wxString driveLetter)
{ {
wxWindowID result = wxID_CANCEL; wxWindowID result = wxID_CANCEL;
@ -230,27 +230,27 @@ wxWindowID SwapOrReset_Disc( wxWindow* owner, IScopedCoreThread& core, const wxS
return result; return result;
} }
wxWindowID SwapOrReset_CdvdSrc( wxWindow* owner, CDVD_SourceType newsrc ) wxWindowID SwapOrReset_CdvdSrc(wxWindow* owner, CDVD_SourceType newsrc)
{ {
if(newsrc == g_Conf->CdvdSource) return wxID_CANCEL; if (newsrc == g_Conf->CdvdSource)
return wxID_CANCEL;
wxWindowID result = wxID_CANCEL; wxWindowID result = wxID_CANCEL;
ScopedCoreThreadPopup core; ScopedCoreThreadPopup core;
if( SysHasValidState() ) if (SysHasValidState())
{ {
wxDialogWithHelpers dialog( owner, _("Confirm CDVD source change") ); wxDialogWithHelpers dialog(owner, _("Confirm CDVD source change"));
wxString changeMsg; wxString changeMsg;
changeMsg.Printf(_("You've selected to switch the CDVD source from %s to %s."), changeMsg.Printf(_("You've selected to switch the CDVD source from %s to %s."),
CDVD_SourceLabels[enum_cast(g_Conf->CdvdSource)], CDVD_SourceLabels[enum_cast(newsrc)] ); CDVD_SourceLabels[enum_cast(g_Conf->CdvdSource)], CDVD_SourceLabels[enum_cast(newsrc)]);
dialog += dialog.Heading(changeMsg + L"\n\n" + dialog += dialog.Heading(changeMsg + L"\n\n" +
_("Do you want to swap discs or boot the new image (system reset)?") _("Do you want to swap discs or boot the new image (system reset)?"));
);
result = pxIssueConfirmation( dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap")); result = pxIssueConfirmation(dialog, MsgButtons().Reset().Cancel().Custom(_("Swap Disc"), "swap"));
if( result == wxID_CANCEL ) if (result == wxID_CANCEL)
{ {
core.AllowResume(); core.AllowResume();
sMainFrame.UpdateCdvdSrcSelection(); sMainFrame.UpdateCdvdSrcSelection();
@ -261,11 +261,11 @@ wxWindowID SwapOrReset_CdvdSrc( wxWindow* owner, CDVD_SourceType newsrc )
CDVD_SourceType oldsrc = g_Conf->CdvdSource; CDVD_SourceType oldsrc = g_Conf->CdvdSource;
g_Conf->CdvdSource = newsrc; g_Conf->CdvdSource = newsrc;
if( result != wxID_RESET ) if (result != wxID_RESET)
{ {
Console.Indent().WriteLn(L"(CdvdSource) HotSwapping CDVD source types from %s to %s.", Console.Indent().WriteLn(L"(CdvdSource) HotSwapping CDVD source types from %s to %s.",
WX_STR(wxString(CDVD_SourceLabels[enum_cast(oldsrc)])), WX_STR(wxString(CDVD_SourceLabels[enum_cast(oldsrc)])),
WX_STR(wxString(CDVD_SourceLabels[enum_cast(newsrc)]))); WX_STR(wxString(CDVD_SourceLabels[enum_cast(newsrc)])));
//CoreThread.ChangeCdvdSource(); //CoreThread.ChangeCdvdSource();
sMainFrame.UpdateCdvdSrcSelection(); sMainFrame.UpdateCdvdSrcSelection();
core.AllowResume(); core.AllowResume();
@ -273,19 +273,20 @@ wxWindowID SwapOrReset_CdvdSrc( wxWindow* owner, CDVD_SourceType newsrc )
else else
{ {
core.DisallowResume(); core.DisallowResume();
sApp.SysExecute( g_Conf->CdvdSource ); sApp.SysExecute(g_Conf->CdvdSource);
} }
return result; return result;
} }
static wxString JoinFiletypes( const wxChar** src ) static wxString JoinFiletypes(const wxChar** src)
{ {
wxString dest; wxString dest;
while( *src != NULL ) while (*src != NULL)
{ {
if( *src[0] == 0 ) continue; if (*src[0] == 0)
if( !dest.IsEmpty() ) continue;
if (!dest.IsEmpty())
dest += L";"; dest += L";";
dest += pxsFmt(L"*.%ls", *src); dest += pxsFmt(L"*.%ls", *src);
@ -298,30 +299,29 @@ static wxString JoinFiletypes( const wxChar** src )
++src; ++src;
} }
return dest; return dest;
} }
// Returns FALSE if the user canceled the action. // Returns FALSE if the user canceled the action.
bool MainEmuFrame::_DoSelectIsoBrowser( wxString& result ) bool MainEmuFrame::_DoSelectIsoBrowser(wxString& result)
{ {
static const wxChar* isoSupportedTypes[] = static const wxChar* isoSupportedTypes[] =
{ {
L"iso", L"mdf", L"nrg", L"bin", L"img", NULL L"iso", L"mdf", L"nrg", L"bin", L"img", NULL};
};
const wxString isoSupportedLabel(JoinString(isoSupportedTypes, L" "));
const wxString isoSupportedList(JoinFiletypes(isoSupportedTypes));
const wxString isoSupportedLabel( JoinString(isoSupportedTypes, L" ") );
const wxString isoSupportedList( JoinFiletypes(isoSupportedTypes) );
wxArrayString isoFilterTypes; wxArrayString isoFilterTypes;
isoFilterTypes.Add(pxsFmt(_("All Supported (%s)"), WX_STR((isoSupportedLabel + L" .dump" + L" .gz" + L" .cso")))); isoFilterTypes.Add(pxsFmt(_("All Supported (%s)"), WX_STR((isoSupportedLabel + L" .dump" + L" .gz" + L" .cso"))));
isoFilterTypes.Add(isoSupportedList + L";*.dump" + L";*.gz" + L";*.cso"); isoFilterTypes.Add(isoSupportedList + L";*.dump" + L";*.gz" + L";*.cso");
isoFilterTypes.Add(pxsFmt(_("Disc Images (%s)"), WX_STR(isoSupportedLabel) )); isoFilterTypes.Add(pxsFmt(_("Disc Images (%s)"), WX_STR(isoSupportedLabel)));
isoFilterTypes.Add(isoSupportedList); isoFilterTypes.Add(isoSupportedList);
isoFilterTypes.Add(pxsFmt(_("Blockdumps (%s)"), L".dump" )); isoFilterTypes.Add(pxsFmt(_("Blockdumps (%s)"), L".dump"));
isoFilterTypes.Add(L"*.dump"); isoFilterTypes.Add(L"*.dump");
isoFilterTypes.Add(pxsFmt(_("Compressed (%s)"), L".gz .cso")); isoFilterTypes.Add(pxsFmt(_("Compressed (%s)"), L".gz .cso"));
@ -329,14 +329,14 @@ bool MainEmuFrame::_DoSelectIsoBrowser( wxString& result )
isoFilterTypes.Add(_("All Files (*.*)")); isoFilterTypes.Add(_("All Files (*.*)"));
isoFilterTypes.Add(L"*.*"); isoFilterTypes.Add(L"*.*");
wxFileDialog ctrl( this, _("Select disc image, compressed disc image, or block-dump..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString,
JoinString(isoFilterTypes, L"|"), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( ctrl.ShowModal() != wxID_CANCEL ) wxFileDialog ctrl(this, _("Select disc image, compressed disc image, or block-dump..."), g_Conf->Folders.RunIso.ToString(), wxEmptyString,
JoinString(isoFilterTypes, L"|"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if (ctrl.ShowModal() != wxID_CANCEL)
{ {
result = ctrl.GetPath(); result = ctrl.GetPath();
g_Conf->Folders.RunIso = wxFileName( result ).GetPath(); g_Conf->Folders.RunIso = wxFileName(result).GetPath();
return true; return true;
} }
@ -347,12 +347,12 @@ bool MainEmuFrame::_DoSelectELFBrowser()
{ {
static const wxChar* elfFilterType = L"ELF Files (.elf)|*.elf;*.ELF"; static const wxChar* elfFilterType = L"ELF Files (.elf)|*.elf;*.ELF";
wxFileDialog ctrl( this, _("Select ELF file..."), g_Conf->Folders.RunELF.ToString(), wxEmptyString, wxFileDialog ctrl(this, _("Select ELF file..."), g_Conf->Folders.RunELF.ToString(), wxEmptyString,
(wxString)elfFilterType + L"|" + _("All Files (*.*)") + L"|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST ); (wxString)elfFilterType + L"|" + _("All Files (*.*)") + L"|*.*", wxFD_OPEN | wxFD_FILE_MUST_EXIST);
if( ctrl.ShowModal() != wxID_CANCEL ) if (ctrl.ShowModal() != wxID_CANCEL)
{ {
g_Conf->Folders.RunELF = wxFileName( ctrl.GetPath() ).GetPath(); g_Conf->Folders.RunELF = wxFileName(ctrl.GetPath()).GetPath();
g_Conf->CurrentELF = ctrl.GetPath(); g_Conf->CurrentELF = ctrl.GetPath();
return true; return true;
} }
@ -364,79 +364,84 @@ void MainEmuFrame::_DoBootCdvd()
{ {
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
if( g_Conf->CdvdSource == CDVD_SourceType::Iso ) if (g_Conf->CdvdSource == CDVD_SourceType::Iso)
{ {
bool selector = g_Conf->CurrentIso.IsEmpty(); bool selector = g_Conf->CurrentIso.IsEmpty();
if( !selector && !wxFileExists(g_Conf->CurrentIso) ) if (!selector && !wxFileExists(g_Conf->CurrentIso))
{ {
// User has an iso selected from a previous run, but it doesn't exist anymore. // User has an iso selected from a previous run, but it doesn't exist anymore.
// Issue a courtesy popup and then an Iso Selector to choose a new one. // Issue a courtesy popup and then an Iso Selector to choose a new one.
wxDialogWithHelpers dialog( this, _("ISO file not found!") ); wxDialogWithHelpers dialog(this, _("ISO file not found!"));
dialog += dialog.Heading( dialog += dialog.Heading(
_("An error occurred while trying to open the file:") + wxString(L"\n\n") + g_Conf->CurrentIso + L"\n\n" + _("An error occurred while trying to open the file:") + wxString(L"\n\n") + g_Conf->CurrentIso + L"\n\n" +
_("Error: The configured ISO file does not exist. Click OK to select a new ISO source for CDVD.") _("Error: The configured ISO file does not exist. Click OK to select a new ISO source for CDVD."));
);
pxIssueConfirmation( dialog, MsgButtons().OK() ); pxIssueConfirmation(dialog, MsgButtons().OK());
selector = true; selector = true;
} }
if( selector || g_Conf->AskOnBoot) if (selector || g_Conf->AskOnBoot)
{ {
wxString result; wxString result;
if( !_DoSelectIsoBrowser( result ) ) if (!_DoSelectIsoBrowser(result))
{ {
paused_core.AllowResume(); paused_core.AllowResume();
return; return;
} }
SysUpdateIsoSrcFile( result ); SysUpdateIsoSrcFile(result);
} }
} }
if( SysHasValidState() ) if (SysHasValidState())
{ {
wxDialogWithHelpers dialog( this, _("Confirm PS2 Reset") ); wxDialogWithHelpers dialog(this, _("Confirm PS2 Reset"));
dialog += dialog.Heading( GetMsg_ConfirmSysReset() ); dialog += dialog.Heading(GetMsg_ConfirmSysReset());
bool confirmed = (pxIssueConfirmation( dialog, MsgButtons().Yes().Cancel(), L"BootCdvd.ConfirmReset" ) != wxID_CANCEL); bool confirmed = (pxIssueConfirmation(dialog, MsgButtons().Yes().Cancel(), L"BootCdvd.ConfirmReset") != wxID_CANCEL);
if( !confirmed ) if (!confirmed)
{ {
paused_core.AllowResume(); paused_core.AllowResume();
return; return;
} }
} }
sApp.SysExecute( g_Conf->CdvdSource ); sApp.SysExecute(g_Conf->CdvdSource);
} }
void MainEmuFrame::Menu_CdvdSource_Click( wxCommandEvent &event ) void MainEmuFrame::Menu_CdvdSource_Click(wxCommandEvent& event)
{ {
CDVD_SourceType newsrc = CDVD_SourceType::NoDisc; CDVD_SourceType newsrc = CDVD_SourceType::NoDisc;
switch( event.GetId() ) switch (event.GetId())
{ {
case MenuId_Src_Iso: newsrc = CDVD_SourceType::Iso; break; case MenuId_Src_Iso:
case MenuId_Src_Disc: newsrc = CDVD_SourceType::Disc; break; newsrc = CDVD_SourceType::Iso;
case MenuId_Src_NoDisc: newsrc = CDVD_SourceType::NoDisc; break; break;
jNO_DEFAULT case MenuId_Src_Disc:
newsrc = CDVD_SourceType::Disc;
break;
case MenuId_Src_NoDisc:
newsrc = CDVD_SourceType::NoDisc;
break;
jNO_DEFAULT
} }
SwapOrReset_CdvdSrc(this, newsrc); SwapOrReset_CdvdSrc(this, newsrc);
} }
void MainEmuFrame::Menu_BootCdvd_Click( wxCommandEvent &event ) void MainEmuFrame::Menu_BootCdvd_Click(wxCommandEvent& event)
{ {
g_Conf->EmuOptions.UseBOOT2Injection = g_Conf->EnableFastBoot; g_Conf->EmuOptions.UseBOOT2Injection = g_Conf->EnableFastBoot;
_DoBootCdvd(); _DoBootCdvd();
} }
void MainEmuFrame::Menu_FastBoot_Click( wxCommandEvent &event ) void MainEmuFrame::Menu_FastBoot_Click(wxCommandEvent& event)
{ {
g_Conf->EnableFastBoot = GetMenuBar()->IsChecked( MenuId_Config_FastBoot ); g_Conf->EnableFastBoot = GetMenuBar()->IsChecked(MenuId_Config_FastBoot);
AppApplySettings(); AppApplySettings();
AppSaveSettings(); AppSaveSettings();
UpdateStatusBar(); UpdateStatusBar();
@ -447,22 +452,22 @@ wxString GetMsg_IsoImageChanged()
return _("You have selected the following ISO image into PCSX2:\n\n"); return _("You have selected the following ISO image into PCSX2:\n\n");
} }
void MainEmuFrame::Menu_IsoBrowse_Click( wxCommandEvent &event ) void MainEmuFrame::Menu_IsoBrowse_Click(wxCommandEvent& event)
{ {
ScopedCoreThreadPopup core; ScopedCoreThreadPopup core;
wxString isofile; wxString isofile;
if( !_DoSelectIsoBrowser(isofile) ) if (!_DoSelectIsoBrowser(isofile))
{ {
core.AllowResume(); core.AllowResume();
return; return;
} }
SwapOrReset_Iso(this, core, isofile, GetMsg_IsoImageChanged()); SwapOrReset_Iso(this, core, isofile, GetMsg_IsoImageChanged());
AppSaveSettings(); // save the new iso selection; update menus! AppSaveSettings(); // save the new iso selection; update menus!
} }
void MainEmuFrame::Menu_IsoClear_Click(wxCommandEvent &event) void MainEmuFrame::Menu_IsoClear_Click(wxCommandEvent& event)
{ {
wxDialogWithHelpers dialog(this, _("Confirm clearing ISO list")); wxDialogWithHelpers dialog(this, _("Confirm clearing ISO list"));
dialog += dialog.Heading(_("This will clear the ISO list. If an ISO is running it will remain in the list. Continue?")); dialog += dialog.Heading(_("This will clear the ISO list. If an ISO is running it will remain in the list. Continue?"));
@ -479,7 +484,7 @@ void MainEmuFrame::Menu_IsoClear_Click(wxCommandEvent &event)
} }
} }
void MainEmuFrame::Menu_Ask_On_Boot_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Ask_On_Boot_Click(wxCommandEvent& event)
{ {
g_Conf->AskOnBoot = event.IsChecked(); g_Conf->AskOnBoot = event.IsChecked();
@ -490,7 +495,7 @@ void MainEmuFrame::Menu_Ask_On_Boot_Click(wxCommandEvent &event)
FindItemInMenuBar(MenuId_IsoBrowse)->Enable(!event.IsChecked()); FindItemInMenuBar(MenuId_IsoBrowse)->Enable(!event.IsChecked());
} }
void MainEmuFrame::Menu_Debug_CreateBlockdump_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Debug_CreateBlockdump_Click(wxCommandEvent& event)
{ {
g_Conf->EmuOptions.CdvdDumpBlocks = event.IsChecked(); g_Conf->EmuOptions.CdvdDumpBlocks = event.IsChecked();
if (g_Conf->EmuOptions.CdvdDumpBlocks && SysHasValidState()) if (g_Conf->EmuOptions.CdvdDumpBlocks && SysHasValidState())
@ -499,20 +504,20 @@ void MainEmuFrame::Menu_Debug_CreateBlockdump_Click(wxCommandEvent &event)
AppSaveSettings(); AppSaveSettings();
} }
void MainEmuFrame::Menu_MultitapToggle_Click( wxCommandEvent& ) void MainEmuFrame::Menu_MultitapToggle_Click(wxCommandEvent&)
{ {
g_Conf->EmuOptions.MultitapPort0_Enabled = GetMenuBar()->IsChecked( MenuId_Config_Multitap0Toggle ); g_Conf->EmuOptions.MultitapPort0_Enabled = GetMenuBar()->IsChecked(MenuId_Config_Multitap0Toggle);
g_Conf->EmuOptions.MultitapPort1_Enabled = GetMenuBar()->IsChecked( MenuId_Config_Multitap1Toggle ); g_Conf->EmuOptions.MultitapPort1_Enabled = GetMenuBar()->IsChecked(MenuId_Config_Multitap1Toggle);
AppApplySettings(); AppApplySettings();
AppSaveSettings(); AppSaveSettings();
//evt.Skip(); //evt.Skip();
} }
void MainEmuFrame::Menu_EnableBackupStates_Click( wxCommandEvent& ) void MainEmuFrame::Menu_EnableBackupStates_Click(wxCommandEvent&)
{ {
g_Conf->EmuOptions.BackupSavestate = GetMenuBar()->IsChecked( MenuId_EnableBackupStates ); g_Conf->EmuOptions.BackupSavestate = GetMenuBar()->IsChecked(MenuId_EnableBackupStates);
//without the next line, after toggling this menu-checkbox, the change only applies from the 2nd save and onwards //without the next line, after toggling this menu-checkbox, the change only applies from the 2nd save and onwards
// (1st save after the toggle keeps the old pre-toggle value).. // (1st save after the toggle keeps the old pre-toggle value)..
// wonder what that means for all the other menu checkboxes which only use AppSaveSettings... (avih) // wonder what that means for all the other menu checkboxes which only use AppSaveSettings... (avih)
@ -520,30 +525,30 @@ void MainEmuFrame::Menu_EnableBackupStates_Click( wxCommandEvent& )
AppSaveSettings(); AppSaveSettings();
} }
void MainEmuFrame::Menu_EnablePatches_Click( wxCommandEvent& ) void MainEmuFrame::Menu_EnablePatches_Click(wxCommandEvent&)
{ {
g_Conf->EmuOptions.EnablePatches = GetMenuBar()->IsChecked( MenuId_EnablePatches ); g_Conf->EmuOptions.EnablePatches = GetMenuBar()->IsChecked(MenuId_EnablePatches);
AppApplySettings(); AppApplySettings();
AppSaveSettings(); AppSaveSettings();
} }
void MainEmuFrame::Menu_EnableCheats_Click( wxCommandEvent& ) void MainEmuFrame::Menu_EnableCheats_Click(wxCommandEvent&)
{ {
g_Conf->EmuOptions.EnableCheats = GetMenuBar()->IsChecked( MenuId_EnableCheats ); g_Conf->EmuOptions.EnableCheats = GetMenuBar()->IsChecked(MenuId_EnableCheats);
AppApplySettings(); AppApplySettings();
AppSaveSettings(); AppSaveSettings();
} }
void MainEmuFrame::Menu_EnableIPC_Click( wxCommandEvent& ) void MainEmuFrame::Menu_EnableIPC_Click(wxCommandEvent&)
{ {
g_Conf->EmuOptions.EnableIPC = GetMenuBar()->IsChecked( MenuId_EnableIPC ); g_Conf->EmuOptions.EnableIPC = GetMenuBar()->IsChecked(MenuId_EnableIPC);
AppApplySettings(); AppApplySettings();
AppSaveSettings(); AppSaveSettings();
} }
void MainEmuFrame::Menu_EnableWideScreenPatches_Click( wxCommandEvent& ) void MainEmuFrame::Menu_EnableWideScreenPatches_Click(wxCommandEvent&)
{ {
g_Conf->EmuOptions.EnableWideScreenPatches = GetMenuBar()->IsChecked( MenuId_EnableWideScreenPatches ); g_Conf->EmuOptions.EnableWideScreenPatches = GetMenuBar()->IsChecked(MenuId_EnableWideScreenPatches);
AppApplySettings(); AppApplySettings();
AppSaveSettings(); AppSaveSettings();
} }
@ -556,8 +561,9 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent& event)
if (checked) if (checked)
{ {
if (!Msgbox::OkCancel(_("Please be aware that PCSX2's input recording features are still very much a work-in-progress.\n" if (!Msgbox::OkCancel(_("Please be aware that PCSX2's input recording features are still very much a work-in-progress.\n"
"As a result, there may be unforeseen bugs, performance implications and instability with certain games.\n\n" "As a result, there may be unforeseen bugs, performance implications and instability with certain games.\n\n"
"These tools are provided as-is and should be enabled under your own discretion."), "Enabling Input Recording")) "These tools are provided as-is and should be enabled under your own discretion."),
"Enabling Input Recording"))
{ {
checked = false; checked = false;
m_GameSettingsSubmenu.FindChildItem(MenuId_EnableInputRecording)->Check(false); m_GameSettingsSubmenu.FindChildItem(MenuId_EnableInputRecording)->Check(false);
@ -608,46 +614,46 @@ void MainEmuFrame::Menu_EnableRecordingTools_Click(wxCommandEvent& event)
} }
#endif #endif
void MainEmuFrame::Menu_EnableHostFs_Click( wxCommandEvent& ) void MainEmuFrame::Menu_EnableHostFs_Click(wxCommandEvent&)
{ {
g_Conf->EmuOptions.HostFs = GetMenuBar()->IsChecked( MenuId_EnableHostFs ); g_Conf->EmuOptions.HostFs = GetMenuBar()->IsChecked(MenuId_EnableHostFs);
AppSaveSettings(); AppSaveSettings();
} }
void MainEmuFrame::Menu_OpenELF_Click(wxCommandEvent&) void MainEmuFrame::Menu_OpenELF_Click(wxCommandEvent&)
{ {
ScopedCoreThreadClose stopped_core; ScopedCoreThreadClose stopped_core;
if( _DoSelectELFBrowser() ) if (_DoSelectELFBrowser())
{ {
g_Conf->EmuOptions.UseBOOT2Injection = true; g_Conf->EmuOptions.UseBOOT2Injection = true;
sApp.SysExecute( g_Conf->CdvdSource, g_Conf->CurrentELF ); sApp.SysExecute(g_Conf->CdvdSource, g_Conf->CurrentELF);
} }
stopped_core.AllowResume(); stopped_core.AllowResume();
} }
void MainEmuFrame::Menu_LoadStates_Click(wxCommandEvent &event) void MainEmuFrame::Menu_LoadStates_Click(wxCommandEvent& event)
{ {
if( event.GetId() == MenuId_State_LoadBackup ) if (event.GetId() == MenuId_State_LoadBackup)
{ {
States_DefrostCurrentSlotBackup(); States_DefrostCurrentSlotBackup();
return; return;
} }
States_SetCurrentSlot( event.GetId() - MenuId_State_Load01 - 1 ); States_SetCurrentSlot(event.GetId() - MenuId_State_Load01 - 1);
States_DefrostCurrentSlot(); States_DefrostCurrentSlot();
} }
void MainEmuFrame::Menu_SaveStates_Click(wxCommandEvent &event) void MainEmuFrame::Menu_SaveStates_Click(wxCommandEvent& event)
{ {
States_SetCurrentSlot( event.GetId() - MenuId_State_Save01 - 1 ); States_SetCurrentSlot(event.GetId() - MenuId_State_Save01 - 1);
States_FreezeCurrentSlot(); States_FreezeCurrentSlot();
} }
void MainEmuFrame::Menu_LoadStateFromFile_Click(wxCommandEvent &event) void MainEmuFrame::Menu_LoadStateFromFile_Click(wxCommandEvent& event)
{ {
wxFileDialog loadStateDialog(this, _("Load State"), L"", L"", wxFileDialog loadStateDialog(this, _("Load State"), L"", L"",
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN); L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
if (loadStateDialog.ShowModal() == wxID_CANCEL) if (loadStateDialog.ShowModal() == wxID_CANCEL)
{ {
@ -658,10 +664,10 @@ void MainEmuFrame::Menu_LoadStateFromFile_Click(wxCommandEvent &event)
StateCopy_LoadFromFile(path); StateCopy_LoadFromFile(path);
} }
void MainEmuFrame::Menu_SaveStateToFile_Click(wxCommandEvent &event) void MainEmuFrame::Menu_SaveStateToFile_Click(wxCommandEvent& event)
{ {
wxFileDialog saveStateDialog(this, _("Save State"), L"", L"", wxFileDialog saveStateDialog(this, _("Save State"), L"", L"",
L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN); L"Savestate files (*.p2s)|*.p2s", wxFD_OPEN);
if (saveStateDialog.ShowModal() == wxID_CANCEL) if (saveStateDialog.ShowModal() == wxID_CANCEL)
{ {
@ -672,7 +678,7 @@ void MainEmuFrame::Menu_SaveStateToFile_Click(wxCommandEvent &event)
StateCopy_SaveToFile(path); StateCopy_SaveToFile(path);
} }
void MainEmuFrame::Menu_Exit_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Exit_Click(wxCommandEvent& event)
{ {
Close(); Close();
} }
@ -687,26 +693,27 @@ public:
protected: protected:
void InvokeEvent() void InvokeEvent()
{ {
if( CoreThread.IsOpen() ) if (CoreThread.IsOpen())
CoreThread.Suspend(); CoreThread.Suspend();
else else
CoreThread.Resume(); CoreThread.Resume();
} }
}; };
void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent &event) void MainEmuFrame::Menu_SuspendResume_Click(wxCommandEvent& event)
{ {
if( !SysHasValidState() ) return; if (!SysHasValidState())
return;
// Disable the menu item. The state of the menu is indeterminate until the core thread // Disable the menu item. The state of the menu is indeterminate until the core thread
// has responded (it updates status after the plugins are loaded and emulation has // has responded (it updates status after the plugins are loaded and emulation has
// engaged successfully). // engaged successfully).
EnableMenuItem( MenuId_Sys_SuspendResume, false ); EnableMenuItem(MenuId_Sys_SuspendResume, false);
GetSysExecutorThread().PostEvent( new SysExecEvent_ToggleSuspend() ); GetSysExecutorThread().PostEvent(new SysExecEvent_ToggleSuspend());
} }
void MainEmuFrame::Menu_SysShutdown_Click(wxCommandEvent &event) void MainEmuFrame::Menu_SysShutdown_Click(wxCommandEvent& event)
{ {
UI_DisableSysShutdown(); UI_DisableSysShutdown();
Console.SetTitle("PCSX2 Program Log"); Console.SetTitle("PCSX2 Program Log");
@ -737,8 +744,8 @@ void MainEmuFrame::Menu_ConfigPlugin_Click(wxCommandEvent& event)
// However, since the PAD plugin is used to do so, if it's closed then there is nothing to read // However, since the PAD plugin is used to do so, if it's closed then there is nothing to read
// the keybind resulting producing an unrecovable state. // the keybind resulting producing an unrecovable state.
// //
// If the CoreThread is paused prior to opening the PAD plugin settings then when the settings // If the CoreThread is paused prior to opening the PAD plugin settings then when the settings
// are closed the PAD will not re-open. To avoid this, we resume emulation prior to the plugins // are closed the PAD will not re-open. To avoid this, we resume emulation prior to the plugins
// configuration handler doing so. // configuration handler doing so.
if (g_Conf->EmuOptions.EnableRecordingTools && g_InputRecordingControls.IsPaused()) if (g_Conf->EmuOptions.EnableRecordingTools && g_InputRecordingControls.IsPaused())
{ {
@ -756,7 +763,7 @@ void MainEmuFrame::Menu_ConfigPlugin_Click(wxCommandEvent& event)
#endif #endif
} }
void MainEmuFrame::Menu_Debug_Open_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Debug_Open_Click(wxCommandEvent& event)
{ {
DisassemblyDialog* dlg = wxGetApp().GetDisassemblyPtr(); DisassemblyDialog* dlg = wxGetApp().GetDisassemblyPtr();
if (dlg) if (dlg)
@ -768,61 +775,61 @@ void MainEmuFrame::Menu_Debug_Open_Click(wxCommandEvent &event)
} }
} }
void MainEmuFrame::Menu_Debug_MemoryDump_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Debug_MemoryDump_Click(wxCommandEvent& event)
{ {
} }
void MainEmuFrame::Menu_ShowConsole(wxCommandEvent &event) void MainEmuFrame::Menu_ShowConsole(wxCommandEvent& event)
{ {
// Use messages to relay open/close commands (thread-safe) // Use messages to relay open/close commands (thread-safe)
g_Conf->ProgLogBox.Visible = event.IsChecked(); g_Conf->ProgLogBox.Visible = event.IsChecked();
wxCommandEvent evt( wxEVT_MENU, g_Conf->ProgLogBox.Visible ? wxID_OPEN : wxID_CLOSE ); wxCommandEvent evt(wxEVT_MENU, g_Conf->ProgLogBox.Visible ? wxID_OPEN : wxID_CLOSE);
wxGetApp().ProgramLog_PostEvent( evt ); wxGetApp().ProgramLog_PostEvent(evt);
} }
void MainEmuFrame::Menu_ShowConsole_Stdio(wxCommandEvent &event) void MainEmuFrame::Menu_ShowConsole_Stdio(wxCommandEvent& event)
{ {
g_Conf->EmuOptions.ConsoleToStdio = GetMenuBar()->IsChecked( MenuId_Console_Stdio ); g_Conf->EmuOptions.ConsoleToStdio = GetMenuBar()->IsChecked(MenuId_Console_Stdio);
AppSaveSettings(); AppSaveSettings();
} }
void MainEmuFrame::Menu_GetStarted(wxCommandEvent &event) void MainEmuFrame::Menu_GetStarted(wxCommandEvent& event)
{ {
wxLaunchDefaultBrowser("https://pcsx2.net/getting-started.html"); wxLaunchDefaultBrowser("https://pcsx2.net/getting-started.html");
} }
void MainEmuFrame::Menu_Compatibility(wxCommandEvent &event) void MainEmuFrame::Menu_Compatibility(wxCommandEvent& event)
{ {
wxLaunchDefaultBrowser("https://pcsx2.net/compatibility-list.html"); wxLaunchDefaultBrowser("https://pcsx2.net/compatibility-list.html");
} }
void MainEmuFrame::Menu_Forums(wxCommandEvent &event) void MainEmuFrame::Menu_Forums(wxCommandEvent& event)
{ {
wxLaunchDefaultBrowser("https://forums.pcsx2.net/"); wxLaunchDefaultBrowser("https://forums.pcsx2.net/");
} }
void MainEmuFrame::Menu_Website(wxCommandEvent &event) void MainEmuFrame::Menu_Website(wxCommandEvent& event)
{ {
wxLaunchDefaultBrowser("https://pcsx2.net/"); wxLaunchDefaultBrowser("https://pcsx2.net/");
} }
void MainEmuFrame::Menu_Github(wxCommandEvent &event) void MainEmuFrame::Menu_Github(wxCommandEvent& event)
{ {
wxLaunchDefaultBrowser("https://github.com/PCSX2/pcsx2"); wxLaunchDefaultBrowser("https://github.com/PCSX2/pcsx2");
} }
void MainEmuFrame::Menu_Wiki(wxCommandEvent &event) void MainEmuFrame::Menu_Wiki(wxCommandEvent& event)
{ {
wxLaunchDefaultBrowser("https://wiki.pcsx2.net/Main_Page"); wxLaunchDefaultBrowser("https://wiki.pcsx2.net/Main_Page");
} }
void MainEmuFrame::Menu_ShowAboutBox(wxCommandEvent &event) void MainEmuFrame::Menu_ShowAboutBox(wxCommandEvent& event)
{ {
AppOpenDialog<AboutBoxDialog>( this ); AppOpenDialog<AboutBoxDialog>(this);
} }
void MainEmuFrame::Menu_Capture_Video_Record_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Capture_Video_Record_Click(wxCommandEvent& event)
{ {
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
paused_core.AllowResume(); paused_core.AllowResume();
@ -831,7 +838,7 @@ void MainEmuFrame::Menu_Capture_Video_Record_Click(wxCommandEvent &event)
VideoCaptureUpdate(); VideoCaptureUpdate();
} }
void MainEmuFrame::Menu_Capture_Video_Stop_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Capture_Video_Stop_Click(wxCommandEvent& event)
{ {
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
paused_core.AllowResume(); paused_core.AllowResume();
@ -842,7 +849,7 @@ void MainEmuFrame::Menu_Capture_Video_Stop_Click(wxCommandEvent &event)
void MainEmuFrame::VideoCaptureUpdate() void MainEmuFrame::VideoCaptureUpdate()
{ {
GetMTGS().WaitGS(); // make sure GS is in sync with the audio stream when we start. GetMTGS().WaitGS(); // make sure GS is in sync with the audio stream when we start.
if (m_capturingVideo) if (m_capturingVideo)
{ {
// start recording // start recording
@ -879,7 +886,6 @@ void MainEmuFrame::VideoCaptureUpdate()
if (GetMainFramePtr() && needsMainFrameEnable) if (GetMainFramePtr() && needsMainFrameEnable)
GetMainFramePtr()->Enable(); GetMainFramePtr()->Enable();
} }
else else
{ {
@ -901,7 +907,7 @@ void MainEmuFrame::VideoCaptureUpdate()
} }
} }
void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent & event) void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent& event)
{ {
if (!CoreThread.IsOpen()) if (!CoreThread.IsOpen())
{ {
@ -911,7 +917,7 @@ void MainEmuFrame::Menu_Capture_Screenshot_Screenshot_Click(wxCommandEvent & eve
} }
#ifndef DISABLE_RECORDING #ifndef DISABLE_RECORDING
void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent& event)
{ {
const bool initiallyPaused = g_InputRecordingControls.IsPaused(); const bool initiallyPaused = g_InputRecordingControls.IsPaused();
if (!initiallyPaused) if (!initiallyPaused)
@ -937,13 +943,13 @@ void MainEmuFrame::Menu_Recording_New_Click(wxCommandEvent &event)
sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, g_InputRecording.IsActive()); sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, g_InputRecording.IsActive());
} }
void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent& event)
{ {
const bool initiallyPaused = g_InputRecordingControls.IsPaused(); const bool initiallyPaused = g_InputRecordingControls.IsPaused();
if (!initiallyPaused) if (!initiallyPaused)
g_InputRecordingControls.PauseImmediately(); g_InputRecordingControls.PauseImmediately();
wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"", wxFileDialog openFileDialog(this, _("Select P2M2 record file."), L"", L"",
L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN); L"p2m2 file(*.p2m2)|*.p2m2", wxFD_OPEN);
if (openFileDialog.ShowModal() == wxID_CANCEL) if (openFileDialog.ShowModal() == wxID_CANCEL)
{ {
if (!initiallyPaused) if (!initiallyPaused)
@ -969,7 +975,7 @@ void MainEmuFrame::Menu_Recording_Play_Click(wxCommandEvent &event)
sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, g_InputRecording.IsActive()); sMainFrame.enableRecordingMenuItem(MenuId_Recording_ToggleRecordingMode, g_InputRecording.IsActive());
} }
void MainEmuFrame::Menu_Recording_Stop_Click(wxCommandEvent &event) void MainEmuFrame::Menu_Recording_Stop_Click(wxCommandEvent& event)
{ {
g_InputRecording.Stop(); g_InputRecording.Stop();
m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(true); m_menuRecording.FindChildItem(MenuId_Recording_New)->Enable(true);

View File

@ -35,9 +35,9 @@
// Used to hold the current state backup (fullcopy of PS2 memory and plugin states). // Used to hold the current state backup (fullcopy of PS2 memory and plugin states).
//static VmStateBuffer state_buffer( L"Public Savestate Buffer" ); //static VmStateBuffer state_buffer( L"Public Savestate Buffer" );
static const wxChar* EntryFilename_StateVersion = L"PCSX2 Savestate Version.id"; static const wxChar* EntryFilename_StateVersion = L"PCSX2 Savestate Version.id";
static const wxChar* EntryFilename_Screenshot = L"Screenshot.jpg"; static const wxChar* EntryFilename_Screenshot = L"Screenshot.jpg";
static const wxChar* EntryFilename_InternalStructures = L"PCSX2 Internal Structures.dat"; static const wxChar* EntryFilename_InternalStructures = L"PCSX2 Internal Structures.dat";
// -------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------
@ -51,10 +51,10 @@ protected:
public: public:
virtual ~BaseSavestateEntry() = default; virtual ~BaseSavestateEntry() = default;
virtual wxString GetFilename() const=0; virtual wxString GetFilename() const = 0;
virtual void FreezeIn( pxInputStream& reader ) const=0; virtual void FreezeIn(pxInputStream& reader) const = 0;
virtual void FreezeOut( SaveStateBase& writer ) const=0; virtual void FreezeOut(SaveStateBase& writer) const = 0;
virtual bool IsRequired() const=0; virtual bool IsRequired() const = 0;
}; };
class MemorySavestateEntry : public BaseSavestateEntry class MemorySavestateEntry : public BaseSavestateEntry
@ -64,13 +64,13 @@ protected:
virtual ~MemorySavestateEntry() = default; virtual ~MemorySavestateEntry() = default;
public: public:
virtual void FreezeIn( pxInputStream& reader ) const; virtual void FreezeIn(pxInputStream& reader) const;
virtual void FreezeOut( SaveStateBase& writer ) const; virtual void FreezeOut(SaveStateBase& writer) const;
virtual bool IsRequired() const { return true; } virtual bool IsRequired() const { return true; }
protected: protected:
virtual u8* GetDataPtr() const=0; virtual u8* GetDataPtr() const = 0;
virtual uint GetDataSize() const=0; virtual uint GetDataSize() const = 0;
}; };
class PluginSavestateEntry : public BaseSavestateEntry class PluginSavestateEntry : public BaseSavestateEntry
@ -79,7 +79,7 @@ protected:
PluginsEnum_t m_pid; PluginsEnum_t m_pid;
public: public:
PluginSavestateEntry( PluginsEnum_t pid ) PluginSavestateEntry(PluginsEnum_t pid)
{ {
m_pid = pid; m_pid = pid;
} }
@ -87,8 +87,8 @@ public:
virtual ~PluginSavestateEntry() = default; virtual ~PluginSavestateEntry() = default;
virtual wxString GetFilename() const; virtual wxString GetFilename() const;
virtual void FreezeIn( pxInputStream& reader ) const; virtual void FreezeIn(pxInputStream& reader) const;
virtual void FreezeOut( SaveStateBase& writer ) const; virtual void FreezeOut(SaveStateBase& writer) const;
virtual bool IsRequired() const { return false; } virtual bool IsRequired() const { return false; }
@ -96,43 +96,43 @@ protected:
virtual PluginsEnum_t GetPluginId() const { return m_pid; } virtual PluginsEnum_t GetPluginId() const { return m_pid; }
}; };
void MemorySavestateEntry::FreezeIn( pxInputStream& reader ) const void MemorySavestateEntry::FreezeIn(pxInputStream& reader) const
{ {
const uint entrySize = reader.Length(); const uint entrySize = reader.Length();
const uint expectedSize = GetDataSize(); const uint expectedSize = GetDataSize();
if (entrySize < expectedSize) if (entrySize < expectedSize)
{ {
Console.WriteLn( Color_Yellow, " '%s' is incomplete (expected 0x%x bytes, loading only 0x%x bytes)", Console.WriteLn(Color_Yellow, " '%s' is incomplete (expected 0x%x bytes, loading only 0x%x bytes)",
WX_STR(GetFilename()), expectedSize, entrySize ); WX_STR(GetFilename()), expectedSize, entrySize);
} }
uint copylen = std::min(entrySize, expectedSize); uint copylen = std::min(entrySize, expectedSize);
reader.Read( GetDataPtr(), copylen ); reader.Read(GetDataPtr(), copylen);
} }
void MemorySavestateEntry::FreezeOut( SaveStateBase& writer ) const void MemorySavestateEntry::FreezeOut(SaveStateBase& writer) const
{ {
writer.FreezeMem( GetDataPtr(), GetDataSize() ); writer.FreezeMem(GetDataPtr(), GetDataSize());
} }
wxString PluginSavestateEntry::GetFilename() const wxString PluginSavestateEntry::GetFilename() const
{ {
return pxsFmt( "Plugin %s.dat", tbl_PluginInfo[m_pid].shortname ); return pxsFmt("Plugin %s.dat", tbl_PluginInfo[m_pid].shortname);
} }
void PluginSavestateEntry::FreezeIn( pxInputStream& reader ) const void PluginSavestateEntry::FreezeIn(pxInputStream& reader) const
{ {
GetCorePlugins().FreezeIn( GetPluginId(), reader ); GetCorePlugins().FreezeIn(GetPluginId(), reader);
} }
void PluginSavestateEntry::FreezeOut( SaveStateBase& writer ) const void PluginSavestateEntry::FreezeOut(SaveStateBase& writer) const
{ {
if (uint size = GetCorePlugins().GetFreezeSize( GetPluginId() )) if (uint size = GetCorePlugins().GetFreezeSize(GetPluginId()))
{ {
writer.PrepBlock( size ); writer.PrepBlock(size);
GetCorePlugins().FreezeOut( GetPluginId(), writer.GetBlockPtr() ); GetCorePlugins().FreezeOut(GetPluginId(), writer.GetBlockPtr());
writer.CommitBlock( size ); writer.CommitBlock(size);
} }
} }
@ -150,14 +150,14 @@ class SavestateEntry_EmotionMemory : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_EmotionMemory() = default; virtual ~SavestateEntry_EmotionMemory() = default;
wxString GetFilename() const { return L"eeMemory.bin"; } wxString GetFilename() const { return L"eeMemory.bin"; }
u8* GetDataPtr() const { return eeMem->Main; } u8* GetDataPtr() const { return eeMem->Main; }
uint GetDataSize() const { return sizeof(eeMem->Main); } uint GetDataSize() const { return sizeof(eeMem->Main); }
virtual void FreezeIn( pxInputStream& reader ) const virtual void FreezeIn(pxInputStream& reader) const
{ {
SysClearExecutionCache(); SysClearExecutionCache();
MemorySavestateEntry::FreezeIn( reader ); MemorySavestateEntry::FreezeIn(reader);
} }
}; };
@ -166,9 +166,9 @@ class SavestateEntry_IopMemory : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_IopMemory() = default; virtual ~SavestateEntry_IopMemory() = default;
wxString GetFilename() const { return L"iopMemory.bin"; } wxString GetFilename() const { return L"iopMemory.bin"; }
u8* GetDataPtr() const { return iopMem->Main; } u8* GetDataPtr() const { return iopMem->Main; }
uint GetDataSize() const { return sizeof(iopMem->Main); } uint GetDataSize() const { return sizeof(iopMem->Main); }
}; };
class SavestateEntry_HwRegs : public MemorySavestateEntry class SavestateEntry_HwRegs : public MemorySavestateEntry
@ -176,9 +176,9 @@ class SavestateEntry_HwRegs : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_HwRegs() = default; virtual ~SavestateEntry_HwRegs() = default;
wxString GetFilename() const { return L"eeHwRegs.bin"; } wxString GetFilename() const { return L"eeHwRegs.bin"; }
u8* GetDataPtr() const { return eeHw; } u8* GetDataPtr() const { return eeHw; }
uint GetDataSize() const { return sizeof(eeHw); } uint GetDataSize() const { return sizeof(eeHw); }
}; };
class SavestateEntry_IopHwRegs : public MemorySavestateEntry class SavestateEntry_IopHwRegs : public MemorySavestateEntry
@ -186,9 +186,9 @@ class SavestateEntry_IopHwRegs : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_IopHwRegs() = default; virtual ~SavestateEntry_IopHwRegs() = default;
wxString GetFilename() const { return L"iopHwRegs.bin"; } wxString GetFilename() const { return L"iopHwRegs.bin"; }
u8* GetDataPtr() const { return iopHw; } u8* GetDataPtr() const { return iopHw; }
uint GetDataSize() const { return sizeof(iopHw); } uint GetDataSize() const { return sizeof(iopHw); }
}; };
class SavestateEntry_Scratchpad : public MemorySavestateEntry class SavestateEntry_Scratchpad : public MemorySavestateEntry
@ -196,9 +196,9 @@ class SavestateEntry_Scratchpad : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_Scratchpad() = default; virtual ~SavestateEntry_Scratchpad() = default;
wxString GetFilename() const { return L"Scratchpad.bin"; } wxString GetFilename() const { return L"Scratchpad.bin"; }
u8* GetDataPtr() const { return eeMem->Scratch; } u8* GetDataPtr() const { return eeMem->Scratch; }
uint GetDataSize() const { return sizeof(eeMem->Scratch); } uint GetDataSize() const { return sizeof(eeMem->Scratch); }
}; };
class SavestateEntry_VU0mem : public MemorySavestateEntry class SavestateEntry_VU0mem : public MemorySavestateEntry
@ -206,9 +206,9 @@ class SavestateEntry_VU0mem : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_VU0mem() = default; virtual ~SavestateEntry_VU0mem() = default;
wxString GetFilename() const { return L"vu0Memory.bin"; } wxString GetFilename() const { return L"vu0Memory.bin"; }
u8* GetDataPtr() const { return vuRegs[0].Mem; } u8* GetDataPtr() const { return vuRegs[0].Mem; }
uint GetDataSize() const { return VU0_MEMSIZE; } uint GetDataSize() const { return VU0_MEMSIZE; }
}; };
class SavestateEntry_VU1mem : public MemorySavestateEntry class SavestateEntry_VU1mem : public MemorySavestateEntry
@ -216,9 +216,9 @@ class SavestateEntry_VU1mem : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_VU1mem() = default; virtual ~SavestateEntry_VU1mem() = default;
wxString GetFilename() const { return L"vu1Memory.bin"; } wxString GetFilename() const { return L"vu1Memory.bin"; }
u8* GetDataPtr() const { return vuRegs[1].Mem; } u8* GetDataPtr() const { return vuRegs[1].Mem; }
uint GetDataSize() const { return VU1_MEMSIZE; } uint GetDataSize() const { return VU1_MEMSIZE; }
}; };
class SavestateEntry_VU0prog : public MemorySavestateEntry class SavestateEntry_VU0prog : public MemorySavestateEntry
@ -226,9 +226,9 @@ class SavestateEntry_VU0prog : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_VU0prog() = default; virtual ~SavestateEntry_VU0prog() = default;
wxString GetFilename() const { return L"vu0MicroMem.bin"; } wxString GetFilename() const { return L"vu0MicroMem.bin"; }
u8* GetDataPtr() const { return vuRegs[0].Micro; } u8* GetDataPtr() const { return vuRegs[0].Micro; }
uint GetDataSize() const { return VU0_PROGSIZE; } uint GetDataSize() const { return VU0_PROGSIZE; }
}; };
class SavestateEntry_VU1prog : public MemorySavestateEntry class SavestateEntry_VU1prog : public MemorySavestateEntry
@ -236,9 +236,9 @@ class SavestateEntry_VU1prog : public MemorySavestateEntry
public: public:
virtual ~SavestateEntry_VU1prog() = default; virtual ~SavestateEntry_VU1prog() = default;
wxString GetFilename() const { return L"vu1MicroMem.bin"; } wxString GetFilename() const { return L"vu1MicroMem.bin"; }
u8* GetDataPtr() const { return vuRegs[1].Micro; } u8* GetDataPtr() const { return vuRegs[1].Micro; }
uint GetDataSize() const { return VU1_PROGSIZE; } uint GetDataSize() const { return VU1_PROGSIZE; }
}; };
class SavestateEntry_SPU2 : public BaseSavestateEntry class SavestateEntry_SPU2 : public BaseSavestateEntry
@ -246,20 +246,21 @@ class SavestateEntry_SPU2 : public BaseSavestateEntry
public: public:
virtual ~SavestateEntry_SPU2() = default; virtual ~SavestateEntry_SPU2() = default;
wxString GetFilename() const { return L"SPU2.bin"; } wxString GetFilename() const { return L"SPU2.bin"; }
void FreezeIn( pxInputStream& reader ) const { return SPU2DoFreezeIn(reader); } void FreezeIn(pxInputStream& reader) const { return SPU2DoFreezeIn(reader); }
void FreezeOut( SaveStateBase& writer ) const void FreezeOut(SaveStateBase& writer) const
{ {
int size = 0; int size = 0;
freezeData fP = { 0, NULL }; freezeData fP = {0, NULL};
if(SPU2freeze( FREEZE_SIZE, &fP)==0) { if (SPU2freeze(FREEZE_SIZE, &fP) == 0)
size = fP.size; {
writer.PrepBlock( size ); size = fP.size;
SPU2DoFreezeOut(writer.GetBlockPtr()); writer.PrepBlock(size);
writer.CommitBlock( size ); SPU2DoFreezeOut(writer.GetBlockPtr());
} writer.CommitBlock(size);
return; }
} return;
}
bool IsRequired() const { return true; } bool IsRequired() const { return true; }
}; };
@ -286,11 +287,10 @@ static const std::unique_ptr<BaseSavestateEntry> SavestateEntries[] = {
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU1prog), std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_VU1prog),
std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_SPU2), std::unique_ptr<BaseSavestateEntry>(new SavestateEntry_SPU2),
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_GS )), std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry(PluginId_GS)),
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_PAD )), std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry(PluginId_PAD)),
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_USB )), std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry(PluginId_USB)),
std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry( PluginId_DEV9 )) std::unique_ptr<BaseSavestateEntry>(new PluginSavestateEntry(PluginId_DEV9))};
};
// It's bad mojo to have savestates trying to read and write from the same file at the // It's bad mojo to have savestates trying to read and write from the same file at the
// same time. To prevent that we use this mutex lock, which is used by both the // same time. To prevent that we use this mutex lock, which is used by both the
@ -300,23 +300,23 @@ static const std::unique_ptr<BaseSavestateEntry> SavestateEntries[] = {
// //
static Mutex mtx_CompressToDisk; static Mutex mtx_CompressToDisk;
static void CheckVersion( pxInputStream& thr ) static void CheckVersion(pxInputStream& thr)
{ {
u32 savever; u32 savever;
thr.Read( savever ); thr.Read(savever);
// Major version mismatch. Means we can't load this savestate at all. Support for it // Major version mismatch. Means we can't load this savestate at all. Support for it
// was removed entirely. // was removed entirely.
if( savever > g_SaveVersion ) if (savever > g_SaveVersion)
throw Exception::SaveStateLoadError( thr.GetStreamName() ) throw Exception::SaveStateLoadError(thr.GetStreamName())
.SetDiagMsg(pxsFmt( L"Savestate uses an unsupported or unknown savestate version.\n(PCSX2 ver=%x, state ver=%x)", g_SaveVersion, savever )) .SetDiagMsg(pxsFmt(L"Savestate uses an unsupported or unknown savestate version.\n(PCSX2 ver=%x, state ver=%x)", g_SaveVersion, savever))
.SetUserMsg(_("Cannot load this savestate. The state is an unsupported version.")); .SetUserMsg(_("Cannot load this savestate. The state is an unsupported version."));
// check for a "minor" version incompatibility; which happens if the savestate being loaded is a newer version // check for a "minor" version incompatibility; which happens if the savestate being loaded is a newer version
// than the emulator recognizes. 99% chance that trying to load it will just corrupt emulation or crash. // than the emulator recognizes. 99% chance that trying to load it will just corrupt emulation or crash.
if( (savever >> 16) != (g_SaveVersion >> 16) ) if ((savever >> 16) != (g_SaveVersion >> 16))
throw Exception::SaveStateLoadError( thr.GetStreamName() ) throw Exception::SaveStateLoadError(thr.GetStreamName())
.SetDiagMsg(pxsFmt( L"Savestate uses an unknown savestate version.\n(PCSX2 ver=%x, state ver=%x)", g_SaveVersion, savever )) .SetDiagMsg(pxsFmt(L"Savestate uses an unknown savestate version.\n(PCSX2 ver=%x, state ver=%x)", g_SaveVersion, savever))
.SetUserMsg(_("Cannot load this savestate. The state is an unsupported version.")); .SetUserMsg(_("Cannot load this savestate. The state is an unsupported version."));
}; };
@ -330,14 +330,14 @@ static void CheckVersion( pxInputStream& thr )
class SysExecEvent_DownloadState : public SysExecEvent class SysExecEvent_DownloadState : public SysExecEvent
{ {
protected: protected:
ArchiveEntryList* m_dest_list; ArchiveEntryList* m_dest_list;
public: public:
wxString GetEventName() const { return L"VM_Download"; } wxString GetEventName() const { return L"VM_Download"; }
virtual ~SysExecEvent_DownloadState() = default; virtual ~SysExecEvent_DownloadState() = default;
SysExecEvent_DownloadState* Clone() const { return new SysExecEvent_DownloadState( *this ); } SysExecEvent_DownloadState* Clone() const { return new SysExecEvent_DownloadState(*this); }
SysExecEvent_DownloadState( ArchiveEntryList* dest_list=NULL ) SysExecEvent_DownloadState(ArchiveEntryList* dest_list = NULL)
{ {
m_dest_list = dest_list; m_dest_list = dest_list;
} }
@ -350,29 +350,28 @@ protected:
{ {
ScopedCoreThreadPause paused_core; ScopedCoreThreadPause paused_core;
if( !SysHasValidState() ) if (!SysHasValidState())
throw Exception::RuntimeError() throw Exception::RuntimeError()
.SetDiagMsg(L"SysExecEvent_DownloadState: Cannot freeze/download an invalid VM state!") .SetDiagMsg(L"SysExecEvent_DownloadState: Cannot freeze/download an invalid VM state!")
.SetUserMsg(_("There is no active virtual machine state to download or save." )); .SetUserMsg(_("There is no active virtual machine state to download or save."));
memSavingState saveme( m_dest_list->GetBuffer() ); memSavingState saveme(m_dest_list->GetBuffer());
ArchiveEntry internals( EntryFilename_InternalStructures ); ArchiveEntry internals(EntryFilename_InternalStructures);
internals.SetDataIndex( saveme.GetCurrentPos() ); internals.SetDataIndex(saveme.GetCurrentPos());
saveme.FreezeBios(); saveme.FreezeBios();
saveme.FreezeInternals(); saveme.FreezeInternals();
internals.SetDataSize( saveme.GetCurrentPos() - internals.GetDataIndex() ); internals.SetDataSize(saveme.GetCurrentPos() - internals.GetDataIndex());
m_dest_list->Add( internals ); m_dest_list->Add(internals);
for (uint i=0; i<ArraySize(SavestateEntries); ++i) for (uint i = 0; i < ArraySize(SavestateEntries); ++i)
{ {
uint startpos = saveme.GetCurrentPos(); uint startpos = saveme.GetCurrentPos();
SavestateEntries[i]->FreezeOut( saveme ); SavestateEntries[i]->FreezeOut(saveme);
m_dest_list->Add( ArchiveEntry( SavestateEntries[i]->GetFilename() ) m_dest_list->Add(ArchiveEntry(SavestateEntries[i]->GetFilename())
.SetDataIndex( startpos ) .SetDataIndex(startpos)
.SetDataSize( saveme.GetCurrentPos() - startpos ) .SetDataSize(saveme.GetCurrentPos() - startpos));
);
} }
UI_EnableStateActions(); UI_EnableStateActions();
@ -389,7 +388,7 @@ class VmStateCompressThread : public BaseCompressThread
typedef BaseCompressThread _parent; typedef BaseCompressThread _parent;
protected: protected:
ScopedLock m_lock_Compress; ScopedLock m_lock_Compress;
public: public:
VmStateCompressThread() VmStateCompressThread()
@ -419,24 +418,24 @@ protected:
class SysExecEvent_ZipToDisk : public SysExecEvent class SysExecEvent_ZipToDisk : public SysExecEvent
{ {
protected: protected:
ArchiveEntryList* m_src_list; ArchiveEntryList* m_src_list;
wxString m_filename; wxString m_filename;
public: public:
wxString GetEventName() const { return L"VM_ZipToDisk"; } wxString GetEventName() const { return L"VM_ZipToDisk"; }
virtual ~SysExecEvent_ZipToDisk() = default; virtual ~SysExecEvent_ZipToDisk() = default;
SysExecEvent_ZipToDisk* Clone() const { return new SysExecEvent_ZipToDisk( *this ); } SysExecEvent_ZipToDisk* Clone() const { return new SysExecEvent_ZipToDisk(*this); }
SysExecEvent_ZipToDisk( ArchiveEntryList& srclist, const wxString& filename ) SysExecEvent_ZipToDisk(ArchiveEntryList& srclist, const wxString& filename)
: m_filename( filename ) : m_filename(filename)
{ {
m_src_list = &srclist; m_src_list = &srclist;
} }
SysExecEvent_ZipToDisk( ArchiveEntryList* srclist, const wxString& filename ) SysExecEvent_ZipToDisk(ArchiveEntryList* srclist, const wxString& filename)
: m_filename( filename ) : m_filename(filename)
{ {
m_src_list = srclist; m_src_list = srclist;
} }
@ -450,7 +449,7 @@ protected:
// Provisionals for scoped cleanup, in case of exception: // Provisionals for scoped cleanup, in case of exception:
std::unique_ptr<ArchiveEntryList> elist(m_src_list); std::unique_ptr<ArchiveEntryList> elist(m_src_list);
wxString tempfile( m_filename + L".tmp" ); wxString tempfile(m_filename + L".tmp");
wxFFileOutputStream* woot = new wxFFileOutputStream(tempfile); wxFFileOutputStream* woot = new wxFFileOutputStream(tempfile);
if (!woot->IsOk()) if (!woot->IsOk())
@ -468,8 +467,8 @@ protected:
{ {
wxZipEntry* vent = new wxZipEntry(EntryFilename_StateVersion); wxZipEntry* vent = new wxZipEntry(EntryFilename_StateVersion);
vent->SetMethod( wxZIP_METHOD_STORE ); vent->SetMethod(wxZIP_METHOD_STORE);
gzfp->PutNextEntry( vent ); gzfp->PutNextEntry(vent);
out->Write(g_SaveVersion); out->Write(g_SaveVersion);
gzfp->CloseEntry(); gzfp->CloseEntry();
} }
@ -479,9 +478,9 @@ protected:
if (m_screenshot) if (m_screenshot)
{ {
wxZipEntry* vent = new wxZipEntry(EntryFilename_Screenshot); wxZipEntry* vent = new wxZipEntry(EntryFilename_Screenshot);
vent->SetMethod( wxZIP_METHOD_STORE ); vent->SetMethod(wxZIP_METHOD_STORE);
gzfp->PutNextEntry( vent ); gzfp->PutNextEntry(vent);
m_screenshot->SaveFile( *gzfp, wxBITMAP_TYPE_JPEG ); m_screenshot->SaveFile(*gzfp, wxBITMAP_TYPE_JPEG);
gzfp->CloseEntry(); gzfp->CloseEntry();
} }
@ -511,15 +510,15 @@ protected:
class SysExecEvent_UnzipFromDisk : public SysExecEvent class SysExecEvent_UnzipFromDisk : public SysExecEvent
{ {
protected: protected:
wxString m_filename; wxString m_filename;
public: public:
wxString GetEventName() const { return L"VM_UnzipFromDisk"; } wxString GetEventName() const { return L"VM_UnzipFromDisk"; }
virtual ~SysExecEvent_UnzipFromDisk() = default; virtual ~SysExecEvent_UnzipFromDisk() = default;
SysExecEvent_UnzipFromDisk* Clone() const { return new SysExecEvent_UnzipFromDisk( *this ); } SysExecEvent_UnzipFromDisk* Clone() const { return new SysExecEvent_UnzipFromDisk(*this); }
SysExecEvent_UnzipFromDisk( const wxString& filename ) SysExecEvent_UnzipFromDisk(const wxString& filename)
: m_filename( filename ) : m_filename(filename)
{ {
} }
@ -528,21 +527,21 @@ public:
protected: protected:
void InvokeEvent() void InvokeEvent()
{ {
ScopedLock lock( mtx_CompressToDisk ); ScopedLock lock(mtx_CompressToDisk);
// Ugh. Exception handling made crappy because wxWidgets classes don't support scoped pointers yet. // Ugh. Exception handling made crappy because wxWidgets classes don't support scoped pointers yet.
std::unique_ptr<wxFFileInputStream> woot(new wxFFileInputStream(m_filename)); std::unique_ptr<wxFFileInputStream> woot(new wxFFileInputStream(m_filename));
if (!woot->IsOk()) if (!woot->IsOk())
throw Exception::CannotCreateStream( m_filename ).SetDiagMsg(L"Cannot open file for reading."); throw Exception::CannotCreateStream(m_filename).SetDiagMsg(L"Cannot open file for reading.");
std::unique_ptr<pxInputStream> reader(new pxInputStream(m_filename, new wxZipInputStream(woot.get()))); std::unique_ptr<pxInputStream> reader(new pxInputStream(m_filename, new wxZipInputStream(woot.get())));
woot.release(); woot.release();
if (!reader->IsOk()) if (!reader->IsOk())
{ {
throw Exception::SaveStateLoadError( m_filename ) throw Exception::SaveStateLoadError(m_filename)
.SetDiagMsg( L"Savestate file is not a valid gzip archive." ) .SetDiagMsg(L"Savestate file is not a valid gzip archive.")
.SetUserMsg(_("This savestate cannot be loaded because it is not a valid gzip archive. It may have been created by an older unsupported version of PCSX2, or it may be corrupted.")); .SetUserMsg(_("This savestate cannot be loaded because it is not a valid gzip archive. It may have been created by an older unsupported version of PCSX2, or it may be corrupted."));
} }
@ -557,16 +556,17 @@ protected:
std::unique_ptr<wxZipEntry> foundInternal; std::unique_ptr<wxZipEntry> foundInternal;
std::unique_ptr<wxZipEntry> foundEntry[ArraySize(SavestateEntries)]; std::unique_ptr<wxZipEntry> foundEntry[ArraySize(SavestateEntries)];
while(true) while (true)
{ {
Threading::pxTestCancel(); Threading::pxTestCancel();
std::unique_ptr<wxZipEntry> entry(gzreader->GetNextEntry()); std::unique_ptr<wxZipEntry> entry(gzreader->GetNextEntry());
if (!entry) break; if (!entry)
break;
if (entry->GetName().CmpNoCase(EntryFilename_StateVersion) == 0) if (entry->GetName().CmpNoCase(EntryFilename_StateVersion) == 0)
{ {
DevCon.WriteLn( Color_Green, L" ... found '%s'", EntryFilename_StateVersion); DevCon.WriteLn(Color_Green, L" ... found '%s'", EntryFilename_StateVersion);
foundVersion = true; foundVersion = true;
CheckVersion(*reader); CheckVersion(*reader);
continue; continue;
@ -574,7 +574,7 @@ protected:
if (entry->GetName().CmpNoCase(EntryFilename_InternalStructures) == 0) if (entry->GetName().CmpNoCase(EntryFilename_InternalStructures) == 0)
{ {
DevCon.WriteLn( Color_Green, L" ... found '%s'", EntryFilename_InternalStructures); DevCon.WriteLn(Color_Green, L" ... found '%s'", EntryFilename_InternalStructures);
foundInternal = std::move(entry); foundInternal = std::move(entry);
continue; continue;
} }
@ -586,11 +586,11 @@ protected:
foundScreenshot = true; foundScreenshot = true;
}*/ }*/
for (uint i=0; i<ArraySize(SavestateEntries); ++i) for (uint i = 0; i < ArraySize(SavestateEntries); ++i)
{ {
if (entry->GetName().CmpNoCase(SavestateEntries[i]->GetFilename()) == 0) if (entry->GetName().CmpNoCase(SavestateEntries[i]->GetFilename()) == 0)
{ {
DevCon.WriteLn( Color_Green, L" ... found '%s'", WX_STR(SavestateEntries[i]->GetFilename()) ); DevCon.WriteLn(Color_Green, L" ... found '%s'", WX_STR(SavestateEntries[i]->GetFilename()));
foundEntry[i] = std::move(entry); foundEntry[i] = std::move(entry);
break; break;
} }
@ -599,28 +599,29 @@ protected:
if (!foundVersion || !foundInternal) if (!foundVersion || !foundInternal)
{ {
throw Exception::SaveStateLoadError( m_filename ) throw Exception::SaveStateLoadError(m_filename)
.SetDiagMsg( pxsFmt(L"Savestate file does not contain '%s'", .SetDiagMsg(pxsFmt(L"Savestate file does not contain '%s'",
!foundVersion ? EntryFilename_StateVersion : EntryFilename_InternalStructures) ) !foundVersion ? EntryFilename_StateVersion : EntryFilename_InternalStructures))
.SetUserMsg(_("This file is not a valid PCSX2 savestate. See the logfile for details.")); .SetUserMsg(_("This file is not a valid PCSX2 savestate. See the logfile for details."));
} }
// Log any parts and pieces that are missing, and then generate an exception. // Log any parts and pieces that are missing, and then generate an exception.
bool throwIt = false; bool throwIt = false;
for (uint i=0; i<ArraySize(SavestateEntries); ++i) for (uint i = 0; i < ArraySize(SavestateEntries); ++i)
{ {
if (foundEntry[i]) continue; if (foundEntry[i])
continue;
if (SavestateEntries[i]->IsRequired()) if (SavestateEntries[i]->IsRequired())
{ {
throwIt = true; throwIt = true;
Console.WriteLn( Color_Red, " ... not found '%s'!", WX_STR(SavestateEntries[i]->GetFilename()) ); Console.WriteLn(Color_Red, " ... not found '%s'!", WX_STR(SavestateEntries[i]->GetFilename()));
} }
} }
if (throwIt) if (throwIt)
throw Exception::SaveStateLoadError( m_filename ) throw Exception::SaveStateLoadError(m_filename)
.SetDiagMsg( L"Savestate cannot be loaded: some required components were not found or are incomplete." ) .SetDiagMsg(L"Savestate cannot be loaded: some required components were not found or are incomplete.")
.SetUserMsg(_("This savestate cannot be loaded due to missing critical components. See the log file for details.")); .SetUserMsg(_("This savestate cannot be loaded due to missing critical components. See the log file for details."));
// We use direct Suspend/Resume control here, since it's desirable that emulation // We use direct Suspend/Resume control here, since it's desirable that emulation
@ -631,25 +632,26 @@ protected:
GetCoreThread().Pause(); GetCoreThread().Pause();
SysClearExecutionCache(); SysClearExecutionCache();
for (uint i=0; i<ArraySize(SavestateEntries); ++i) for (uint i = 0; i < ArraySize(SavestateEntries); ++i)
{ {
if (!foundEntry[i]) continue; if (!foundEntry[i])
continue;
Threading::pxTestCancel(); Threading::pxTestCancel();
gzreader->OpenEntry( *foundEntry[i] ); gzreader->OpenEntry(*foundEntry[i]);
SavestateEntries[i]->FreezeIn( *reader ); SavestateEntries[i]->FreezeIn(*reader);
} }
// Load all the internal data // Load all the internal data
gzreader->OpenEntry( *foundInternal ); gzreader->OpenEntry(*foundInternal);
VmStateBuffer buffer( foundInternal->GetSize(), L"StateBuffer_UnzipFromDisk" ); // start with an 8 meg buffer to avoid frequent reallocation. VmStateBuffer buffer(foundInternal->GetSize(), L"StateBuffer_UnzipFromDisk"); // start with an 8 meg buffer to avoid frequent reallocation.
reader->Read( buffer.GetPtr(), foundInternal->GetSize() ); reader->Read(buffer.GetPtr(), foundInternal->GetSize());
memLoadingState( buffer ).FreezeBios().FreezeInternals(); memLoadingState(buffer).FreezeBios().FreezeInternals();
GetCoreThread().Resume(); // force resume regardless of emulation state earlier. GetCoreThread().Resume(); // force resume regardless of emulation state earlier.
} }
}; };
@ -657,7 +659,7 @@ protected:
// StateCopy Public Interface // StateCopy Public Interface
// ===================================================================================================== // =====================================================================================================
void StateCopy_SaveToFile( const wxString& file ) void StateCopy_SaveToFile(const wxString& file)
{ {
UI_DisableStateActions(); UI_DisableStateActions();
@ -669,52 +671,52 @@ void StateCopy_SaveToFile( const wxString& file )
ziplist.release(); ziplist.release();
} }
void StateCopy_LoadFromFile( const wxString& file ) void StateCopy_LoadFromFile(const wxString& file)
{ {
UI_DisableSysActions(); UI_DisableSysActions();
GetSysExecutorThread().PostEvent(new SysExecEvent_UnzipFromDisk( file )); GetSysExecutorThread().PostEvent(new SysExecEvent_UnzipFromDisk(file));
} }
// Saves recovery state info to the given saveslot, or saves the active emulation state // Saves recovery state info to the given saveslot, or saves the active emulation state
// (if one exists) and no recovery data was found. This is needed because when a recovery // (if one exists) and no recovery data was found. This is needed because when a recovery
// state is made, the emulation state is usually reset so the only persisting state is // state is made, the emulation state is usually reset so the only persisting state is
// the one in the memory save. :) // the one in the memory save. :)
void StateCopy_SaveToSlot( uint num ) void StateCopy_SaveToSlot(uint num)
{ {
const wxString file( SaveStateBase::GetFilename( num ) ); const wxString file(SaveStateBase::GetFilename(num));
// Backup old Savestate if one exists. // Backup old Savestate if one exists.
if( wxFileExists( file ) && EmuConfig.BackupSavestate ) if (wxFileExists(file) && EmuConfig.BackupSavestate)
{ {
const wxString copy( SaveStateBase::GetFilename( num ) + pxsFmt( L".backup") ); const wxString copy(SaveStateBase::GetFilename(num) + pxsFmt(L".backup"));
Console.Indent().WriteLn( Color_StrongGreen, L"Backing up existing state in slot %d.", num); Console.Indent().WriteLn(Color_StrongGreen, L"Backing up existing state in slot %d.", num);
wxRenameFile( file, copy ); wxRenameFile(file, copy);
} }
OSDlog( Color_StrongGreen, true, "Saving savestate to slot %d...", num ); OSDlog(Color_StrongGreen, true, "Saving savestate to slot %d...", num);
Console.Indent().WriteLn( Color_StrongGreen, L"filename: %s", WX_STR(file) ); Console.Indent().WriteLn(Color_StrongGreen, L"filename: %s", WX_STR(file));
StateCopy_SaveToFile( file ); StateCopy_SaveToFile(file);
#ifdef USE_NEW_SAVESLOTS_UI #ifdef USE_NEW_SAVESLOTS_UI
UI_UpdateSysControls(); UI_UpdateSysControls();
#endif #endif
} }
void StateCopy_LoadFromSlot( uint slot, bool isFromBackup ) void StateCopy_LoadFromSlot(uint slot, bool isFromBackup)
{ {
wxString file( SaveStateBase::GetFilename( slot ) + wxString( isFromBackup?L".backup":L"" ) ); wxString file(SaveStateBase::GetFilename(slot) + wxString(isFromBackup ? L".backup" : L""));
if( !wxFileExists( file ) ) if (!wxFileExists(file))
{ {
OSDlog(Color_StrongGreen, true, "Savestate slot %d%s is empty.", slot, isFromBackup ? " (backup)" : ""); OSDlog(Color_StrongGreen, true, "Savestate slot %d%s is empty.", slot, isFromBackup ? " (backup)" : "");
return; return;
} }
OSDlog( Color_StrongGreen, true, "Loading savestate from slot %d...%s", slot, isFromBackup?" (backup)":"" ); OSDlog(Color_StrongGreen, true, "Loading savestate from slot %d...%s", slot, isFromBackup ? " (backup)" : "");
Console.Indent().WriteLn( Color_StrongGreen, L"filename: %s", WX_STR(file) ); Console.Indent().WriteLn(Color_StrongGreen, L"filename: %s", WX_STR(file));
StateCopy_LoadFromFile( file ); StateCopy_LoadFromFile(file);
#ifdef USE_NEW_SAVESLOTS_UI #ifdef USE_NEW_SAVESLOTS_UI
UI_UpdateSysControls(); UI_UpdateSysControls();
#endif #endif