Friday, July 20, 2007

Speeding causes fatal crash in space!

"Did you really think you could run 1.3 MHz and not crash, sir?" the C128 cop asked me after the game went awry on my FrankenDiesel.

It's true: the game was too fast on C128! What happened was that at the beginning of a game frame the main loop told IRQ "Grab sprite register data next display frame and stuff them into VIC-II when I'm busy minding other business, please" and went on to do its other business. The screen redraw takes almost a complete display frame on PAL, more than one frame on NTSC, so everything was ok. But with C128 running 2 MHz in the lower/upper border screen redraw finishes a lot before the IRQ grabs the sprite data. In fact it finishes so early that the main loop can sometimes run the complete game loop before IRQ gets to do its task. An there the disaster strike: the main loop told the interrupt "do it next frame" before IRQ had done the previous task and so sprite registers never got updated.

I fixed this with a working frame limiter, forcing the game use at least two display frames for each game frame. There was a limiter before, but that broke down when I added VIC-II buffering. I bet it knew that it could cause havoc that way...

But wait - C128 problem isn't fixed yet! Because main loop still runs droids before IRQ grabs the sprite data, sprites may get the position meant for the next game fram, and they start to wobble around the screen again. And that's what I was trying to avoid in the first place when I added the buffered writes.

Solution was surpisingly easy: screen drawing finishes somewhere around raster line 0 on PAL C128, later on all other computers. So I can do the sprite register writes in the bottom-of-the-display-IRQ which is guaranteed to come before any droids get run. This has the added bonus that now the copy loop runs in 2 MHz, speeding up the game ;)

Another bonus is that now I can allow the game run every frame if I really want. If I ever write C128-specific version I can save ~4000 cycles in the screen draw alone by unrolling the loop - that takes "only" 8 KB or so. In the end C128 version might run at 50 Hz all the time - Paradroid Redux Competition Edition, anyone?


Bugfix at the usual place. Title screen crashed randomly on C128 too, that should be fixed now.

No comments: