The Woebegone Trail: DevLog - Day 14 - ANTIC antics ...
Woebegone: An “The Oregon Trail” Homage - DevLog: Day 14 (06/28/24) - "ANTIC antics ..."
I've managed to squeeze in two solid days, and several "stolen hours" on various other days, of work on this in the last two weeks. The bulk of this time has been spent taking the code I originally wrote to test various techniques and a) re-writing it to use the various macros and equates/includes I created, and b) adding various moving elements and "graphics". It is still not the final presentation for the title/intro screen, nor for the travel screen, but it is the actual basis for both now - despite missing the animated oxen and wagon, and some additional foreground graphics.
The decidedly poor current "graphics" are due to my artistic ineptitude, and take me far longer to do than they should. Until I'm ready to have them done properly, I am going to stop fiddling with those. And the oxen/wagon that needs to be added I will probably borrow from the original Apple II version. At that point, I'll change the post graphic to my screen, not the Apple II version.
For now, it looks like this (excuse the odd colors in the text, the color-flow is hard to capture correctly; you can run the attached binaries if you want to see it properly):
ANTIC antics ...
I thought implementing what I'd already played with in my testbed, just using better coding style and my includes/macros would be relatively quick and painless. And in truth, it was.
Initially.
Doing a like-for-like conversion took about an hour. And maybe another hour tidying things up a bit.
Once I started adding the actual parallax scrolling regions, and had to combine those with changing colors and character sets during DLIs, things got "interesting" very quickly. I ran into all kinds of issues with cycle-stealing affecting (my) timing, DLIs interrupting DLIs, and so on ... which were lots of fun to resolve. This started off with four "clever" chained DLIs, handling color, character set and HSCROL changes. These were just too complicated to run reliably without causing very strange screen-glitching. Not just the beam outrunning my code, but huge areas of screen corruption. This was made more interesting by the fact that the same code, doing the same thing, with the same modes and settings, called 4 mode lines later, didn't not cause any issues.
My first fix to this was simple, but felt "ugly" ...
I broke those four "clever" DLIs into eleven separate, simple (as in, they did MUCH less) ones, and just had them chained in the proper sequence. The first switched the character set for the scenery, the second handled a mode-line color change, the third the first HSCROL update, the next a color change, then another to adjust the second HSCROL update and so on. This worked, but just felt clumsy (at the time). I wound up refactoring that to eight DLIs, but the complexity and run-time of two of them, while working nicely now, may just make more sense to go back to the "clumsy" eleven chained DLIs version (it's easier to read and understand the code for that approach).
It took a lot of repetitive work, exploration and trial/error to figure out what was really going on. In most cases the issues were DLIs interrupting each other, the rest, generally DLIs just taking too long (even if they weren't getting interrupted) and causing changes in the wrong places.
Overall, I got things working though a combination of:
- Smaller, simpler, faster, DLIs that reliably completed before the horizontal retrace finished.
- Using page zero storage for some values and indexes, to help make the DLI code faster (in some cases one cycle really did make a difference).
- Moving some longer DLIs to earlier mode lines in the display list; particularly if what the changed didn't affect the immediately following mode lines (e.g. changing HSCROL), so they could complete before the mode lines they were intended to affect were processed
- Adding benign blank-line display list instructions or an additional WSYNC in the DLI in a couple of cases where it had no negative effect and saved adding yet another DLI in the chain.
So that was that ...
"Parallax" Scrolling
This is a straightforward enough technique. It's just different bands of mode lines, all with their HSCROLL bit set, and a DLI updating HSCROL between bands, with the appropriate values calculated in a VBI (which also handles the coarse scrolling part). It can be table driven, or discrete, but as long as there aren't lots of other things going on in your DLI it's pretty simple to set up.
My first attempt at this worked (excepting the ANTIC antics described above), but wasn't great. The approach I took was to update each different band (clouds, hills/mountains, rocks/greenery) with a different HSCROL increment on every frame. So the clouds would move one pixel/color-clock, the mountains two pixels/color-clocks, and the foreground four pixels/color-clocks EVERY frame. While the not-scrolling at 30 or 60 FPS means it is never going to look seamlessly smooth, this looked excessively jerky.
I re-wrote that code to only ever scroll a band one pixel at a time, and to control the speed by changing how often HSCROL was update. So, the clouds would update every 16th frame (but move one pixel/color-clock), the mountains would update every 8th frame ... and so on. While the number of pixels moved per second is unchanged from the first approach, when not updating at 30 or 60 FPS the end result looks better. This approach also allows for much finer control over relative scrolling speeds for each band, the bands speeds are table-driven, adding new bands is trivial, and the code is easier to understand (and can still be refactored to be clearer still).
Note that both of the attached .XEX files use this new scrolling approach, just that one is setup with speeds similar to what I anticipate in the actual travel screen during gameplay, and the other (woebegone-fast.xex) updates the clouds at 4 frame intervals, the hills at 2 frame intervals, and the rocks/greenery every frame.
Current Code
Attached are two .XEX files; they differ only in the delta speeds of the scrolling elements (the "fast" version just being there so you can see the scrolling is smooth if done at appropriate speeds).
The repository for this code can be found here, though it's probably worth waiting until the next update before paying it any mind.
Bear in mind that this project uses Git sub-modules, so if you do want to play with the code, and you clone the project to do so, the standard clone operation won't pull in the "includes" project. You either need to recursively clone, or init the sub-module manually the first time, to get those files.
NOTE: I just noticed that on Atari800/Atari800MacX emulators, the rocks/greenery has the top 1-2 scan lines not scrolling properly. I'm sure this is another DLI timing problem in my code (though I'm aware of at least one timing difference between Altirra and Atari800MacX, which might also be why I didn't see it in my coding - for which I'm using Altirra). I will fix it in my next update, as part of the refactoring and consistency updates I want to make. I'll also need to at Atari800 to my tests so I can catch such things earlier.
What's Next?
- Fix the afore-mentioned scrolling/timing issue.
- Some general refactoring.
- Some consistency updates to coding style, comments (some didn't get updated during some of my iterating on code).
- Add the animated oxen/wagon.
- Put in the proper bottom-panel for the title screen.
- 1
1 Comment
Recommended Comments