Content warning. This post is mostly text.
Anyway, the Torch emulator has a bit of an issue. It now picks up the time from the local host (either Linux or - bleurgh - windows) and even uses days with dates that match the current year even though it's not y2k compliant. It just picks a previous year where the days match and for 2026 that year is 1998.
All well and good since we can manage without the absolute correct year on files. But what is more of an issue is that the time starts to accelerate as soon as the emulator picks up the host time. So after a few minutes the time has advanced about ten minutes. After an hour, the time is an hour and a half ahead and just getting further and further away from the actual time.
![]() |
| Are you sure it's nearly five to six? |
It turns out that the original code basically says 'after 200,000 emulated cycles advance the RTC by one second'. And because the code doesn't advance anything other than the seconds, I have to assume that Torch Unix sees it and just maintains its own system clock from that.
Looking through the comments in the code there's this one:
/*
* The deliberately short interval also satisfies Caretaker's RTC
* liveness tests.
*/This suggested that it was designed to make the seconds register update often enough that Caretaker believes that the RTC works. Obviously, in the real hardware, the seconds register would update once per err... second.. (In actual fact, this check is only at the start..)
So, the next question, does the clock run fast because the 68010 implementation in musashi is not regulated? The Triple X hardware uses the 6845E CRTC VSYNC signal to drive IRQ6 so maybe Torch Unix is actually using that as the system clock 'tick'. As a bit of a test, I put in a fixed 50hz IRQ6 using one of the SDL functions (SDL_GetPerformanceCounter()) rather than the existing CRTC timing. And would you believe, with that hack running the time is spot on. So that's nice.
Looking over the original code, the function video_crtc_tick() is just toggling the VSYNC state every 4000 calls to that function. And because the emulator main loop runs at the host speed it means that this timing is also host speed dependent. There is a variable called g_crtc_cycles that doesn't really represent CRTC cycles but actually counts function calls... (This code is freakin' complicated.)
To get around that I changed the video code (since it was all CRTC based) to use the SDL library performance counter. This means that the CRTC now has an accumulator that generates one VSYNC event every 20ms. I also had to mod the video code so that it now has a 'pending' VSYNC count. One function adds the 'tick' event every 20ms and then another removes one event at a time. This means that VSYNC events aren't lost because the main loop doesn't see the actual event i.e. it's still in the queue. Without this change the clock was losing about five seconds a minute because of the 'missed' VSYNC pulses.
There is a hack in the code for Caretaker startup that I didn't touch (mentioned earlier). This hack is needed because Caretaker does a timing test during power up and it expects about 600 status reads between changes. If it ain't broke, don't fix it... This hack is only running at startup anyway and doesn't impact the (updated) RTC and VSYNC code.
At this point, the clock looks good and seemed to be keeping good time. Except it was an hour ahead. I hate GMT/BST nonsense. (It causes me issues at work too..) Anyway, I just updated the Linux RTC sync function to use gmtime() rather than localtime(). It looked like Linux was compensating for local time even though local time was already at BST.. Twisting my melon man.
So far so good. But all of this messing about with the clock code messed up the Torch startup animation. It would get through the first 'bar' and then immediately move onto the next part of the boot phase. There's just about enough time to click 'STOP' if I wanted to but I wasn't happy with the situation. I wanted it to look like a proper Torch booting up and that requires a fully executed animation. So there.
So back to the code again. I had to fiddle with the 'host divisor' (which controls how slow Caretaker runs to give you time to see the animation and click 'STOP' if you want) and realised that if I increased it, it would compensate for the now correct VSYNC rate. I got the full animation back with a bit of experimenting but with a minor annoyance. Because the whole system is running slow during that initial startup, it puts the clock 30 seconds(ish) behind real time. By this point, I am willing to just go with that. I'd had enough of trying to understand the code and where it is now is fine.
In summary, the RTC timezone is now correct (yay!). The CRTC now generates a 'real' 50Hz VSYNC. IRQ6 uses this to drive the Unix software clock (or rather the Unix software uses IRQ6 as the 'tick' for its clock). The Caretaker startup is intentionally slowed down to allow the boot animation to run (as well as give an opportunity to click 'STOP' for more startup options) but with a slightly modified 'divisor' value. This puts the Torch RTC about 32 seconds behind actual time.
I can live with that.
*I'm fully aware the time difference on the last screenshot is actually 28 seconds. It takes four seconds for me to get the screenshot up and clicked after running the 'date' command on the emulator!



No comments:
Post a Comment