Short version: The game is now running with approx 2 ticks per render (range bound between 1 and 3), using a modified version of the framerate-adaptive system. So movement speed remains constant as framerate fluctuates.
(Using the original, unmodified code, it wants to run about 6 ticks per render but ends up trying to do many more because of its own poor performance at 16mhz).
Long version:
First, I tried disabling framerate-adaptive behaviour - so the game plays like 'timedemo' mode with 2 ticks per render - and got that working, but the result was awful. The framerate is too variable and correlated with view direction as much as location. It feels like slow motion suddenly when you meet monsters, and entering a narrow corridor causes you to run unexpectedly. Not good.
I tried just capping the number of ticks allowed to per render to 2, and this also produced terrible results. The tick system generates event packets for each gametick and capping causes some of these to get dropped, so weird things happen. The most obvious problem is 'lag' from the controls - stepping sideways with a keypress doesn't actually happen until a few frames later. After mucking about with that for a while I abandoned the idea. It did work to limit spikes if the cap was set just above the average tick count, but set it lower and there are problems so it wasn't really helping.
While trawling through the code for the TryRunTicks and NetUpdate processes, I began to realize there is a sort of insidious flaw in there, which is probably due to the network stuff needing to be fast and synchronous and in constant contact with the other nodes. But it is a flaw from BM's point of view and is directly causing (really, amplifying) the worst case scenario when trying to track live ticks in realtime.
The whole gametick loop - which tries to tick the game enough times to catch up with the current realtime clock - is continuously checking the clock at different points within the process (!). The time is constantly moving on, so it keeps getting confused and finding more work to do, corresponding to the time taken by the gametick stuff itself. This is causing more ticks to happen than desired - it particularly encourages runaway spikes and nonlinear cost.
So I made some mods which trick the realtime clock into reporting time deltas only once per gametick 'turn' vs the renderer. The clock reports an accurate change in time, but only once. Sampling the clock within the gametick loop doesn't indicate any change in time, so the loop exits early. The time actually taken by the gametick process will register the next time round so no time actually gets lost.
This actually works. The game on average ticks one less than before, and the spikes have been ironed out. It would typically float around 2 ticks per frame, and rise to 3 on direction changes, spiking to 4-5 when you shoot something. Now it hangs around 1-2, and only jumps to 3 in a fight. That's quite a big saving given the high cost of each tick. The game feels basically the same. What's more, the lower average tick count means capping becomes safe to use, at around 3, for any untested worst-cases.
So the best solution seems to be:
- leave the adaptive gametick system mostly alone
- freeze realtime during the gametick catchup process, but keep track of the time wasted in there
- cap the tick count to 3 per render, max
These tests were done with a 12Hz tick frequency. I have also tested with 9Hz and that works even better but it causes some problems with AIs. I may return to that another time. The current setup is good enough for now.
On another topic - had some problems with the game not running reliably on a real Falcon. Turned out to be a few pieces of DSP code doing things which the DSP user manual warns are not legal, and cause undefined results

