mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-24 23:11:14 +01:00
statesave prep: Change coretiming to index/registration model, instead of storing pointers. This will make it possible to save/load the event queue.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@258 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
9e3747e2f3
commit
6a4d697f5f
@ -39,7 +39,6 @@ struct SCoreStartupParameter
|
|||||||
bool bUseDualCore;
|
bool bUseDualCore;
|
||||||
bool bNTSC;
|
bool bNTSC;
|
||||||
bool bHLEBios;
|
bool bHLEBios;
|
||||||
bool bThrottle;
|
|
||||||
bool bUseFastMem;
|
bool bUseFastMem;
|
||||||
bool bLockThreads;
|
bool bLockThreads;
|
||||||
bool bOptimizeQuantizers;
|
bool bOptimizeQuantizers;
|
||||||
|
@ -15,6 +15,8 @@
|
|||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Thread.h"
|
#include "Thread.h"
|
||||||
#include "PowerPC/PowerPC.h"
|
#include "PowerPC/PowerPC.h"
|
||||||
#include "CoreTiming.h"
|
#include "CoreTiming.h"
|
||||||
@ -24,12 +26,52 @@
|
|||||||
|
|
||||||
namespace CoreTiming
|
namespace CoreTiming
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct EventType
|
||||||
|
{
|
||||||
|
TimedCallback callback;
|
||||||
|
const char *name;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<EventType> event_types;
|
||||||
|
|
||||||
|
struct Event
|
||||||
|
{
|
||||||
|
s64 time;
|
||||||
|
u64 userdata;
|
||||||
|
Event *next;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// STATE_TO_SAVE (how?)
|
||||||
|
Event *first;
|
||||||
|
Event *tsFirst;
|
||||||
|
|
||||||
int downcount, slicelength;
|
int downcount, slicelength;
|
||||||
int maxSliceLength = 20000;
|
int maxSliceLength = 20000;
|
||||||
|
|
||||||
s64 globalTimer;
|
s64 globalTimer;
|
||||||
s64 idledCycles;
|
s64 idledCycles;
|
||||||
|
|
||||||
|
Common::CriticalSection externalEventSection;
|
||||||
|
|
||||||
|
int RegisterEvent(const char *name, TimedCallback callback)
|
||||||
|
{
|
||||||
|
EventType type;
|
||||||
|
type.name = name;
|
||||||
|
type.callback = callback;
|
||||||
|
event_types.push_back(type);
|
||||||
|
return event_types.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnregisterAllEvents()
|
||||||
|
{
|
||||||
|
if (first)
|
||||||
|
PanicAlert("Cannot unregister events with events pending");
|
||||||
|
event_types.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
u64 GetTicks()
|
u64 GetTicks()
|
||||||
{
|
{
|
||||||
return (u64)globalTimer;
|
return (u64)globalTimer;
|
||||||
@ -40,29 +82,14 @@ u64 GetIdleTicks()
|
|||||||
return (u64)idledCycles;
|
return (u64)idledCycles;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Event
|
|
||||||
{
|
|
||||||
TimedCallback callback;
|
|
||||||
Event *next;
|
|
||||||
s64 time;
|
|
||||||
u64 userdata;
|
|
||||||
const char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
Event *first;
|
|
||||||
Event *tsFirst;
|
|
||||||
|
|
||||||
Common::CriticalSection externalEventSection;
|
|
||||||
|
|
||||||
// This is to be called when outside threads, such as the graphics thread, wants to
|
// This is to be called when outside threads, such as the graphics thread, wants to
|
||||||
// schedule things to be executed on the main thread.
|
// schedule things to be executed on the main thread.
|
||||||
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, TimedCallback callback, const char *name, u64 userdata)
|
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata)
|
||||||
{
|
{
|
||||||
externalEventSection.Enter();
|
externalEventSection.Enter();
|
||||||
Event *ne = new Event;
|
Event *ne = new Event;
|
||||||
ne->time = globalTimer + cyclesIntoFuture;
|
ne->time = globalTimer + cyclesIntoFuture;
|
||||||
ne->name = name;
|
ne->type = event_type;
|
||||||
ne->callback = callback;
|
|
||||||
ne->next = tsFirst;
|
ne->next = tsFirst;
|
||||||
ne->userdata = userdata;
|
ne->userdata = userdata;
|
||||||
tsFirst = ne;
|
tsFirst = ne;
|
||||||
@ -125,12 +152,11 @@ void AddEventToQueue(Event *ne)
|
|||||||
// This must be run ONLY from within the cpu thread
|
// This must be run ONLY from within the cpu thread
|
||||||
// cyclesIntoFuture may be VERY inaccurate if called from anything else
|
// cyclesIntoFuture may be VERY inaccurate if called from anything else
|
||||||
// than Advance
|
// than Advance
|
||||||
void ScheduleEvent(int cyclesIntoFuture, TimedCallback callback, const char *name, u64 userdata)
|
void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata)
|
||||||
{
|
{
|
||||||
Event *ne = new Event;
|
Event *ne = new Event;
|
||||||
ne->callback = callback;
|
|
||||||
ne->userdata = userdata;
|
ne->userdata = userdata;
|
||||||
ne->name = name;
|
ne->type = event_type;
|
||||||
ne->time = globalTimer + cyclesIntoFuture;
|
ne->time = globalTimer + cyclesIntoFuture;
|
||||||
|
|
||||||
AddEventToQueue(ne);
|
AddEventToQueue(ne);
|
||||||
@ -144,24 +170,24 @@ void RegisterAdvanceCallback(void (*callback)(int cyclesExecuted))
|
|||||||
advanceCallback = callback;
|
advanceCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsScheduled(TimedCallback callback)
|
bool IsScheduled(int event_type)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (!first)
|
||||||
return false;
|
return false;
|
||||||
Event *e = first;
|
Event *e = first;
|
||||||
while (e) {
|
while (e) {
|
||||||
if (e->callback == callback)
|
if (e->type == event_type)
|
||||||
return true;
|
return true;
|
||||||
e = e->next;
|
e = e->next;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoveEvent(TimedCallback callback)
|
void RemoveEvent(int event_type)
|
||||||
{
|
{
|
||||||
if (!first)
|
if (!first)
|
||||||
return;
|
return;
|
||||||
if (first->callback == callback)
|
if (first->type == event_type)
|
||||||
{
|
{
|
||||||
Event *next = first->next;
|
Event *next = first->next;
|
||||||
delete first;
|
delete first;
|
||||||
@ -173,7 +199,7 @@ void RemoveEvent(TimedCallback callback)
|
|||||||
Event *ptr = prev->next;
|
Event *ptr = prev->next;
|
||||||
while (ptr)
|
while (ptr)
|
||||||
{
|
{
|
||||||
if (ptr->callback == callback)
|
if (ptr->type == event_type)
|
||||||
{
|
{
|
||||||
prev->next = ptr->next;
|
prev->next = ptr->next;
|
||||||
delete ptr;
|
delete ptr;
|
||||||
@ -219,8 +245,7 @@ void Advance()
|
|||||||
// LOG(GEKKO, "[Scheduler] %s (%lld, %lld) ",
|
// LOG(GEKKO, "[Scheduler] %s (%lld, %lld) ",
|
||||||
// first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
|
// first->name ? first->name : "?", (u64)globalTimer, (u64)first->time);
|
||||||
|
|
||||||
first->callback(first->userdata, (int)(globalTimer - first->time));
|
event_types[first->type].callback(first->userdata, (int)(globalTimer - first->time));
|
||||||
|
|
||||||
Event *next = first->next;
|
Event *next = first->next;
|
||||||
delete first;
|
delete first;
|
||||||
first = next;
|
first = next;
|
||||||
|
@ -14,32 +14,49 @@
|
|||||||
|
|
||||||
// Official SVN repository and contact information can be found at
|
// Official SVN repository and contact information can be found at
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _CORETIMING_H
|
#ifndef _CORETIMING_H
|
||||||
#define _CORETIMING_H
|
#define _CORETIMING_H
|
||||||
|
|
||||||
|
// This is a system to schedule events into the emulated machine's future. Time is measured
|
||||||
|
// in main CPU clock cycles.
|
||||||
|
|
||||||
|
// To schedule an event, you first have to register its type. This is where you pass in the
|
||||||
|
// callback. You then schedule events using the type id you get back.
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
namespace CoreTiming
|
namespace CoreTiming
|
||||||
{
|
{
|
||||||
|
|
||||||
enum {
|
|
||||||
SOON = 100
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void (*TimedCallback)(u64 userdata, int cyclesLate);
|
typedef void (*TimedCallback)(u64 userdata, int cyclesLate);
|
||||||
|
|
||||||
u64 GetTicks();
|
u64 GetTicks();
|
||||||
u64 GetIdleTicks();
|
u64 GetIdleTicks();
|
||||||
|
|
||||||
// The int that the callbacks get is how many cycles late it was.
|
// The int that the callbacks get is how many cycles late it was.
|
||||||
// So to schedule a new event on a regular basis:
|
// So to schedule a new event on a regular basis:
|
||||||
// inside callback:
|
// inside callback:
|
||||||
// ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever")
|
// ScheduleEvent(periodInCycles - cyclesLate, callback, "whatever")
|
||||||
void ScheduleEvent(int cyclesIntoFuture, TimedCallback callback, const char *name, u64 userdata=0);
|
|
||||||
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, TimedCallback callback, const char *name, u64 userdata=0);
|
// Returns the event_type identifier.
|
||||||
void RemoveEvent(TimedCallback callback);
|
int RegisterEvent(const char *name, TimedCallback callback);
|
||||||
bool IsScheduled(TimedCallback callback);
|
void UnregisterAllEvents();
|
||||||
|
|
||||||
|
// userdata MAY NOT CONTAIN POINTERS. userdata might get written and reloaded from disk,
|
||||||
|
// when we implement state saves.
|
||||||
|
void ScheduleEvent(int cyclesIntoFuture, int event_type, u64 userdata=0);
|
||||||
|
void ScheduleEvent_Threadsafe(int cyclesIntoFuture, int event_type, u64 userdata=0);
|
||||||
|
|
||||||
|
// We only permit one event of each type in the queue at a time.
|
||||||
|
void RemoveEvent(int event_type);
|
||||||
|
bool IsScheduled(int event_type);
|
||||||
void Advance();
|
void Advance();
|
||||||
|
|
||||||
|
// Pretend that the main CPU has executed enough cycles to reach the next event.
|
||||||
void Idle();
|
void Idle();
|
||||||
|
|
||||||
|
// Clear all pending events. This should ONLY be done on exit.
|
||||||
void Clear();
|
void Clear();
|
||||||
void LogPendingEvents();
|
void LogPendingEvents();
|
||||||
void SetMaximumSlice(int maximumSliceLength);
|
void SetMaximumSlice(int maximumSliceLength);
|
||||||
|
@ -22,7 +22,7 @@ public:
|
|||||||
virtual void setPC(unsigned int /*address*/) {}
|
virtual void setPC(unsigned int /*address*/) {}
|
||||||
virtual void step() {}
|
virtual void step() {}
|
||||||
virtual void runToBreakpoint() {}
|
virtual void runToBreakpoint() {}
|
||||||
virtual void insertBLR(unsigned int address) {}
|
virtual void insertBLR(unsigned int /*address*/) {}
|
||||||
virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;}
|
virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;}
|
||||||
virtual std::string getDescription(unsigned int /*address*/) = 0;
|
virtual std::string getDescription(unsigned int /*address*/) = 0;
|
||||||
};
|
};
|
||||||
|
@ -91,6 +91,7 @@ union UCPClearReg
|
|||||||
UCPClearReg(u16 _hex) {Hex = _hex; }
|
UCPClearReg(u16 _hex) {Hex = _hex; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// STATE_TO_SAVE
|
||||||
// variables
|
// variables
|
||||||
UCPStatusReg m_CPStatusReg;
|
UCPStatusReg m_CPStatusReg;
|
||||||
UCPCtrlReg m_CPCtrlReg;
|
UCPCtrlReg m_CPCtrlReg;
|
||||||
@ -114,6 +115,13 @@ inline void WriteHigh(u32& _reg, u16 highbits) {_reg = (_reg & 0x0000FFFF) | ((u
|
|||||||
inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);}
|
inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);}
|
||||||
inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
|
inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
|
||||||
|
|
||||||
|
int et_UpdateInterrupts;
|
||||||
|
|
||||||
|
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
||||||
|
{
|
||||||
|
UpdateInterrupts();
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
m_CPStatusReg.Hex = 0;
|
m_CPStatusReg.Hex = 0;
|
||||||
@ -132,6 +140,9 @@ void Init()
|
|||||||
fifo.bFF_GPReadEnable = false;
|
fifo.bFF_GPReadEnable = false;
|
||||||
fifo.bFF_GPLinkEnable = false;
|
fifo.bFF_GPLinkEnable = false;
|
||||||
fifo.bFF_BPEnable = false;
|
fifo.bFF_BPEnable = false;
|
||||||
|
|
||||||
|
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
InitializeCriticalSection(&fifo.sync);
|
InitializeCriticalSection(&fifo.sync);
|
||||||
#endif
|
#endif
|
||||||
@ -464,14 +475,9 @@ void UpdateInterrupts()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
|
|
||||||
{
|
|
||||||
UpdateInterrupts();
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateInterruptsFromVideoPlugin()
|
void UpdateInterruptsFromVideoPlugin()
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(0, &UpdateInterrupts_Wrapper, "CP:UI");
|
CoreTiming::ScheduleEvent_Threadsafe(0, et_UpdateInterrupts);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // end of namespace CommandProcessor
|
} // end of namespace CommandProcessor
|
||||||
|
@ -164,6 +164,8 @@ struct ARDMA
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// STATE_TO_SAVE
|
||||||
u8 *g_ARAM = NULL;
|
u8 *g_ARAM = NULL;
|
||||||
DSPState g_dspState;
|
DSPState g_dspState;
|
||||||
AudioDMA g_audioDMA;
|
AudioDMA g_audioDMA;
|
||||||
@ -179,11 +181,19 @@ void WriteARAM(u8 _iValue, u32 _iAddress);
|
|||||||
bool Update_DSP_ReadRegister();
|
bool Update_DSP_ReadRegister();
|
||||||
void Update_DSP_WriteRegister();
|
void Update_DSP_WriteRegister();
|
||||||
|
|
||||||
|
int et_GenerateDSPInterrupt;
|
||||||
|
|
||||||
|
void GenerateDSPInterrupt_Wrapper(u64 userdata, int cyclesLate)
|
||||||
|
{
|
||||||
|
GenerateDSPInterrupt((DSPInterruptType)(userdata&0xFFFF), (bool)((userdata>>16) & 1));
|
||||||
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
g_ARAM = (u8 *)AllocateMemoryPages(ARAM_SIZE);
|
g_ARAM = (u8 *)AllocateMemoryPages(ARAM_SIZE);
|
||||||
g_dspState.DSPControl.Hex = 0;
|
g_dspState.DSPControl.Hex = 0;
|
||||||
g_dspState.DSPControl.DSPHalt = 1;
|
g_dspState.DSPControl.DSPHalt = 1;
|
||||||
|
et_GenerateDSPInterrupt = CoreTiming::RegisterEvent("DSPint", GenerateDSPInterrupt_Wrapper);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown()
|
void Shutdown()
|
||||||
@ -525,16 +535,11 @@ void GenerateDSPInterrupt(DSPInterruptType type, bool _bSet)
|
|||||||
UpdateInterrupts();
|
UpdateInterrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateDSPInterrupt_Wrapper(u64 userdata, int cyclesLate)
|
|
||||||
{
|
|
||||||
GenerateDSPInterrupt((DSPInterruptType)(userdata&0xFFFF), (bool)((userdata>>16) & 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// CALLED FROM DSP PLUGIN, POSSIBLY THREADED
|
// CALLED FROM DSP PLUGIN, POSSIBLY THREADED
|
||||||
void GenerateDSPInterruptFromPlugin(DSPInterruptType type, bool _bSet)
|
void GenerateDSPInterruptFromPlugin(DSPInterruptType type, bool _bSet)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(
|
CoreTiming::ScheduleEvent_Threadsafe(
|
||||||
0, GenerateDSPInterrupt_Wrapper, "DSPInt", type | (_bSet<<16));
|
0, et_GenerateDSPInterrupt, type | (_bSet<<16));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update_ARAM_DMA()
|
void Update_ARAM_DMA()
|
||||||
|
@ -129,11 +129,11 @@ IEXIDevice* EXIDevice_Create(TEXIDevices _EXIDevice)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIDEVICE_MEMORYCARD_A:
|
case EXIDEVICE_MEMORYCARD_A:
|
||||||
return new CEXIMemoryCard("MemoryCardA", Core::GetStartupParameter().m_strMemoryCardA);
|
return new CEXIMemoryCard("MemoryCardA", Core::GetStartupParameter().m_strMemoryCardA, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIDEVICE_MEMORYCARD_B:
|
case EXIDEVICE_MEMORYCARD_B:
|
||||||
return new CEXIMemoryCard("MemoryCardB", Core::GetStartupParameter().m_strMemoryCardB);
|
return new CEXIMemoryCard("MemoryCardB", Core::GetStartupParameter().m_strMemoryCardB, 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case EXIDEVICE_IPL:
|
case EXIDEVICE_IPL:
|
||||||
|
@ -31,9 +31,21 @@
|
|||||||
#define MC_STATUS_PROGRAMEERROR 0x08
|
#define MC_STATUS_PROGRAMEERROR 0x08
|
||||||
#define MC_STATUS_READY 0x01
|
#define MC_STATUS_READY 0x01
|
||||||
|
|
||||||
CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename) :
|
static CEXIMemoryCard *cards[2];
|
||||||
|
|
||||||
|
void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
|
||||||
|
{
|
||||||
|
CEXIMemoryCard *ptr = cards[userdata];
|
||||||
|
ptr->Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
CEXIMemoryCard::CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename, int card_index) :
|
||||||
m_strFilename(_rFilename)
|
m_strFilename(_rFilename)
|
||||||
{
|
{
|
||||||
|
this->card_index = card_index;
|
||||||
|
cards[card_index] = this;
|
||||||
|
et_this_card = CoreTiming::RegisterEvent(_rName.c_str(), FlushCallback);
|
||||||
|
|
||||||
nintendo_card_id = 0x00000010; // 16MBit nintendo card
|
nintendo_card_id = 0x00000010; // 16MBit nintendo card
|
||||||
card_id = 0xc221;
|
card_id = 0xc221;
|
||||||
/* nintendo_card_id = 0x00000510; // 16MBit "bigben" card
|
/* nintendo_card_id = 0x00000510; // 16MBit "bigben" card
|
||||||
@ -85,13 +97,7 @@ void CEXIMemoryCard::Flush()
|
|||||||
}
|
}
|
||||||
fwrite(memory_card_content, memory_card_size, 1, pFile);
|
fwrite(memory_card_content, memory_card_size, 1, pFile);
|
||||||
fclose(pFile);
|
fclose(pFile);
|
||||||
}
|
Core::DisplayMessage(StringFromFormat("Wrote memory card contents to %s", GetFileName().c_str()), 4000);
|
||||||
|
|
||||||
void CEXIMemoryCard::FlushCallback(u64 userdata, int cyclesLate)
|
|
||||||
{
|
|
||||||
CEXIMemoryCard *ptr = reinterpret_cast<CEXIMemoryCard*>(userdata);
|
|
||||||
ptr->Flush();
|
|
||||||
Core::DisplayMessage(StringFromFormat("Wrote memory card contents to %s", ptr->GetFileName().c_str()), 4000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -161,8 +167,8 @@ void CEXIMemoryCard::SetCS(int cs)
|
|||||||
|
|
||||||
// Page written to memory card, not just to buffer - let's schedule a flush 0.5b cycles into the future (1 sec)
|
// Page written to memory card, not just to buffer - let's schedule a flush 0.5b cycles into the future (1 sec)
|
||||||
// But first we unschedule already scheduled flushes - no point in flushing once per page for a large write.
|
// But first we unschedule already scheduled flushes - no point in flushing once per page for a large write.
|
||||||
CoreTiming::RemoveEvent(&CEXIMemoryCard::FlushCallback);
|
CoreTiming::RemoveEvent(et_this_card);
|
||||||
CoreTiming::ScheduleEvent(500000000, &CEXIMemoryCard::FlushCallback, "Memory Card Flush", reinterpret_cast<u64>(this));
|
CoreTiming::ScheduleEvent(500000000, et_this_card, card_index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
class CEXIMemoryCard : public IEXIDevice
|
class CEXIMemoryCard : public IEXIDevice
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename);
|
CEXIMemoryCard(const std::string& _rName, const std::string& _rFilename, int card_index);
|
||||||
virtual ~CEXIMemoryCard();
|
virtual ~CEXIMemoryCard();
|
||||||
void SetCS(int cs);
|
void SetCS(int cs);
|
||||||
void Update();
|
void Update();
|
||||||
@ -58,7 +58,8 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
std::string m_strFilename;
|
std::string m_strFilename;
|
||||||
|
int card_index;
|
||||||
|
int et_this_card;
|
||||||
//! memory card state
|
//! memory card state
|
||||||
|
|
||||||
// STATE_TO_SAVE
|
// STATE_TO_SAVE
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
#include "VideoInterface.h"
|
#include "VideoInterface.h"
|
||||||
#include "WII_IPC.h"
|
#include "WII_IPC.h"
|
||||||
#include "../Plugins/Plugin_Video.h"
|
#include "../Plugins/Plugin_Video.h"
|
||||||
|
#include "../CoreTiming.h"
|
||||||
#include "SystemTimers.h"
|
#include "SystemTimers.h"
|
||||||
#include "../IPC_HLE/WII_IPC_HLE.h"
|
#include "../IPC_HLE/WII_IPC_HLE.h"
|
||||||
|
|
||||||
@ -75,5 +76,7 @@ namespace HW
|
|||||||
WII_IPC_HLE_Interface::Shutdown();
|
WII_IPC_HLE_Interface::Shutdown();
|
||||||
WII_IPCInterface::Shutdown();
|
WII_IPCInterface::Shutdown();
|
||||||
Thunk_Shutdown();
|
Thunk_Shutdown();
|
||||||
|
|
||||||
|
CoreTiming::UnregisterAllEvents();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,21 @@ static u16 g_token = 0;
|
|||||||
static bool g_bSignalTokenInterrupt;
|
static bool g_bSignalTokenInterrupt;
|
||||||
static bool g_bSignalFinishInterrupt;
|
static bool g_bSignalFinishInterrupt;
|
||||||
|
|
||||||
|
int et_SetTokenOnMainThread;
|
||||||
|
int et_SetFinishOnMainThread;
|
||||||
|
|
||||||
void UpdateInterrupts();
|
void UpdateInterrupts();
|
||||||
|
|
||||||
|
void SetToken_OnMainThread(u64 userdata, int cyclesLate);
|
||||||
|
void SetFinish_OnMainThread(u64 userdata, int cyclesLate);
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
g_token = 0;
|
g_token = 0;
|
||||||
g_ctrlReg.Hex = 0;
|
g_ctrlReg.Hex = 0;
|
||||||
|
|
||||||
|
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
|
||||||
|
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Read16(u16& _uReturnValue, const u32 _iAddress)
|
void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||||
@ -164,7 +173,7 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
|||||||
void SetToken(const unsigned __int16 _token, const int _bSetTokenAcknowledge)
|
void SetToken(const unsigned __int16 _token, const int _bSetTokenAcknowledge)
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(
|
CoreTiming::ScheduleEvent_Threadsafe(
|
||||||
0, SetToken_OnMainThread, "SetToken", _token | (_bSetTokenAcknowledge << 16));
|
0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetFinish
|
// SetFinish
|
||||||
@ -172,7 +181,7 @@ void SetToken(const unsigned __int16 _token, const int _bSetTokenAcknowledge)
|
|||||||
void SetFinish()
|
void SetFinish()
|
||||||
{
|
{
|
||||||
CoreTiming::ScheduleEvent_Threadsafe(
|
CoreTiming::ScheduleEvent_Threadsafe(
|
||||||
0, SetFinish_OnMainThread, "SetFinish");
|
0, et_SetFinishOnMainThread);
|
||||||
LOG(PIXELENGINE, "VIDEO Set Finish");
|
LOG(PIXELENGINE, "VIDEO Set Finish");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ namespace SystemTimers
|
|||||||
|
|
||||||
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||||
|
|
||||||
const int ThrottleFrequency = 60;
|
|
||||||
s64 fakeDec;
|
s64 fakeDec;
|
||||||
|
|
||||||
//ratio of TB and Decrementer to clock cycles
|
//ratio of TB and Decrementer to clock cycles
|
||||||
@ -46,6 +45,15 @@ enum {
|
|||||||
TIMER_RATIO = 8
|
TIMER_RATIO = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int et_Dec;
|
||||||
|
int et_VI;
|
||||||
|
int et_SI;
|
||||||
|
int et_AI;
|
||||||
|
int et_AudioFifo;
|
||||||
|
int et_DSP;
|
||||||
|
int et_IPC_HLE;
|
||||||
|
int et_GPU;
|
||||||
|
|
||||||
// These are badly educated guesses
|
// These are badly educated guesses
|
||||||
// Feel free to experiment
|
// Feel free to experiment
|
||||||
int
|
int
|
||||||
@ -58,7 +66,6 @@ int
|
|||||||
// We should obey that instead of arbitrarly checking at 60fps.
|
// We should obey that instead of arbitrarly checking at 60fps.
|
||||||
SI_PERIOD = GetTicksPerSecond() / 60, //once a frame is good for controllers
|
SI_PERIOD = GetTicksPerSecond() / 60, //once a frame is good for controllers
|
||||||
|
|
||||||
// These are the big question marks IMHO :)
|
|
||||||
// This one should simply be determined by the increasing counter in AI.
|
// This one should simply be determined by the increasing counter in AI.
|
||||||
AI_PERIOD = GetTicksPerSecond() / 80,
|
AI_PERIOD = GetTicksPerSecond() / 80,
|
||||||
|
|
||||||
@ -67,7 +74,7 @@ int
|
|||||||
|
|
||||||
// This is completely arbitrary. If we find that we need lower latency, we can just
|
// This is completely arbitrary. If we find that we need lower latency, we can just
|
||||||
// increase this number.
|
// increase this number.
|
||||||
HLE_IPC_PERIOD = GetTicksPerSecond() / 250,
|
IPC_HLE_PERIOD = GetTicksPerSecond() / 250,
|
||||||
|
|
||||||
// This one is also fairly arbitrary. Every N cycles, run the GPU until it starves (in single core mode only).
|
// This one is also fairly arbitrary. Every N cycles, run the GPU until it starves (in single core mode only).
|
||||||
GPU_PERIOD = 10000;
|
GPU_PERIOD = 10000;
|
||||||
@ -87,14 +94,14 @@ void AICallback(u64 userdata, int cyclesLate)
|
|||||||
// Update disk streaming. All that code really needs a revamp, including replacing the codec with the one
|
// Update disk streaming. All that code really needs a revamp, including replacing the codec with the one
|
||||||
// from in_cube.
|
// from in_cube.
|
||||||
AudioInterface::Update();
|
AudioInterface::Update();
|
||||||
CoreTiming::ScheduleEvent(AI_PERIOD-cyclesLate, &AICallback, "AICallback");
|
CoreTiming::ScheduleEvent(AI_PERIOD-cyclesLate, et_AI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPCallback(u64 userdata, int cyclesLate)
|
void DSPCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
// ~1/6th as many cycles as the period PPC-side.
|
// ~1/6th as many cycles as the period PPC-side.
|
||||||
PluginDSP::DSP_Update(DSP_PERIOD / 6);
|
PluginDSP::DSP_Update(DSP_PERIOD / 6);
|
||||||
CoreTiming::ScheduleEvent(DSP_PERIOD-cyclesLate, &DSPCallback, "DSPCallback");
|
CoreTiming::ScheduleEvent(DSP_PERIOD-cyclesLate, et_DSP);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioFifoCallback(u64 userdata, int cyclesLate)
|
void AudioFifoCallback(u64 userdata, int cyclesLate)
|
||||||
@ -102,19 +109,19 @@ void AudioFifoCallback(u64 userdata, int cyclesLate)
|
|||||||
int period = CPU_CORE_CLOCK / (AudioInterface::GetDSPSampleRate() * 4 / 32);
|
int period = CPU_CORE_CLOCK / (AudioInterface::GetDSPSampleRate() * 4 / 32);
|
||||||
DSP::UpdateAudioDMA(); // Push audio to speakers.
|
DSP::UpdateAudioDMA(); // Push audio to speakers.
|
||||||
|
|
||||||
CoreTiming::ScheduleEvent(period - cyclesLate, &AudioFifoCallback, "AudioFifoCallback");
|
CoreTiming::ScheduleEvent(period - cyclesLate, et_AudioFifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
|
void IPC_HLE_UpdateCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
WII_IPC_HLE_Interface::Update();
|
WII_IPC_HLE_Interface::Update();
|
||||||
CoreTiming::ScheduleEvent(HLE_IPC_PERIOD-cyclesLate, &IPC_HLE_UpdateCallback, "IPC_HLE_UpdateCallback");
|
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD-cyclesLate, et_IPC_HLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VICallback(u64 userdata, int cyclesLate)
|
void VICallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
VideoInterface::Update();
|
VideoInterface::Update();
|
||||||
CoreTiming::ScheduleEvent(VI_PERIOD-cyclesLate, &VICallback, "VICallback");
|
CoreTiming::ScheduleEvent(VI_PERIOD-cyclesLate, et_VI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SICallback(u64 userdata, int cyclesLate)
|
void SICallback(u64 userdata, int cyclesLate)
|
||||||
@ -123,7 +130,7 @@ void SICallback(u64 userdata, int cyclesLate)
|
|||||||
PatchEngine_ApplyFramePatches();
|
PatchEngine_ApplyFramePatches();
|
||||||
// OK, do what we are here to do.
|
// OK, do what we are here to do.
|
||||||
SerialInterface::UpdateDevices();
|
SerialInterface::UpdateDevices();
|
||||||
CoreTiming::ScheduleEvent(SI_PERIOD-cyclesLate, &SICallback, "SICallback");
|
CoreTiming::ScheduleEvent(SI_PERIOD-cyclesLate, et_SI);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DecrementerCallback(u64 userdata, int cyclesLate)
|
void DecrementerCallback(u64 userdata, int cyclesLate)
|
||||||
@ -138,8 +145,8 @@ void DecrementerSet()
|
|||||||
{
|
{
|
||||||
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
|
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
|
||||||
fakeDec = decValue*TIMER_RATIO;
|
fakeDec = decValue*TIMER_RATIO;
|
||||||
CoreTiming::RemoveEvent(DecrementerCallback);
|
CoreTiming::RemoveEvent(et_Dec);
|
||||||
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, DecrementerCallback, "DecCallback");
|
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvanceCallback(int cyclesExecuted)
|
void AdvanceCallback(int cyclesExecuted)
|
||||||
@ -151,43 +158,10 @@ void AdvanceCallback(int cyclesExecuted)
|
|||||||
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
|
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunGPUCallback(u64 userdata, int cyclesLate)
|
void GPUCallback(u64 userdata, int cyclesLate)
|
||||||
{
|
{
|
||||||
CommandProcessor::CatchUpGPU();
|
CommandProcessor::CatchUpGPU();
|
||||||
CoreTiming::ScheduleEvent(GPU_PERIOD-cyclesLate, &RunGPUCallback, "RunGPUCallback");
|
CoreTiming::ScheduleEvent(GPU_PERIOD-cyclesLate, et_GPU);
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(ector): improve, by using a more accurate timer
|
|
||||||
// calculate the timing over the past 7 frames
|
|
||||||
// calculating over all time doesn't work : if it's slow for a while, will run like crazy after that
|
|
||||||
// calculating over just 1 frame is too shaky
|
|
||||||
#define HISTORYLENGTH 7
|
|
||||||
int timeHistory[HISTORYLENGTH] = {0,0,0,0,0};
|
|
||||||
|
|
||||||
void Throttle(u64 userdata, int cyclesLate)
|
|
||||||
{
|
|
||||||
if (!Core::GetStartupParameter().bThrottle)
|
|
||||||
return;
|
|
||||||
static Common::Timer timer;
|
|
||||||
|
|
||||||
for (int i=0; i<HISTORYLENGTH-1; i++)
|
|
||||||
timeHistory[i] = timeHistory[i+1];
|
|
||||||
|
|
||||||
int t = (int)timer.GetTimeDifference();
|
|
||||||
//timer.Update();
|
|
||||||
|
|
||||||
if (timeHistory[0] != 0)
|
|
||||||
{
|
|
||||||
const int delta = (int)(1000*(HISTORYLENGTH-1)/ThrottleFrequency);
|
|
||||||
while (t - timeHistory[0] < delta)
|
|
||||||
{
|
|
||||||
// ugh, busy wait
|
|
||||||
Common::SleepCurrentThread(0);
|
|
||||||
t = (int)timer.GetTimeDifference();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timeHistory[HISTORYLENGTH-1] = t;
|
|
||||||
CoreTiming::ScheduleEvent((int)(GetTicksPerSecond()/ThrottleFrequency)-cyclesLate, &Throttle, "Throttle");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
@ -202,7 +176,7 @@ void Init()
|
|||||||
AI_PERIOD = GetTicksPerSecond() / 80;
|
AI_PERIOD = GetTicksPerSecond() / 80;
|
||||||
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||||
|
|
||||||
HLE_IPC_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
IPC_HLE_PERIOD = (int)(GetTicksPerSecond() * 0.003f);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -215,25 +189,28 @@ void Init()
|
|||||||
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f);
|
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f);
|
||||||
}
|
}
|
||||||
Common::Timer::IncreaseResolution();
|
Common::Timer::IncreaseResolution();
|
||||||
memset(timeHistory, 0, sizeof(timeHistory));
|
|
||||||
CoreTiming::Clear();
|
|
||||||
|
|
||||||
CoreTiming::ScheduleEvent((int)(GetTicksPerSecond() / ThrottleFrequency), &Throttle, "Throttle");
|
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
|
||||||
|
et_AI = CoreTiming::RegisterEvent("AICallback", AICallback);
|
||||||
|
et_VI = CoreTiming::RegisterEvent("VICallback", VICallback);
|
||||||
|
et_SI = CoreTiming::RegisterEvent("SICallback", SICallback);
|
||||||
|
et_DSP = CoreTiming::RegisterEvent("DSPCallback", DSPCallback);
|
||||||
|
et_GPU = CoreTiming::RegisterEvent("GPUCallback", GPUCallback);
|
||||||
|
et_AudioFifo = CoreTiming::RegisterEvent("AudioFifoCallback", AudioFifoCallback);
|
||||||
|
et_IPC_HLE = CoreTiming::RegisterEvent("IPC_HLE_UpdateCallback", IPC_HLE_UpdateCallback);
|
||||||
|
|
||||||
CoreTiming::ScheduleEvent(AI_PERIOD, &AICallback, "AICallback");
|
CoreTiming::ScheduleEvent(AI_PERIOD, et_AI);
|
||||||
CoreTiming::ScheduleEvent(VI_PERIOD, &VICallback, "VICallback");
|
CoreTiming::ScheduleEvent(VI_PERIOD, et_VI);
|
||||||
CoreTiming::ScheduleEvent(DSP_PERIOD, &DSPCallback, "DSPCallback");
|
CoreTiming::ScheduleEvent(DSP_PERIOD, et_DSP);
|
||||||
CoreTiming::ScheduleEvent(SI_PERIOD, &SICallback, "SICallback");
|
CoreTiming::ScheduleEvent(SI_PERIOD, et_SI);
|
||||||
CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), &AudioFifoCallback, "AudioFifoCallback");
|
CoreTiming::ScheduleEvent(CPU_CORE_CLOCK / (32000 * 4 / 32), et_AudioFifo);
|
||||||
|
|
||||||
if (!Core::GetStartupParameter().bUseDualCore)
|
if (!Core::GetStartupParameter().bUseDualCore)
|
||||||
CoreTiming::ScheduleEvent(GPU_PERIOD, &RunGPUCallback, "RunGPUCallback");
|
CoreTiming::ScheduleEvent(GPU_PERIOD, et_GPU);
|
||||||
|
|
||||||
if (Core::GetStartupParameter().bWii)
|
if (Core::GetStartupParameter().bWii)
|
||||||
{
|
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||||
CoreTiming::ScheduleEvent(HLE_IPC_PERIOD, &IPC_HLE_UpdateCallback, "IPC_HLE_UpdateCallback");
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreTiming::RegisterAdvanceCallback(&AdvanceCallback);
|
CoreTiming::RegisterAdvanceCallback(&AdvanceCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,4 +220,4 @@ void Shutdown()
|
|||||||
CoreTiming::Clear();
|
CoreTiming::Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace
|
||||||
|
@ -66,7 +66,6 @@ void SConfig::SaveSettings()
|
|||||||
ini.Set("Core", "HLEBios", m_LocalCoreStartupParameter.bHLEBios);
|
ini.Set("Core", "HLEBios", m_LocalCoreStartupParameter.bHLEBios);
|
||||||
ini.Set("Core", "UseDynarec", m_LocalCoreStartupParameter.bUseDynarec);
|
ini.Set("Core", "UseDynarec", m_LocalCoreStartupParameter.bUseDynarec);
|
||||||
ini.Set("Core", "UseDualCore", m_LocalCoreStartupParameter.bUseDualCore);
|
ini.Set("Core", "UseDualCore", m_LocalCoreStartupParameter.bUseDualCore);
|
||||||
ini.Set("Core", "Throttle", m_LocalCoreStartupParameter.bThrottle);
|
|
||||||
ini.Set("Core", "LockThreads", m_LocalCoreStartupParameter.bLockThreads);
|
ini.Set("Core", "LockThreads", m_LocalCoreStartupParameter.bLockThreads);
|
||||||
ini.Set("Core", "DefaultGCM", m_LocalCoreStartupParameter.m_strDefaultGCM);
|
ini.Set("Core", "DefaultGCM", m_LocalCoreStartupParameter.m_strDefaultGCM);
|
||||||
ini.Set("Core", "OptimizeQuantizers", m_LocalCoreStartupParameter.bOptimizeQuantizers);
|
ini.Set("Core", "OptimizeQuantizers", m_LocalCoreStartupParameter.bOptimizeQuantizers);
|
||||||
@ -117,7 +116,6 @@ void SConfig::LoadSettings()
|
|||||||
ini.Get("Core", "HLEBios", &m_LocalCoreStartupParameter.bHLEBios, true);
|
ini.Get("Core", "HLEBios", &m_LocalCoreStartupParameter.bHLEBios, true);
|
||||||
ini.Get("Core", "UseDynarec", &m_LocalCoreStartupParameter.bUseDynarec, true);
|
ini.Get("Core", "UseDynarec", &m_LocalCoreStartupParameter.bUseDynarec, true);
|
||||||
ini.Get("Core", "UseDualCore", &m_LocalCoreStartupParameter.bUseDualCore, false);
|
ini.Get("Core", "UseDualCore", &m_LocalCoreStartupParameter.bUseDualCore, false);
|
||||||
ini.Get("Core", "Throttle", &m_LocalCoreStartupParameter.bThrottle, true);
|
|
||||||
ini.Get("Core", "LockThreads", &m_LocalCoreStartupParameter.bLockThreads, true);
|
ini.Get("Core", "LockThreads", &m_LocalCoreStartupParameter.bLockThreads, true);
|
||||||
ini.Get("Core", "OptimizeQuantizers", &m_LocalCoreStartupParameter.bOptimizeQuantizers, true);
|
ini.Get("Core", "OptimizeQuantizers", &m_LocalCoreStartupParameter.bOptimizeQuantizers, true);
|
||||||
}
|
}
|
||||||
|
@ -94,7 +94,6 @@ EVT_MENU(IDM_BROWSE, CFrame::OnBrowse)
|
|||||||
EVT_MENU(IDM_MEMCARD, CFrame::OnMemcard)
|
EVT_MENU(IDM_MEMCARD, CFrame::OnMemcard)
|
||||||
EVT_MENU(IDM_TOGGLE_FULLSCREEN, CFrame::OnToggleFullscreen)
|
EVT_MENU(IDM_TOGGLE_FULLSCREEN, CFrame::OnToggleFullscreen)
|
||||||
EVT_MENU(IDM_TOGGLE_DUALCORE, CFrame::OnToggleDualCore)
|
EVT_MENU(IDM_TOGGLE_DUALCORE, CFrame::OnToggleDualCore)
|
||||||
EVT_MENU(IDM_TOGGLE_THROTTLE, CFrame::OnToggleThrottle)
|
|
||||||
EVT_MENU(IDM_TOGGLE_TOOLBAR, CFrame::OnToggleToolbar)
|
EVT_MENU(IDM_TOGGLE_TOOLBAR, CFrame::OnToggleToolbar)
|
||||||
EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage)
|
EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage)
|
||||||
END_EVENT_TABLE()
|
END_EVENT_TABLE()
|
||||||
@ -197,8 +196,6 @@ void CFrame::CreateMenu()
|
|||||||
pOptionsMenu->Append(IDM_TOGGLE_FULLSCREEN, _T("&Fullscreen"));
|
pOptionsMenu->Append(IDM_TOGGLE_FULLSCREEN, _T("&Fullscreen"));
|
||||||
pOptionsMenu->AppendCheckItem(IDM_TOGGLE_DUALCORE, _T("&Dual-core (unstable!)"));
|
pOptionsMenu->AppendCheckItem(IDM_TOGGLE_DUALCORE, _T("&Dual-core (unstable!)"));
|
||||||
pOptionsMenu->Check(IDM_TOGGLE_DUALCORE, SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore);
|
pOptionsMenu->Check(IDM_TOGGLE_DUALCORE, SConfig::GetInstance().m_LocalCoreStartupParameter.bUseDualCore);
|
||||||
pOptionsMenu->AppendCheckItem(IDM_TOGGLE_THROTTLE, _T("&Enable throttle"));
|
|
||||||
pOptionsMenu->Check(IDM_TOGGLE_THROTTLE, SConfig::GetInstance().m_LocalCoreStartupParameter.bThrottle);
|
|
||||||
m_pMenuBar->Append(pOptionsMenu, _T("&Options"));
|
m_pMenuBar->Append(pOptionsMenu, _T("&Options"));
|
||||||
|
|
||||||
// misc menu
|
// misc menu
|
||||||
@ -499,12 +496,6 @@ void CFrame::OnToggleDualCore(wxCommandEvent& WXUNUSED (event))
|
|||||||
SConfig::GetInstance().SaveSettings();
|
SConfig::GetInstance().SaveSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFrame::OnToggleThrottle(wxCommandEvent& WXUNUSED (event))
|
|
||||||
{
|
|
||||||
SConfig::GetInstance().m_LocalCoreStartupParameter.bThrottle = !SConfig::GetInstance().m_LocalCoreStartupParameter.bThrottle;
|
|
||||||
SConfig::GetInstance().SaveSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CFrame::OnToggleToolbar(wxCommandEvent& event)
|
void CFrame::OnToggleToolbar(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
wxToolBarBase* toolBar = GetToolBar();
|
wxToolBarBase* toolBar = GetToolBar();
|
||||||
|
@ -34,7 +34,6 @@ enum
|
|||||||
IDM_CONFIG_PAD_PLUGIN,
|
IDM_CONFIG_PAD_PLUGIN,
|
||||||
IDM_TOGGLE_FULLSCREEN,
|
IDM_TOGGLE_FULLSCREEN,
|
||||||
IDM_TOGGLE_DUALCORE,
|
IDM_TOGGLE_DUALCORE,
|
||||||
IDM_TOGGLE_THROTTLE,
|
|
||||||
IDM_TOGGLE_TOOLBAR,
|
IDM_TOGGLE_TOOLBAR,
|
||||||
IDM_NOTIFYMAPLOADED,
|
IDM_NOTIFYMAPLOADED,
|
||||||
IDM_UPDATELOGDISPLAY,
|
IDM_UPDATELOGDISPLAY,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user