From c03938ca7deef6454162b3874e8bdb1a34b94d48 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Thu, 18 Dec 2014 14:29:20 -0500 Subject: [PATCH] Time Manager stuff --- toolbox/os.cpp | 178 +++++++++++++++++++++++++++++++++++++++++ toolbox/os.h | 5 ++ toolbox/os_gestalt.cpp | 1 + toolbox/toolbox.cpp | 13 +++ 4 files changed, 197 insertions(+) diff --git a/toolbox/os.cpp b/toolbox/os.cpp index 4d76ee1..e6c3877 100644 --- a/toolbox/os.cpp +++ b/toolbox/os.cpp @@ -1197,4 +1197,182 @@ namespace OS return MacOS::prWrErr; } + #pragma mark - Timer + + struct TimerEntry { + uint32_t tmTaskPtr = 0; // address of the queue. passed back in A1. + uint32_t tmAddr = 0; + bool extended = false; + bool active = false; + + std::chrono::time_point when; + + TimerEntry(uint32_t a, uint32_t b) : tmTaskPtr(a), tmAddr(b) + {} + }; + + // heap sorted by next task to run? + static std::deque TimerQueue; + + namespace TMTask { + enum { + _qLink = 0, + _qType = 4, + _tmAddr = 6, + _tmCount = 10, + _tmWakeUp = 14, + _tmReserved = 18 + }; + } + + uint16_t InsTime(uint16_t trap) + { + // PROCEDURE InsTime (tmTaskPtr: QElemPtr); + + // this adds an entry to the queue but does not schedule it. + + /* + * on entry + * A0 Address of the task record + * + * on exit + * D0 Result code + */ + + using namespace TMTask; + + uint32_t tmTaskPtr = cpuGetAReg(0); + + Log("%04x InsTime(%08x)\n", trap, tmTaskPtr); + + if (tmTaskPtr) + { + memoryWriteLong(0, tmTaskPtr + _qLink); + memoryWriteWord(0, tmTaskPtr + _qType); + memoryWriteLong(0, tmTaskPtr + _tmCount); + memoryWriteLong(0, tmTaskPtr + _tmWakeUp); + memoryWriteLong(0, tmTaskPtr + _tmReserved); + + TimerQueue.emplace_back(tmTaskPtr, memoryReadLong(tmTaskPtr + _tmAddr)); + } + + return MacOS::noErr; + } + + uint16_t PrimeTime(uint16_t trap) + { + // PROCEDURE PrimeTime (tmTaskPtr: QElemPtr; count: LongInt); + // this activates an entry. + + /* + * on entry + * A0 Address of the task record + * D0 Specified delay time (long) + * + * on exit + * D0 Result code + */ + + using namespace TMTask; + + uint32_t tmTaskPtr = cpuGetAReg(0); + uint32_t count = cpuGetDReg(0); + + Log("%04x PrimeTime(%08x, %08x)\n", trap, tmTaskPtr, count); + + if (tmTaskPtr) + { + auto iter = std::find_if(TimerQueue.begin(), TimerQueue.end(), [tmTaskPtr](const TimerEntry &e){ + return e.tmTaskPtr == tmTaskPtr; + }); + + if (iter != TimerQueue.end() && !iter->active) + { + auto now = std::chrono::steady_clock::now(); + + iter->active = true; + + if (count == 0) { + // retain the original time or set it to now. + iter->when = std::max(now, iter->when); + } + else + { + int64_t micro; + if (count < 0x80000000) + micro = count * 1000; + else + micro = -(int32_t)count; + + + iter->when = now + std::chrono::microseconds(micro); + + } + memoryWriteWord(tmTaskPtr + _qType, 0x8000); + } + } + + + return MacOS::noErr; + + } + + uint16_t RmvTime(uint16_t trap) + { + // PROCEDURE RmvTime (tmTaskPtr: QElemPtr); + + // unschedule (but not actually remove) + + /* + * on entry + * A0 Address of the task record + * + * on exit + * D0 Result code + */ + + using namespace TMTask; + + uint32_t tmTaskPtr = cpuGetAReg(0); + + Log("%04x RmvTime(%08x)\n", trap, tmTaskPtr); + + if (tmTaskPtr) + { + auto iter = std::find_if(TimerQueue.begin(), TimerQueue.end(), [tmTaskPtr](const TimerEntry &e){ + return e.tmTaskPtr == tmTaskPtr; + }); + + if (iter != TimerQueue.end()) + { + uint32_t count = 0; + if (iter->active) + { + iter->active = false; + + + // update tmCount to the amount of time remaining. + // uses negative microseconds + // or positive milliseconds. + + auto now = std::chrono::steady_clock::now(); + + int64_t micro = std::chrono::duration_cast< std::chrono::microseconds >(iter->when - now).count(); + + if (micro < 0) + count = 0; + else if (micro < 0x80000000) + count = -micro; + else + count = micro / 10000; + } + + memoryWriteWord(tmTaskPtr + _qType, 0); + memoryWriteLong(tmTaskPtr + _tmCount, count); + } + } + + return MacOS::noErr; + } + } \ No newline at end of file diff --git a/toolbox/os.h b/toolbox/os.h index 4e75094..b97cbe1 100644 --- a/toolbox/os.h +++ b/toolbox/os.h @@ -98,6 +98,11 @@ namespace OS uint16_t ReadXPRam(uint16_t trap); uint16_t WriteXPRam(uint16_t trap); + uint16_t InsTime(uint16_t trap); + uint16_t InsXTime(uint16_t trap); + uint16_t PrimeTime(uint16_t trap); + uint16_t RmvTime(uint16_t trap); + } #endif diff --git a/toolbox/os_gestalt.cpp b/toolbox/os_gestalt.cpp index affb36b..00ba179 100644 --- a/toolbox/os_gestalt.cpp +++ b/toolbox/os_gestalt.cpp @@ -65,6 +65,7 @@ namespace OS { std::map GestaltMap = { {'alis', 1}, // Alias Manager + {'tmgr', 2}, // Time Manager (2 = revised, 3 = extended.) }; uint16_t Gestalt(uint16_t trap) diff --git a/toolbox/toolbox.cpp b/toolbox/toolbox.cpp index 60f9564..33aa27a 100644 --- a/toolbox/toolbox.cpp +++ b/toolbox/toolbox.cpp @@ -358,6 +358,19 @@ namespace ToolBox { d0 = MM::EmptyHandle(trap); break; + + case 0xa058: + d0 = OS::InsTime(trap); + break; + + case 0xa059: + d0 = OS::RmvTime(trap); + break; + + case 0xa05a: + d0 = OS::PrimeTime(trap); + break; + // resource manager stuff. // Count1Resources (theType: ResType): Integer;