Skip to main content

Atari craziness

So between making more maps for Robo-Ninja (I finished the rest of the Temple zone yesterday!), I'm still playing with my side-SIDE project of learning Atari programming.

Let me just tell you, that machine is insane.

On most modern hardware, drawing game graphics is a matter of setting up a scene in openGL, (or  often, some framework that abstracts away the openGL and lets you tell it what stuff to draw where).

On the GBA, it was a little harder. You had magical memory registers for video ram, which you'd fill up with appropriate graphics, you'd poke palette data into a different register, then you'd have other  registers that told it how to build and display sprites or background tiles based on all that. You could, for example, fill in a register to say "put a 16x16 sprite, flipped horizontally, at position X,Y, based on graphic data at video ram location FOO" You still had to do a good bit of work figuring out how to swap data in and out of the limited video ram, how to update slices of the background tile data to make it look like the screen was scrolling, etc, but it wasn't too bad.

On the Atari, you have to hold the thing's hand THROUGH EVERY TV SCANLINE.  To position a sprite horizontally, you literally have to wait until the scanline is at the right place and say "DRAW IT NOW!" Which is tricky because the only way to track how far you are into the scanline is to count the processor cycles of every assembly command, and know that the scanline advances X amount for every cycle. You only get 76 clock cycles per scanline, which is only around 30 assembly instructions, so you're counting and squeezing to try to minimize every assembly command you send to it while drawing the screen.

Luckily it remembers the horizontal position of where you last said "DRAW IT NOW" so on other scanlines you can focus on doing such trivial tasks as loading each scanline's sprite data into the right register, hoping that you can load it into the register before the scanline passes the sprite's X position, because if you take too long, it will have drawn the sprite before you managed to load the new data.

Oh, and you only get 2 sprites and 120 bytes of ram to work with.

It's horrible and wonderful all at the same time. For some crazy reason, I'm loving it.  Tonight, for example, I was trying to figure out how to prevent the black bars from showing up on the left when you move a sprite mid-frame. Take a look at missile command and frogger:


Those are classic examples of games with positioning lines on the left -- the Atari hardware had a weird quirk where if you moved a sprite's horizontal position partway through the frame, it would draw a black line at the left. There didn't seem to much you could do about it. Quite a few games just gave up and had them. A lot of others (particularly Activision games, or so I've read), made the whole left bar of the screen be black, just to hide them.

But somewhere along the line, some smart person realized you could trick the Atari hardware into not showing them, if you wrote to the move register at EXACTLY the 74th clock cycle, at the end of the scanline. So I spent part of my evening counting clock cycles to try to write to that register at exactly the right time.

I ended up going with an easier but less elegant solution, which was to basically not put any enemies or background changes on that scanline, so I could spend an entire line just burning cycles to get to 74. It will work for what I'm going for, but prevents anything interesting from happening on that line.

Just for kicks, here's the code for managing that scanline:
      STA WSYNC   
        LDA #$80            ;2 prevent other things from moving on early hmove,
        STA HMP0     ;3  so clear out the movement registers 
        STA HMM0     ;3
        STA HMM1     ;3
        STA HMBL     ;3 
        LDY #7              ;2 (16 so far) ... 58 cycles left

BurnScanlineLoop
        NOP                  ;2  (7 cycles through each iteration of  
                             ;     the burn loop, 8 the last time through,
        DEY                  ;2    because the BNE only takes 2 cycles 
                             ;     if the branch isn't followed)

        BNE BurnScanlineLoop ;3 (2) (burns 48 during loop) ... 10 left


        LDA Temp             ;3  (basically a NOP, but needed to burn
                             ;3 cycles instead of 2)
        NOP                  ;2
        DEX                  ;2  Reduce the line counter since 
                             ;   skipping the regular WSYNC
        STA HMOVE            ;3  Do the MOVE!
        JMP ScanLoopSkipWsync ; Skip the Wsync since we used the whole scanline

And there we have it, folks. Clearly I've descended into unbridled insanity.




Comments

Popular posts from this blog

Retrospex 32 Review

RetrospexInternational recently sent me a couple units of their new handheld device, the Retrospex 32, a new dedicated GameboyAdvance emulator handheld.  To make the unit playable out of the box, they pre-loaded a handful of homebrew games, including Anguna, which is why they were kind enough to send me 2 of the units to play with.  I was pretty excited to get my hands on the device and try it (I loved my old GBA micro with a good flash cart!), and see Anguna running on it. So here's my thoughts after playing with it.



Their website lists the Retrospex 32 for £59.99, which is around $100 USD. It seems like it's marketed toward people into retro-gaming (which makes sense for a dedicated GBA emulator device). At that price, with that target market, and such a limited set of functionality (why not make it a multi-machine emulator, and emulate all the old consoles?), it would hopefully do a really good job of it.

The short version of my review: it doesn't. It has one job (emula…

Making the game fun

The real trick for Spacey McRacey (as I'm calling it now) is going to be making it fun.  And that's what I'm rather unsure about at this point.

I have a game design that basically works. The technical issues are mostly sorted out, I just need to get a few more implemented before I can seriously play test it.

But fun? It's hard to know if it's actually going to be any fun to play.  With a 4-player party-style game, it's seems like it might be hard to hit that fine line where everyone is close and competing, where everything feels exciting and tense, as opposed to tedious and boring.  And despite envisioning my game as fun, it might just be boring to play.

Some of that comes down to tweaking it. Tweaking the speeds, difficulties, etc, will make a difference. (If it's too easy to shoot people from behind, then it will be nearly impossible to hold a lead for very long, which could ruin it and make it no fun. If it's too hard to kill the guy in front, it wil…

Killer Queen

So at PRGE, I played an arcade game that just left me amazed.  Killer Queen.

It's a 10-player game. You have 2 cabinets linked together, and 5 players huddled on each one. Each one is a team of 5 people, working together to play a simple one-screen 2d platformer.  But what made it work was the high quality game design.

First, the game is relatively simple, yet there is a lot going on at once.  One player plays the queen, the most important and powerful character on the team. The others start as workers, but can become warriors who can fly around and attack in a very joust-like flappy contest of height.  The real trick is that there are three completely different ways to win: either collect a bunch of berries and bring them back to your base, or ride a REALLY SLOW snail across the screen (while other people try to kill you, and you hope your team protects you), or kill the enemy queen 3 times.  There's some other things going on as well (using berries to upgrade, capturing upgr…