deathshadow
Veteran Member
- Joined
- Jan 4, 2011
- Messages
- 1,378
While it would be near impossible to use one codebase to generate a 20, 24 and 30fps video framerates with a fixed 120hz audio update simultaneously without the risk of either-or interrupting each-other at undesired intervals.It would be more difficult to update the screen at the full framerate (ie. 60Hz) using your methodology
Basically what I'm doing is running 120hz audio updates, and slicing in the code for everything-else in-between them. I don't see how a flat execution model can handle that with any degree of grace or accuracy -- hell it's why so many CGA-era games have jittery video and buggy sounding audio is they didn't bother.
Even if I synced it flat, I'd then have to add the overhead of fixed point or floating math to the ghost updates making it far more complicated -- OR I'd have to put the audio updates in the timer ISR meaning multiple DIFFERENT timer ISR's or constantly changing what subroutines the ISR is calling depending on if it's in the menu vs. in the game, which siren is in use, which effects are being played or maintained, etc, etc... Are you basically saying that doing that would be SIMPLER than just profiling timeslices? doesnae make any sense to me...
... and honestly at 320x200 or less anything over 30fps is a waste of time. (just as at 640x400 or higher anything over 60hz is a waste of time unless compensating for raster decay)
Yeah, I'm not sure why that's not working either.If that's the only change then I don't see why it shouldn't work.
Actually, should be WORD sized... and that's declared in the macro as countInc and countDec are macro's.Though I did notice something I didn't see before;
I'm running 120hz for the audio updates (I really should consider bumping it back to 240hz) both for speaker arpeggio's and realtime audio updates like the siren frequency; the time-slicing means I don't have the headache of having multiple different versions of the timer ISR or making some dozen different calls for the ISR to check against; but 120hz is NOT an even multiple of the 65536 timer intervals used by the normal 18.2hz clock. If I simply used the next nearest whole number the system timer would skew way off the longer the game ran. (as if it's not bad enough the jitter switching timer freq introduces on entrance/exit).BTW, what is countISR, countInc and countDec anyway? Can you describe the timer code in more detail?
My solution is to simply use fractional math. Keeps it integer, keeps it fast.
Code:
%define countInc WORD 0x4000
%define countDec WORD 0x09B9
remember the PIT runs that 4.77mhz, and the system clock is updated roughly 18.2 times a second? Well, that 18.2 is actually 4,772,727 / 65,536 (+/- 0.027%) -- that 4.77mhz being 4:3 ratio the 315/88 colour burst crystal clock... (though I never really understood how you get a clock FASTER than the feed source?)
Every 65536 ticks on the PIT the system clock ISR should be called. Since I'm running the ISR every 9956 ticks (which actually works out to EXACTLY twice the vertical retrace of 59.902khz) there is no accurate integer value of 65536 / 9956...
So I fraction reduce it by four.
65536 / 4 = 16384 (0x4000)
9956 / 4 = 2489 (0x9B9)
so counter - 2489 until negative, when it goes negative add 16384 to it, and while there is timer "jitter" it is over a long period of time accurate. Every now and then the delay is a hair longer, but the average is accurate without resorting to floating point.
Basically it's the same math that Bresenham used in his line drawing algorithm. You need to get from point A to point B in integer numbers, without using floating point, accurately.. when X and Y do not cross-divide to an integer value.
Assuming distanceX is greater than distanceY:
Code:
void lineX(int x, int y, int distanceX, int distanceY) {
int
endX = x + distanceX,
count = (distanceX / 2); // I divide by two so the ends match
do {
plot(x, y);
x++;
count -= distanceY;
if (count < 0) {
y++;
count += distanceX;
}
} while (x < endX)
Same general idea. Every so often there will be 'jitter' where the delay is longer or shorter between them, but over long periods of time it remains accurate as at the end it all adds up to the same value. Ever heard people talk about "timer jitter"? Well this is often the "why" of that when you want a timer interval that is NOT an integer quotient of the master timer you're trying to divide off of.
... and knowing how to do that can be REALLY handy; particularly if you have multiple events that need to run at different rates; like audio, video, user input and clock NOT running at the same flat frequency. Becomes an even bigger issue in real time programming in industrial settings -- where sensor inputs and motor control outputs often have wildly varying data rates. In a RTOS (real-time operating system) you'll often have dozens or even hundreds of these running off a single master timer -- particularly if trying to maintain realtime I/O on a single threaded processor. (see QNX)
In that way I'm applying a lot of motor control and realtime programming concepts to a game -- I find it easier that way and far simpler code-wise given what I want as a result. YMMV.
Last edited: