pureikyubu/Docs/RE/timestuff.txt
ogamespec c21147ccff Cumulative changes all around project, regarding Stage 1
Docs: New TODO moved to EMU, old renamed to old_todo
Docs: Old coding style is deprecated (old_style.txt)
Docs: Removed mention about CubeDocumented and fixed old emails
RE: boot.s, proved first asm line (lis instruction parameter)
RE: Added PAL and NTSC Boot and IPL IDA files
RE: Some work on NTSC IPL (identified many lib calls, including OS, GX)
RE: Added EXI Bootrom descrambler by segher
RE: GXInit
RE: Internal GX lib structures (GXPrivate.h)
RE: More details on lomem (OS versions)
RE: OSInit and OS.c
RE: OSAlloc (heap allocator)
RE: Very first code of Metrowerk runtime (__start.c)
Docs: Added copy of http://gcdev.narod.ru
Source\Utils: Command processor (Cmd.c)
Source\Utils: File wrapper
Source\Utils: Gekko disasm cleaned up and ported to plain C
Source\Utils: Double-linked lists
Source\Utils: Ported old Profiler code
Source\Utils: String utils
2015-09-04 19:45:10 +03:00

139 lines
4 KiB
Text

Dolphin OS timing initialization
--------------------------------
BOOTROM:
=-=-=-=-
Bootrom will call __SyncTime() in its main() before gfx menu.
typedef s64 OSTime;
typedef s32 OSTick;
OS timer clock period is 1/12 of Gekko CPU core clock :
486 mhz / 12 = 40.5 mhz
// update time-base registers by RTC (real-time clock) value
// RTC is number of seconds, since 01 January 00:00:00 2000 (current epoch)
void __SyncTime()
{
OSTick rtcValue;
OSSram* sram = __OSLockSram();
if( __OSGetRTC(&rtcValue) == TRUE )
{
// counterBias can be negative value
rtcValue += (OSTick)sram->counterBias;
__OSSetTime( (OSTime)rtcValue * OS_TIMER_CLOCK );
}
__OSUnlockSram(0);
}
// here is SRAM structure
typedef struct
{
u16 checkSum; // SRAM byte checksum (discovered by Costis)
u16 checkSumInv; // inverted checksum (see YAGCD)
u32 ead0;
u32 ead1;
s32 counterBias; // now we already know meaning of this one too :)
s8 displayOffsetH; // used by VI library
u8 ntd;
u8 language;
u8 flags;
u8 dummy[44];
} SRAM;
OS:
=-=
__OSSetTime is used only in bootrom, to set time-base registers according
to battery-backed RTC value.
// OS low-memory variable
OSTime __OSSystemTime AT_ADDRESS(OS_BASE_CACHED | 0x30D8);
void __OSSetTime(OSTime newValue)
{
BOOL enabled = OSDisableInterrupts();
// system time keep its value during soft resets (?)
__OSSystemTime += newValue - OSGetTime(); // I'm unsure of that
// 64 bit math is hard to disasm
__SetTime(newValue);
EXIProbeReset();
OSRestoreInterrupts(enabled);
}
// use undocumented SPR registers, to set time-base
// SPR[284] = TBL, to write
// SPR[285] = TBU, to write
void __fastcall __SetTime(OSTime time)
{
__asm li r5, 0
__asm mtspr 284, r5 // clear TBL value (to avoid TBU++)
__asm mtspr 285, r3 // set TBU
__asm mtspr 284, r4 // set TBL
__asm blr
}
Emulation issues : Games dont like real TBR value. At least they work better,
when TBR is set to 0 before game start. Unemulated TBR is only affect on memcard
save date, AFAIK.
To convert TBR value to real-time I use Windows file time utility :
// covert GC time to human-usable time string;
// example output : "30 Jun 2004 3:06:14:127"
char * OSTimeFormat(u64 tbr)
{
// FILETIME - number of 1/10000000 intervals, since Jan 1 1601
// GC time - number of 1/40500000 sec intervals, since Jan 1 2000
// To convert GCTIME -> FILETIME :
// 1: adjust GCTIME by number of 1/10000000 intervals
// between Jan 1 1601 and Jan 1 2000.
// 2: assume X - 1/10000000 sec, Y - 1/40500000 sec,
// FILETIME = (GCTIME * Y) / X
// coversion GCTIME -> FILETIME
#define MAGIK 0x0713AD7857941000
f64 x = 1.0 / 10000000.0, y = 1.0 / 40500000.0;
tbr += MAGIK;
u64 ft = (u64)( ((f64)(s64)tbr * y) / x );
FILETIME fileTime; SYSTEMTIME sysTime;
fileTime.dwHighDateTime = (u32)(ft >> 32);
fileTime.dwLowDateTime = (u32)(ft & 0x00000000ffffffff);
FileTimeToSystemTime(&fileTime, &sysTime);
// format string
static char *mnstr[12] =
{ "Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
static char gcTime[256];
sprintf( gcTime, "%i %s %i %02i:%02i:%02i:%03i",
sysTime.wDay, mnstr[sysTime.wMonth - 1], sysTime.wYear,
sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds );
return gcTime;
}
Although this conversion is not perfect :O) Play with MAGIK value to find
suitable bias adjustment.
Tell me please, if you find better way to format GC time.
Document by org <ogamespec@gmail.com>
RTC: 11 Dec 2004 :)