- Fixed TimeBase and Decrementer registers so that they are updated only when needed
- Fixed RTC for GC homebrews git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6158 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
8d6f98439e
commit
9e17007c90
|
@ -66,7 +66,7 @@ s64 idledCycles;
|
|||
|
||||
Common::CriticalSection externalEventSection;
|
||||
|
||||
void (*advanceCallback)(int cyclesExecuted);
|
||||
void (*advanceCallback)(int cyclesExecuted) = NULL;
|
||||
|
||||
Event* GetNewEvent()
|
||||
{
|
||||
|
|
|
@ -271,13 +271,10 @@ void CEXIIPL::TransferByte(u8& _uByte)
|
|||
if (m_uPosition == 3)
|
||||
{
|
||||
// Get the time ...
|
||||
// Subtract Wii bias
|
||||
u32 GCTime = CEXIIPL::GetGCTime() - cWiiBias;
|
||||
u8* pGCTime = (u8*)&GCTime;
|
||||
for (int i=0; i<4; i++)
|
||||
{
|
||||
m_RTC[i] = pGCTime[i^3];
|
||||
}
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
*((u32 *)&m_RTC) = Common::swap32(CEXIIPL::GetGCTime() - cWiiBias); // Subtract Wii bias
|
||||
else
|
||||
*((u32 *)&m_RTC) = Common::swap32(CEXIIPL::GetGCTime());
|
||||
|
||||
#if MAX_LOGLEVEL >= INFO_LEVEL
|
||||
|
||||
|
|
|
@ -81,8 +81,10 @@ namespace SystemTimers
|
|||
|
||||
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
|
||||
|
||||
s64 fakeDec;
|
||||
u64 startTimeBaseTicks;
|
||||
u32 fakeDecStartValue;
|
||||
u64 fakeDecStartTicks;
|
||||
u64 fakeTBStartValue;
|
||||
u64 fakeTBStartTicks;
|
||||
|
||||
/*
|
||||
Gamecube MHz
|
||||
|
@ -189,9 +191,6 @@ void SICallback(u64 userdata, int cyclesLate)
|
|||
|
||||
void DecrementerCallback(u64 userdata, int cyclesLate)
|
||||
{
|
||||
// Why is fakeDec too big here?
|
||||
// A: Because it's 64bit (0xffffffffffffffff)...?
|
||||
fakeDec = -1;
|
||||
PowerPC::ppcState.spr[SPR_DEC] = 0xFFFFFFFF;
|
||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
||||
}
|
||||
|
@ -199,23 +198,32 @@ void DecrementerCallback(u64 userdata, int cyclesLate)
|
|||
void DecrementerSet()
|
||||
{
|
||||
u32 decValue = PowerPC::ppcState.spr[SPR_DEC];
|
||||
fakeDec = decValue * TIMER_RATIO;
|
||||
|
||||
CoreTiming::RemoveEvent(et_Dec);
|
||||
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
|
||||
if ((decValue & 0x80000000) == 0)
|
||||
{
|
||||
fakeDecStartTicks = CoreTiming::GetTicks();
|
||||
fakeDecStartValue = decValue;
|
||||
|
||||
CoreTiming::ScheduleEvent(decValue * TIMER_RATIO, et_Dec);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvanceCallback(int cyclesExecuted)
|
||||
u32 GetFakeDecrementer()
|
||||
{
|
||||
if (PowerPC::GetState() != PowerPC::CPU_RUNNING)
|
||||
return;
|
||||
|
||||
fakeDec -= cyclesExecuted;
|
||||
u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO;
|
||||
*(u64*)&TL = timebase_ticks + startTimeBaseTicks; //works since we are little endian and TL comes first :)
|
||||
if (fakeDec >= 0)
|
||||
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
|
||||
return (fakeDecStartValue - (u32)((CoreTiming::GetTicks() - fakeDecStartTicks) / TIMER_RATIO));
|
||||
}
|
||||
|
||||
void TimeBaseSet()
|
||||
{
|
||||
fakeTBStartTicks = CoreTiming::GetTicks();
|
||||
fakeTBStartValue = *((u64 *)&TL);
|
||||
}
|
||||
|
||||
u64 GetFakeTimeBase()
|
||||
{
|
||||
return fakeTBStartValue + ((CoreTiming::GetTicks() - fakeTBStartTicks) / TIMER_RATIO);
|
||||
}
|
||||
|
||||
// For DC watchdog hack
|
||||
void FakeGPWatchdogCallback(u64 userdata, int cyclesLate)
|
||||
|
@ -273,7 +281,11 @@ void Init()
|
|||
|
||||
Common::Timer::IncreaseResolution();
|
||||
// store and convert localtime at boot to timebase ticks
|
||||
startTimeBaseTicks = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
|
||||
fakeTBStartValue = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
|
||||
fakeTBStartTicks = CoreTiming::GetTicks();
|
||||
|
||||
fakeDecStartValue = 0xFFFFFFFF;
|
||||
u64 fakeDecStartTicks = CoreTiming::GetTicks();
|
||||
|
||||
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
|
||||
et_AI = CoreTiming::RegisterEvent("AICallback", AICallback);
|
||||
|
@ -300,8 +312,6 @@ void Init()
|
|||
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bWii)
|
||||
CoreTiming::ScheduleEvent(IPC_HLE_PERIOD, et_IPC_HLE);
|
||||
|
||||
CoreTiming::RegisterAdvanceCallback(&AdvanceCallback);
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
|
|
|
@ -29,6 +29,10 @@ void Shutdown();
|
|||
|
||||
// Notify timing system that somebody wrote to the decrementer
|
||||
void DecrementerSet();
|
||||
u32 GetFakeDecrementer();
|
||||
|
||||
void TimeBaseSet();
|
||||
u64 GetFakeTimeBase();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -263,9 +263,8 @@ void Interpreter::mtsrin(UGeckoInstruction _inst)
|
|||
void Interpreter::mftb(UGeckoInstruction _inst)
|
||||
{
|
||||
int iIndex = (_inst.TBR >> 5) | ((_inst.TBR & 0x1F) << 5);
|
||||
if (iIndex == SPR_TL) m_GPR[_inst.RD] = TL;
|
||||
else if (iIndex == SPR_TU) m_GPR[_inst.RD] = TU;
|
||||
else _dbg_assert_(POWERPC, 0);
|
||||
_dbg_assert_msg_(POWERPC, (iIndex == SPR_TL) || (iIndex == SPR_TU), "Invalid mftb");
|
||||
mfspr(_inst);
|
||||
}
|
||||
|
||||
|
||||
|
@ -279,9 +278,18 @@ void Interpreter::mfspr(UGeckoInstruction _inst)
|
|||
|
||||
switch (iIndex)
|
||||
{
|
||||
//case SPR_DEC:
|
||||
// MessageBox(NULL, "Read from DEC", "????", MB_OK);
|
||||
// break;
|
||||
case SPR_DEC:
|
||||
if ((rSPR(iIndex) & 0x80000000) == 0) // We are still decrementing
|
||||
{
|
||||
rSPR(iIndex) = SystemTimers::GetFakeDecrementer();
|
||||
}
|
||||
break;
|
||||
|
||||
case SPR_TL:
|
||||
case SPR_TU:
|
||||
*((u64 *)&TL) = SystemTimers::GetFakeTimeBase(); //works since we are little endian and TL comes first :)
|
||||
break;
|
||||
|
||||
case SPR_WPAR:
|
||||
{
|
||||
// If wpar_empty ever is false, Paper Mario hangs. Strange.
|
||||
|
@ -318,10 +326,12 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
|
|||
|
||||
case SPR_TL_W:
|
||||
TL = m_GPR[_inst.RD];
|
||||
SystemTimers::TimeBaseSet();
|
||||
break;
|
||||
|
||||
case SPR_TU_W:
|
||||
TU = m_GPR[_inst.RD];
|
||||
SystemTimers::TimeBaseSet();
|
||||
break;
|
||||
|
||||
case SPR_HID0: // HID0
|
||||
|
@ -416,10 +426,7 @@ void Interpreter::mtspr(UGeckoInstruction _inst)
|
|||
PanicAlert("Interesting - Software triggered Decrementer exception");
|
||||
Common::AtomicOr(PowerPC::ppcState.Exceptions, EXCEPTION_DECREMENTER);
|
||||
}
|
||||
else
|
||||
{
|
||||
SystemTimers::DecrementerSet();
|
||||
}
|
||||
SystemTimers::DecrementerSet();
|
||||
break;
|
||||
|
||||
// Page table base etc
|
||||
|
|
|
@ -90,15 +90,11 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||
switch (iIndex)
|
||||
{
|
||||
case SPR_WPAR:
|
||||
Default(inst);
|
||||
return;
|
||||
// case SPR_DEC:
|
||||
//MessageBox(NULL, "Read from DEC", "????", MB_OK);
|
||||
//break;
|
||||
case SPR_DEC:
|
||||
case SPR_TL:
|
||||
case SPR_TU:
|
||||
//CALL((void Jit64::*)&CoreTiming::Advance);
|
||||
// fall through
|
||||
Default(inst);
|
||||
return;
|
||||
default:
|
||||
gpr.Lock(d);
|
||||
gpr.BindToRegister(d, false);
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "../HW/CPU.h"
|
||||
#include "../Core.h"
|
||||
#include "../CoreTiming.h"
|
||||
#include "../HW/SystemTimers.h"
|
||||
|
||||
#include "Interpreter/Interpreter.h"
|
||||
#include "JitCommon/JitBase.h"
|
||||
|
@ -73,7 +74,13 @@ void ExpandCR()
|
|||
|
||||
void DoState(PointerWrap &p)
|
||||
{
|
||||
rSPR(SPR_DEC) = SystemTimers::GetFakeDecrementer();
|
||||
*((u64 *)&TL) = SystemTimers::GetFakeTimeBase(); //works since we are little endian and TL comes first :)
|
||||
|
||||
p.Do(ppcState);
|
||||
|
||||
SystemTimers::DecrementerSet();
|
||||
SystemTimers::TimeBaseSet();
|
||||
}
|
||||
|
||||
void ResetRegisters()
|
||||
|
@ -110,10 +117,12 @@ void ResetRegisters()
|
|||
|
||||
TL = 0;
|
||||
TU = 0;
|
||||
SystemTimers::TimeBaseSet();
|
||||
|
||||
// MSR should be 0x40, but we don't emulate BS1, so it would never be turned off :}
|
||||
ppcState.msr = 0;
|
||||
rDEC = 0xFFFFFFFF;
|
||||
SystemTimers::DecrementerSet();
|
||||
}
|
||||
|
||||
void Init(int cpu_core)
|
||||
|
|
Loading…
Reference in New Issue