Fixed TLB games support for the iCache, games using the TLB Hack should now work as before (fixes issue 1218)

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4492 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
sl1nk3.s 2009-11-01 01:24:30 +00:00
parent 22a0864337
commit 6c0c97cffe
12 changed files with 125 additions and 27 deletions

View File

@ -50,7 +50,6 @@ may be redirected here (for example to Read_U32()).
// Declarations and definitions // Declarations and definitions
// ---------------- // ----------------
namespace Memory namespace Memory
@ -539,6 +538,7 @@ u32 Read_Opcode_JIT(const u32 _Address)
{ {
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 && if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 &&
(_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area
(_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000)
{ {
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address); PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
@ -546,10 +546,15 @@ u32 Read_Opcode_JIT(const u32 _Address)
} }
u8* iCache; u8* iCache;
u32 addr; u32 addr;
if (_Address & JIT_ICACHE_EXRAM_BIT) if (_Address & JIT_ICACHE_VMEM_BIT)
{
iCache = jit.GetBlockCache()->GetICacheVMEM();
addr = _Address & JIT_ICACHE_MASK;
}
else if (_Address & JIT_ICACHE_EXRAM_BIT)
{ {
iCache = jit.GetBlockCache()->GetICacheEx(); iCache = jit.GetBlockCache()->GetICacheEx();
addr = _Address & JIT_ICACHEEX_MASK; addr = _Address & JIT_ICACHEEX_MASK;
} }
else else
{ {
@ -587,6 +592,7 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
{ {
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 && if ((_Address & ~JIT_ICACHE_MASK) != 0x80000000 && (_Address & ~JIT_ICACHE_MASK) != 0x00000000 &&
(_Address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area
(_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000) (_Address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (_Address & ~JIT_ICACHEEX_MASK) != 0x10000000)
{ {
PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address); PanicAlert("iCacheJIT: Reading Opcode from %x. Please report.", _Address);
@ -594,10 +600,15 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
} }
u8* iCache; u8* iCache;
u32 addr; u32 addr;
if (_Address & JIT_ICACHE_EXRAM_BIT) if (_Address & JIT_ICACHE_VMEM_BIT)
{
iCache = jit.GetBlockCache()->GetICacheVMEM();
addr = _Address & JIT_ICACHE_MASK;
}
else if (_Address & JIT_ICACHE_EXRAM_BIT)
{ {
iCache = jit.GetBlockCache()->GetICacheEx(); iCache = jit.GetBlockCache()->GetICacheEx();
addr = _Address & JIT_ICACHEEX_MASK; addr = _Address & JIT_ICACHEEX_MASK;
} }
else else
{ {
@ -624,7 +635,11 @@ u32 Read_Opcode_JIT_LC(const u32 _Address)
void Write_Opcode_JIT(const u32 _Address, const u32 _Value) void Write_Opcode_JIT(const u32 _Address, const u32 _Value)
{ {
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
if (_Address & JIT_ICACHE_EXRAM_BIT) if (_Address & JIT_ICACHE_VMEM_BIT)
{
*(u32*)(jit.GetBlockCache()->GetICacheVMEM() + (_Address & JIT_ICACHE_MASK)) = Common::swap32(_Value);
}
else if (_Address & JIT_ICACHE_EXRAM_BIT)
{ {
*(u32*)(jit.GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value); *(u32*)(jit.GetBlockCache()->GetICacheEx() + (_Address & JIT_ICACHEEX_MASK)) = Common::swap32(_Value);
} }
@ -790,7 +805,7 @@ void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength)
} }
else else
{ {
// (comment for old implementation) : F|RES: rouge squadron and other games use the TLB ... so this cant work // (comment for old implementation) : F|RES: rogue squadron and other games use the TLB ... so this cant work
// fixed implementation: // fixed implementation:
for (u32 i = 0; i < _iLength; i++) for (u32 i = 0; i < _iLength; i++)
@ -894,6 +909,10 @@ u8 *GetPointer(const u32 _Address)
else else
return 0; return 0;
case 0x7E:
case 0x7F:
return (u8*)(((char*)m_pFakeVMEM) + (_Address & RAM_MASK));
case 0xE0: case 0xE0:
if (_Address < (0xE0000000 + L1_CACHE_SIZE)) if (_Address < (0xE0000000 + L1_CACHE_SIZE))
return GetCachePtr() + (_Address & L1_CACHE_MASK); return GetCachePtr() + (_Address & L1_CACHE_MASK);

View File

@ -45,6 +45,7 @@ namespace Interpreter
void UpdateSSEState(); void UpdateSSEState();
// Extremely rare - actually, never seen. // Extremely rare - actually, never seen.
// Star Wars : Rogue Leader spams that at some point :|
void Helper_UpdateCR1(double _fValue) void Helper_UpdateCR1(double _fValue)
{ {
// Should just update exception flags, not do any compares. // Should just update exception flags, not do any compares.

View File

@ -159,6 +159,8 @@ void AsmRoutineManager::Generate()
SetJumpTarget(needinst); SetJumpTarget(needinst);
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
TEST(32, R(EAX), Imm32(JIT_ICACHE_VMEM_BIT));
FixupBranch vmem = J_CC(CC_NZ);
TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT)); TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT));
FixupBranch exram = J_CC(CC_NZ); FixupBranch exram = J_CC(CC_NZ);
@ -179,9 +181,21 @@ void AsmRoutineManager::Generate()
#else #else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheEx())); MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheEx()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0)); MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif #endif
FixupBranch getinst2 = J();
SetJumpTarget(vmem);
AND(32, R(EAX), Imm32(JIT_ICACHE_MASK));
#ifdef _M_IX86
MOV(32, R(EAX), MDisp(EAX, (u32)jit.GetBlockCache()->GetICacheVMEM()));
#else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheVMEM()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif
SetJumpTarget(getinst); SetJumpTarget(getinst);
SetJumpTarget(getinst2);
#else #else
#ifdef _M_IX86 #ifdef _M_IX86
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));

View File

@ -164,6 +164,8 @@ void AsmRoutineManager::Generate()
SetJumpTarget(needinst); SetJumpTarget(needinst);
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
TEST(32, R(EAX), Imm32(JIT_ICACHE_VMEM_BIT));
FixupBranch vmem = J_CC(CC_NZ);
TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT)); TEST(32, R(EAX), Imm32(JIT_ICACHE_EXRAM_BIT));
FixupBranch exram = J_CC(CC_NZ); FixupBranch exram = J_CC(CC_NZ);
@ -184,9 +186,21 @@ void AsmRoutineManager::Generate()
#else #else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheEx())); MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheEx()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0)); MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif #endif
FixupBranch getinst2 = J();
SetJumpTarget(vmem);
AND(32, R(EAX), Imm32(JIT_ICACHE_MASK));
#ifdef _M_IX86
MOV(32, R(EAX), MDisp(EAX, (u32)jit.GetBlockCache()->GetICacheVMEM()));
#else
MOV(64, R(RSI), Imm64((u64)jit.GetBlockCache()->GetICacheVMEM()));
MOV(32, R(EAX), MComplex(RSI, EAX, SCALE_1, 0));
#endif
SetJumpTarget(getinst); SetJumpTarget(getinst);
SetJumpTarget(getinst2);
#else #else
#ifdef _M_IX86 #ifdef _M_IX86
AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK)); AND(32, R(EAX), Imm32(Memory::MEMVIEW32_MASK));

View File

@ -86,21 +86,23 @@ bool JitBlock::ContainsAddress(u32 em_address)
blocks = new JitBlock[MAX_NUM_BLOCKS]; blocks = new JitBlock[MAX_NUM_BLOCKS];
blockCodePointers = new const u8*[MAX_NUM_BLOCKS]; blockCodePointers = new const u8*[MAX_NUM_BLOCKS];
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
if (iCache == 0 && iCacheEx == 0) if (iCache == 0 && iCacheEx == 0 && iCacheVMEM == 0)
{ {
iCache = new u8[JIT_ICACHE_SIZE]; iCache = new u8[JIT_ICACHE_SIZE];
iCacheEx = new u8[JIT_ICACHEEX_SIZE]; iCacheEx = new u8[JIT_ICACHEEX_SIZE];
iCacheVMEM = new u8[JIT_ICACHE_SIZE];
} }
else else
{ {
PanicAlert("JitBlockCache::Init() - iCache is already initialized"); PanicAlert("JitBlockCache::Init() - iCache is already initialized");
} }
if (iCache == 0 || iCacheEx == 0) if (iCache == 0 || iCacheEx == 0 || iCacheVMEM == 0)
{ {
PanicAlert("JitBlockCache::Init() - unable to allocate iCache"); PanicAlert("JitBlockCache::Init() - unable to allocate iCache");
} }
memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE); memset(iCache, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE); memset(iCacheEx, JIT_ICACHE_INVALID_BYTE, JIT_ICACHEEX_SIZE);
memset(iCacheVMEM, JIT_ICACHE_INVALID_BYTE, JIT_ICACHE_SIZE);
#endif #endif
Clear(); Clear();
} }
@ -116,6 +118,9 @@ bool JitBlock::ContainsAddress(u32 em_address)
if (iCacheEx != 0) if (iCacheEx != 0)
delete [] iCacheEx; delete [] iCacheEx;
iCacheEx = 0; iCacheEx = 0;
if (iCacheVMEM != 0)
delete [] iCacheVMEM;
iCacheVMEM = 0;
#endif #endif
blocks = 0; blocks = 0;
blockCodePointers = 0; blockCodePointers = 0;
@ -238,6 +243,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
{ {
return iCacheEx; return iCacheEx;
} }
u8* JitBlockCache::GetICacheVMEM()
{
return iCacheVMEM;
}
#endif #endif
int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr) int JitBlockCache::GetBlockNumberFromStartAddress(u32 addr)
@ -246,7 +256,11 @@ bool JitBlock::ContainsAddress(u32 em_address)
return -1; return -1;
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
u32 inst; u32 inst;
if (addr & JIT_ICACHE_EXRAM_BIT) if (addr & JIT_ICACHE_VMEM_BIT)
{
inst = *(u32*)(iCacheVMEM + (addr & JIT_ICACHE_MASK));
}
else if (addr & JIT_ICACHE_EXRAM_BIT)
{ {
inst = *(u32*)(iCacheEx + (addr & JIT_ICACHEEX_MASK)); inst = *(u32*)(iCacheEx + (addr & JIT_ICACHEEX_MASK));
} }
@ -394,11 +408,17 @@ bool JitBlock::ContainsAddress(u32 em_address)
// invalidate iCache. // invalidate iCache.
// icbi can be called with any address, so we sholud check // icbi can be called with any address, so we sholud check
if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000 && if ((address & ~JIT_ICACHE_MASK) != 0x80000000 && (address & ~JIT_ICACHE_MASK) != 0x00000000 &&
(address & ~JIT_ICACHE_MASK) != 0x7e000000 && // TLB area
(address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (address & ~JIT_ICACHEEX_MASK) != 0x10000000) (address & ~JIT_ICACHEEX_MASK) != 0x90000000 && (address & ~JIT_ICACHEEX_MASK) != 0x10000000)
{ {
return; return;
} }
if (address & JIT_ICACHE_EXRAM_BIT) if (address & JIT_ICACHE_VMEM_BIT)
{
u32 cacheaddr = address & JIT_ICACHE_MASK;
memset(iCacheVMEM + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);
}
else if (address & JIT_ICACHE_EXRAM_BIT)
{ {
u32 cacheaddr = address & JIT_ICACHEEX_MASK; u32 cacheaddr = address & JIT_ICACHEEX_MASK;
memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32); memset(iCacheEx + cacheaddr, JIT_ICACHE_INVALID_BYTE, 32);

View File

@ -37,6 +37,7 @@
#define JIT_ICACHEEX_SIZE 0x4000000 #define JIT_ICACHEEX_SIZE 0x4000000
#define JIT_ICACHEEX_MASK 0x3ffffff #define JIT_ICACHEEX_MASK 0x3ffffff
#define JIT_ICACHE_EXRAM_BIT 0x10000000 #define JIT_ICACHE_EXRAM_BIT 0x10000000
#define JIT_ICACHE_VMEM_BIT 0x20000000
// this corresponds to opcode 5 which is invalid in PowerPC // this corresponds to opcode 5 which is invalid in PowerPC
#define JIT_ICACHE_INVALID_BYTE 0x14 #define JIT_ICACHE_INVALID_BYTE 0x14
#define JIT_ICACHE_INVALID_WORD 0x14141414 #define JIT_ICACHE_INVALID_WORD 0x14141414
@ -89,6 +90,7 @@ class JitBlockCache
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
u8 *iCache; u8 *iCache;
u8 *iCacheEx; u8 *iCacheEx;
u8 *iCacheVMEM;
#endif #endif
int MAX_NUM_BLOCKS; int MAX_NUM_BLOCKS;
@ -116,6 +118,7 @@ public:
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
u8 *GetICache(); u8 *GetICache();
u8 *GetICacheEx(); u8 *GetICacheEx();
u8 *GetICacheVMEM();
#endif #endif
// Fast way to get a block. Only works on the first ppc instruction of a block. // Fast way to get a block. Only works on the first ppc instruction of a block.

View File

@ -72,6 +72,7 @@ namespace PowerPC
#ifdef FAST_ICACHE #ifdef FAST_ICACHE
memset(lookup_table, 0xff, sizeof(lookup_table)); memset(lookup_table, 0xff, sizeof(lookup_table));
memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex)); memset(lookup_table_ex, 0xff, sizeof(lookup_table_ex));
memset(lookup_table_vmem, 0xff, sizeof(lookup_table_vmem));
#endif #endif
} }
@ -85,7 +86,9 @@ namespace PowerPC
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
if (valid[set] & (1<<i)) if (valid[set] & (1<<i))
{ {
if (tags[set][i] & (ICACHE_EXRAM_BIT >> 12)) if (tags[set][i] & (ICACHE_VMEM_BIT >> 12))
lookup_table_vmem[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
else if (tags[set][i] & (ICACHE_EXRAM_BIT >> 12))
lookup_table_ex[((tags[set][i] << 7) | set) & 0x1fffff] = 0xff; lookup_table_ex[((tags[set][i] << 7) | set) & 0x1fffff] = 0xff;
else else
lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff; lookup_table[((tags[set][i] << 7) | set) & 0xfffff] = 0xff;
@ -102,7 +105,11 @@ namespace PowerPC
u32 tag = addr >> 12; u32 tag = addr >> 12;
#ifdef FAST_ICACHE #ifdef FAST_ICACHE
u32 t; u32 t;
if (addr & ICACHE_EXRAM_BIT) if (addr & ICACHE_VMEM_BIT)
{
t = lookup_table_vmem[(addr>>5) & 0xfffff];
}
else if (addr & ICACHE_EXRAM_BIT)
{ {
t = lookup_table_ex[(addr>>5) & 0x1fffff]; t = lookup_table_ex[(addr>>5) & 0x1fffff];
} }
@ -134,12 +141,16 @@ namespace PowerPC
#ifdef FAST_ICACHE #ifdef FAST_ICACHE
if (valid[set] & (1<<t)) if (valid[set] & (1<<t))
{ {
if (tags[set][t] & (ICACHE_EXRAM_BIT >> 12)) if (tags[set][t] & (ICACHE_VMEM_BIT >> 12))
lookup_table_vmem[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
else if (tags[set][t] & (ICACHE_EXRAM_BIT >> 12))
lookup_table_ex[((tags[set][t] << 7) | set) & 0x1fffff] = 0xff; lookup_table_ex[((tags[set][t] << 7) | set) & 0x1fffff] = 0xff;
else else
lookup_table[((tags[set][t] << 7) | set) & 0xfffff] = 0xff; lookup_table[((tags[set][t] << 7) | set) & 0xfffff] = 0xff;
} }
if (addr & ICACHE_EXRAM_BIT) if (addr & ICACHE_VMEM_BIT)
lookup_table_vmem[(addr>>5) & 0xfffff] = t;
else if (addr & ICACHE_EXRAM_BIT)
lookup_table_ex[(addr>>5) & 0x1fffff] = t; lookup_table_ex[(addr>>5) & 0x1fffff] = t;
else else
lookup_table[(addr>>5) & 0xfffff] = t; lookup_table[(addr>>5) & 0xfffff] = t;

View File

@ -31,6 +31,7 @@ namespace PowerPC
const u32 ICACHE_BLOCK_SIZE = 8; const u32 ICACHE_BLOCK_SIZE = 8;
const u32 ICACHE_EXRAM_BIT = 0x10000000; const u32 ICACHE_EXRAM_BIT = 0x10000000;
const u32 ICACHE_VMEM_BIT = 0x20000000;
struct InstructionCache struct InstructionCache
{ {
@ -45,6 +46,7 @@ namespace PowerPC
#ifdef FAST_ICACHE #ifdef FAST_ICACHE
u8 lookup_table[1<<20]; u8 lookup_table[1<<20];
u8 lookup_table_ex[1<<21]; u8 lookup_table_ex[1<<21];
u8 lookup_table_vmem[1<<20];
#endif #endif
InstructionCache(); InstructionCache();

View File

@ -72,7 +72,7 @@ static Common::Thread *saveThread = NULL;
// Don't forget to increase this after doing changes on the savestate system // Don't forget to increase this after doing changes on the savestate system
#define STATE_VERSION 1 #define STATE_VERSION 2
void DoState(PointerWrap &p) void DoState(PointerWrap &p)
@ -81,7 +81,8 @@ void DoState(PointerWrap &p)
p.Do(cookie); p.Do(cookie);
if (cookie != 0xBAADBABE + STATE_VERSION) if (cookie != 0xBAADBABE + STATE_VERSION)
{ {
PanicAlert("Savestate version mismatch !\nSorry, you can't load states from other revisions."); //PanicAlert("Savestate version mismatch !\nSorry, you can't load states from other revisions.");
p.SetMode(PointerWrap::MODE_MEASURE);
return; return;
} }
// Begin with video plugin, so that it gets a chance to clear it's caches and writeback modified things to RAM // Begin with video plugin, so that it gets a chance to clear it's caches and writeback modified things to RAM
@ -97,6 +98,7 @@ void DoState(PointerWrap &p)
#ifdef JIT_UNLIMITED_ICACHE #ifdef JIT_UNLIMITED_ICACHE
p.DoVoid(jit.GetBlockCache()->GetICache(), JIT_ICACHE_SIZE); p.DoVoid(jit.GetBlockCache()->GetICache(), JIT_ICACHE_SIZE);
p.DoVoid(jit.GetBlockCache()->GetICacheEx(), JIT_ICACHEEX_SIZE); p.DoVoid(jit.GetBlockCache()->GetICacheEx(), JIT_ICACHEEX_SIZE);
p.DoVoid(jit.GetBlockCache()->GetICacheVMEM(), JIT_ICACHE_SIZE);
#endif #endif
} }
@ -345,9 +347,13 @@ void LoadStateCallback(u64 userdata, int cyclesLate)
u8 *ptr = buffer; u8 *ptr = buffer;
PointerWrap p(&ptr, PointerWrap::MODE_READ); PointerWrap p(&ptr, PointerWrap::MODE_READ);
DoState(p); DoState(p);
delete [] buffer;
Core::DisplayMessage(StringFromFormat("Loaded state from %s", cur_filename.c_str()).c_str(), 2000); if (p.GetMode() == PointerWrap::MODE_READ)
Core::DisplayMessage(StringFromFormat("Loaded state from %s", cur_filename.c_str()).c_str(), 2000);
else
Core::DisplayMessage("Unable to Load : Can't load state from other revisions !", 4000);
delete [] buffer;
} }
void State_Init() void State_Init()

View File

@ -659,7 +659,10 @@ void CFrame::OnKeyDown(wxKeyEvent& event)
// Toggle fullscreen // Toggle fullscreen
if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == WXK_RETURN && event.GetModifiers() == wxMOD_ALT)) if (event.GetKeyCode() == WXK_ESCAPE || (event.GetKeyCode() == WXK_RETURN && event.GetModifiers() == wxMOD_ALT))
{ {
DoFullscreen(!IsFullScreen()); // If a modal dialog is open, this will still process the keyboard events, and may cause
// the main window to become unresponsive, so we have to avoid that.
if ((bRenderToMain || Core::GetState() != Core::CORE_RUN) && !m_bModalDialogOpen)
DoFullscreen(!IsFullScreen());
// We do that to avoid the event to be double processed (which would cause the window to be stuck in fullscreen) // We do that to avoid the event to be double processed (which would cause the window to be stuck in fullscreen)
event.StopPropagation(); event.StopPropagation();
@ -832,9 +835,7 @@ wxAuiNotebook* CFrame::CreateEmptyNotebook()
void CFrame::DoFullscreen(bool bF) void CFrame::DoFullscreen(bool bF)
{ {
// Only switch this to fullscreen if we're rendering to main OR if we're not running a game // Only switch this to fullscreen if we're rendering to main OR if we're not running a game
// AND if this is the active window, as it could cause the main window to become unresponsive if (bRenderToMain || Core::GetState() != Core::CORE_RUN)
// if we're switching to fullscreen while a modal dialog is open
if ((bRenderToMain || Core::GetState() != Core::CORE_RUN) && this->IsActive())
{ {
ShowFullScreen(bF); ShowFullScreen(bF);

View File

@ -194,6 +194,7 @@ class CFrame : public wxFrame
bool m_bEdit; bool m_bEdit;
bool m_bTabSplit; bool m_bTabSplit;
bool m_bNoDocking; bool m_bNoDocking;
bool m_bModalDialogOpen;
char **drives; char **drives;

View File

@ -665,9 +665,11 @@ void CFrame::OnReset(wxCommandEvent& WXUNUSED (event))
void CFrame::OnConfigMain(wxCommandEvent& WXUNUSED (event)) void CFrame::OnConfigMain(wxCommandEvent& WXUNUSED (event))
{ {
m_bModalDialogOpen = true;
CConfigMain ConfigMain(this); CConfigMain ConfigMain(this);
if (ConfigMain.ShowModal() == wxID_OK) if (ConfigMain.ShowModal() == wxID_OK)
m_GameListCtrl->Update(); m_GameListCtrl->Update();
m_bModalDialogOpen = false;
} }
void CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event)) void CFrame::OnPluginGFX(wxCommandEvent& WXUNUSED (event))
@ -712,8 +714,10 @@ void CFrame::OnHelp(wxCommandEvent& event)
{ {
case IDM_HELPABOUT: case IDM_HELPABOUT:
{ {
AboutDolphin frame(this); m_bModalDialogOpen = true;
frame.ShowModal(); AboutDolphin frame(this);
frame.ShowModal();
m_bModalDialogOpen = false;
break; break;
} }
case IDM_HELPWEBSITE: case IDM_HELPWEBSITE:
@ -756,8 +760,10 @@ void CFrame::OnNetPlay(wxCommandEvent& WXUNUSED (event))
void CFrame::OnMemcard(wxCommandEvent& WXUNUSED (event)) void CFrame::OnMemcard(wxCommandEvent& WXUNUSED (event))
{ {
m_bModalDialogOpen = true;
CMemcardManager MemcardManager(this); CMemcardManager MemcardManager(this);
MemcardManager.ShowModal(); MemcardManager.ShowModal();
m_bModalDialogOpen = false;
} }
void CFrame::OnShow_CheatsWindow(wxCommandEvent& WXUNUSED (event)) void CFrame::OnShow_CheatsWindow(wxCommandEvent& WXUNUSED (event))