Fix time in some games (AC and ZWW at least). Many games doesn't use RTC but TBRs. So a TB offset is initialized at boot with localtime now. There are, indeed, side effects since time is CPU cycle dependent in this case.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1519 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
memberTwo.mb2 2008-12-13 11:57:01 +00:00
parent d1712f15ca
commit 82cd659638
5 changed files with 31 additions and 4 deletions

View file

@ -96,4 +96,17 @@ u64 Timer::GetTimeSinceJan1970(void)
time(&ltime);
return((u64)ltime);
}
u64 Timer::GetLocalTimeSinceJan1970(void)
{
time_t sysTime, tzDiff;
struct tm * gmTime;
time(&sysTime);
// Lazy way to get local time in sec
gmTime = gmtime(&sysTime);
tzDiff = sysTime - mktime(gmTime);
return (u64)(sysTime + tzDiff);
}
} // end of namespace Common

View file

@ -37,6 +37,7 @@ class Timer
static void IncreaseResolution();
static void RestoreResolution();
static u64 GetTimeSinceJan1970();
static u64 GetLocalTimeSinceJan1970();
public:

View file

@ -161,13 +161,14 @@ void CBoot::EmulatedBIOS(bool _bDebug)
// Bus Clock Speed
Memory::Write_U32(0x09a7ec80, 0x800000F8);
// CPU Clock Speed
Memory::Write_U32(0x1cf7c580, 0x800000FC);
// fake the VI Init of the BIOS
Memory::Write_U32(Core::g_CoreStartupParameter.bNTSC ? 0 : 1, 0x800000CC);
// preset time
Memory::Write_U32(CEXIIPL::GetGCTime(), 0x800030D8);
// preset time base ticks
Memory::Write_U64( (u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8);
}

View file

@ -266,6 +266,11 @@ void CEXIIPL::TransferByte(u8& _uByte)
u32 CEXIIPL::GetGCTime()
{
const u32 cJanuary2000 = 0x386D4380; // Seconds between 1.1.1970 and 1.1.2000
// (mb2): I think we can get rid of the IPL bias.
// I know, it's another hack so I let the previous code for a while.
#if 0
// Get SRAM bias
u32 Bias;
@ -275,8 +280,11 @@ u32 CEXIIPL::GetGCTime()
}
// Get the time ...
const u32 cJanuary2000 = 0x386d35a1; // Seconds between 1.1.1970 and 1.1.2000
u64 ltime = Common::Timer::GetTimeSinceJan1970();
return ((u32)ltime - cJanuary2000 - Bias);
#else
u64 ltime = Common::Timer::GetLocalTimeSinceJan1970();
return ((u32)ltime - cJanuary2000);
#endif
}

View file

@ -25,6 +25,7 @@
#include "../HW/VideoInterface.h"
#include "../HW/SerialInterface.h"
#include "../HW/CommandProcessor.h" // for DC watchdog hack
#include "../HW/EXI_DeviceIPL.h"
#include "../PowerPC/PowerPC.h"
#include "../CoreTiming.h"
#include "../Core.h"
@ -38,6 +39,7 @@ namespace SystemTimers
u32 CPU_CORE_CLOCK = 486000000u; // 486 mhz (its not 485, stop bugging me!)
s64 fakeDec;
u64 startTimeBaseTicks;
// ratio of TB and Decrementer to clock cycles
// With TB clk at 1/4 of BUS clk
@ -160,7 +162,7 @@ void AdvanceCallback(int cyclesExecuted)
{
fakeDec -= cyclesExecuted;
u64 timebase_ticks = CoreTiming::GetTicks() / TIMER_RATIO; //works since we are little endian and TL comes first :)
*(u64*)&TL = timebase_ticks;
*(u64*)&TL = timebase_ticks + startTimeBaseTicks;
if (fakeDec >= 0)
PowerPC::ppcState.spr[SPR_DEC] = (u32)fakeDec / TIMER_RATIO;
}
@ -198,6 +200,8 @@ void Init()
DSP_PERIOD = (int)(GetTicksPerSecond() * 0.005f);
}
Common::Timer::IncreaseResolution();
// store and convert localtime at boot to timebase ticks
startTimeBaseTicks = (u64)(CPU_CORE_CLOCK / TIMER_RATIO) * (u64)CEXIIPL::GetGCTime();
et_Dec = CoreTiming::RegisterEvent("DecCallback", DecrementerCallback);
et_AI = CoreTiming::RegisterEvent("AICallback", AICallback);