Tursilion was nice enough to let me ask him a couple questions about his first entry into the jagcode
500 (Martian Invasion!) and his first go at programming on the Jaguar.
Another question. With the experience you've gained on the Jaguar doing this small demo, what could you do different if you knew then what you know now sorta thing. Could you figure out a way to get your tilt code to work? I find it hard to believe the Jag has trouble tilting the screen like you needed.Tursi wrote:Sure, I love talking about that sorta thing.
I can't really compare to the PS1... I know so much more than I did when I did that machine, and even then I was using the official Sony libraries, so I never got down and dirty with the machine.
So my Jaguar starting code was actually my tilt screen function. I got this massively ambitious idea and that was the core of it, and eventually it became me versus the machine. (Original idea was a Power Drift clone, but I refused to do it without the tilt screen...)
Programming the Jag - well first I needed to learn the various assembly languages. Previous to this I only knew 6502 and 9900, and I've only done 9900 in the last 10 years or so. I actually *started* with the GPU for my tilt project, using the Atari sample code for the 68k and just making little tweaks to it. There are a lot of comments in my tilt code that talk about discoveries, observations, and conversations. Luckily for me, I have a local friend who knows the hardware quite well and was able to give suggestions for things to try (plus he could read the netlists and was fond of calculating theorhetical performance for me to match).
To be honest what surprised me the most were the number of "gotchas" the machine has. Once they're in mind it's not too hard to avoid them, but there are a lot. And, of course, programming blind (ie: no debug output when a failure occurs) is always interesting, but there are tricks for that (like changing screen color to see where you crash, etc).
For Martian Invasion, I started that only when I realized that the tilt code was never going to reach the performance I needed. For that one, the goal was to get it done quickly as possible, since work was absolutely insane and I wasn't going to have more than an hour or two a day, including weekends. So just for the sake of maximum amount of code per line and minimum 'gotchas', I chose the 68k. Of course, that meant I needed to learn it, as well, but for the most part it wasn't too bad.
Both projects interact the processors a reasonable amount. The tilt code uses the GPU primarily, but also interacts tightly with the OP for scanline interrupts and gets it's vertical interrupts and control from the 68000. Martian Invasion actually has tighter timing, although it is far less optimized. The large scaled Earth and the 68k program actually eats so much time that doing the mid-screen palette change for the base was tricky, the GPU barely gets any cycles. Rewriting the OP list like I do en-masse eats so much system time that the score actually can not be displayed at the top of the screen -- the OP runs out of cycles and the score's characters droop. Despite the awful sound, I actually enjoyed the little bit of time I had for DSP code, too (about 3 hrs, thus the aborted tone generator replaced with a ROM-based noise player ).
The screen tilt code, of course, relies using the blitter to blit from the line buffer after the OP finishes drawing the line. The 16-bit read port to the line buffer really sucks. Had it been a full 32 bit (or 64!!), testing suggests it would have been more than fast enough for what I wanted to do. But I suspect they didn't expect anyone to want to read from it. I never do normal things.
The machine is incredibly low level, and the potential for power is impressive. The machine is also incredibly fussy and, to stretch the metaphor, does not like to be pet backwards. The only way I could move forward during development was to code logical blocks and test as often as possible. More than an hour without testing always made me nervous, and I saw about a 3:1 ratio between debugging:coding. That would decrease with experience -- I didn't know any of the processors after all.
My opinions of various options, in the end. Jumps in the GPU are insanely slow (compared to other ops), OP interrupts aren't really useful for more than simple things, the OP is much slower at scaling than I'd like, and the 68k eats so much bus time it's bloody useless (okay, this latter was well known). Indeed, based on the little I've done, it's pretty clear that everything on the Jag comes down to bus time, and it's a valuable thing to keep in mind.
Hope that's interesting enough.
There are a number of ways to solve any problem. The way I did the tilt code may not have been the best way, but it seemed to me the most interesting one. I actually revisited that code recently, thinking that I was just running the blitter backwards to work around the Y increment bug, and could flip it around for better performance... but that turned out not to be the case. I then switched to increment mode so I could use the blitter's inner loop to step, but that loses the ability to do a phrase at a time, and even 32-bit pixel mode was slower than phrase mode with the outer loop stepping. I *did* find an unexpected combination that made a small performance boost, improving my previous best score - previously I was copying in phrase mode using 16-bit pixels, just because I really am using 16-bit color. I changed it to 32-bit pixels, and saw an improvement of about 20 pixels per frame (I'm not certain why the pixel depth should even matter in phrase mode...)
As I was nearing the end of my experimentation, I was actually thinking about T-Bird and Frog -- polys might well be a better approach that bitmaps. When I saw in Martian Attack how large scaled bitmaps slow the OP, I really pretty much gave up on my plan. (Not that it would not work, but that it'd be tough. Without the tilt it would probably be fine.)
Of course, you can take the same problem and attack it from the other side. My thinking was that I could lean heavily on the OP and not worry about coordinates or rotation, but you could rotate your objects with the blitter and assemble the display in it's final form. I had suspected that would be slower, especially rotating many large bitmaps, but I never actually tried it.
Depending on what the machine's fill rate is really like - polys are probably the best right answer for what I wanted to do - but they aren't really in the spirit of the original game. So I didn't want to do that either.
There are maybe other options, and it may be fun to try them sometime. If I could blit somewhere other than DRAM, it might work - I had considered sort of paging the frame buffer through GPU memory to speed the line buffer access, interleaving the blitter and the GPU. I could try pre-rendering the frame in memory instead of copying out of the line buffer (probably would need to take the OP out of the loop, though, and I'm told that it's much faster at scaling than the blitter -- another thing I have not yet tested). That would also remove the need to do it per scanline.
And, through either a clever hack that was suggested to me (loosely it would be capturing every other scanline), or pre-rendering as I note there, it could be detached from the frame rate. I'm certain at 30fps there would be plenty of time left over for a game, it's only 60fps that's pretty tight.
But it really crosses the line from 'useful technique' to 'interesting hack'.
Thanks again for your time Tursi