Saturday, February 13, 2016

Subscreen

Ok, I finally took the time to sit down and work on the subscreen, and it turned out to be pretty fun, actually.

For now, I omitted the password portion -- I want to include it, but because the total ROM space is going fast, I want to make sure I have the rest of the content first. So right now the subscreen looks a little weird, all bunched up at the top. I'll spread it out a bit if I decide not to do the password.  And I need to adjust a few things (key colors, horizontal alignment of the keys, etc)

I'm also alternatively considering adding some sort of low-resolution map to the bottom half instead. I have no idea how that might actually work, or if I have any possible way of actually doing it with the limited resources I have. But it sounds cool.


The picture above shows all 6 keys, 17 out of 17 HP, 0 attack and 0 armor (which shouldn't ever happen), 0 arrows, and all the special items (bow, dynamite, lantern, ring, and boots).

Thursday, February 11, 2016

More with title screen

I've currently spent some time working on the inventory screen, which for some reason hasn't been easy to get excited about. It seems like a lot of hassle trying to get everything to nicely display.

The first part is getting the player's keys to display. Because you can tell the atari to triple each sprite, it's easy to get potentially 6 keys to line up on the screen. The trick is getting the timings exactly right to change the color appropriately for each key.  I'm pretty close at this point.

Unfortunately, my code to pick the colors based on the key type isn't quite right yet.

The next part will be to display numbers (or if that's too hard, bars) for health, attack power, armor level, number of arrows, and other items.

Then what I really want to do is also have a password system, similar to early NES games, where you can continue by entering a password.  But I'm not sure that I'm going to have ROM space -- showing the current password is pretty easy, but a password entry system might take up too much room. We'll see.

So getting bored and annoyed with that, and after seeing some of the amazing title screens that folks on AtariAge have come up with, I decided to rework my title screen. I played around with a few designs (I tried a sky into ocean with waves that come and go on a beach, but when I asked my friend Tim what he thought it was supposed to be, he couldn't tell, so I gave up on that idea), but finally settled on this road going off to the horizon, with trees around it. It was fun to make, and pretty simple to put to together:

I guess now it's back to the subscreen....

Tuesday, February 2, 2016

Working on hardware

Well, I bought a new RF adapter, soldered on a new controller jack, and bought a Harmony Cartridge.

With that in place, it only took about an hour to solve the problem:


Going through the process of starting with ridiculously simple sample code, testing on the Atari, and then slowly adding complexity until it broke, I finally narrowed it down to a relatively small subset of places that the problem could be.

It turns out that I was trying to do some fancy bank jumping acrobatics before properly zero'ing out everything.  Ok, boring explanation time:

When you turn on the Atari, the entire block of ram, and the state of the CPU registers, are completely unknown. So the first thing you should do is start zero'ing them out.

Now one of the things that's unknown is also what memory bank you're running in. Which means that although you know what memory address the program starts at, it could be in any bank. So one of the first things you need to do is, in the same place in every bank, run code to jump to the bank that has your actual program beginning in it.

Jumping banks is as simple as writing to a magical memory location, BUT that just immediately switches banks, leaving your program counter (ie memory location of the next instruction) as it was. So you have to make sure everything lines up nicely. I previously explained how I made some general routines for doing bank jumps, which involved writing an address to the stack, then issuing an RTS command, (return from subroutine), which makes the CPU pop an address off the stack and jump to it.  And I was using those for my initial beginning-of-program jump to my actual code.

Well, it turns out that if your stack and stack pointer are all in a broken random state, you can't reliably write an address to the stack and return to it.

The awesome Stella emulator has some settings to randomize memory on startup, which helps you generally find these issues, but I guess it wasn't randomizing something quite enough. Because once I properly zeroed out and initialized everything BEFORE doing my bank jump, everything worked!

Now I need to figure out why the colors are so completely different....

Friday, January 22, 2016

Ugh Ugh Ugh

Well, I've run into 2 big problems.

First, is that although I thought I had all the scanline jitter solved, it turns out that I had a few places where there was still jitter. And this has been really hard to track down.  After a few angry evenings staying up too late debugging, I finally realized that it wasn't actually my display kernel causing the problem (where I had spent the longest time debugging), but that occasionally I was taking too long in my main update code, and not rendering the screen in time.  So I need to do some combination of optimizing, removing code, or running updates every other frame.

The other problem is harder to deal with. I asked a friend if he could test with his Harmony Cart (an sd-card-based atari cartridge to run on a real Atari), and the game doesn't work. AT ALL. It won't do anything, not even display anything on the screen. So something's really wrong.  Unfortunately, I have no idea what.  At this point, I think the only thing I can do is get my Atari up and running, buy a Harmony Cart myself, and go through my git history testing different builds. At one point, about a year ago, I know that it ran.  I need to find out where it stopped.

So I got the Atari out of the garage last night, and went through about 8 or 9 combinations of adapters and cords trying to get it to work.  (The RF switch box that came with it is somewhat broken. I tried with my NES RF box, SuperNES switch box, and a few other gizmos from my box of adapters. I had the most luck with the NES switch) The best I got was an extremely blurry screen that you could somewhat see. Not enough to really enjoy playing on. Now do I want to spend $60 on a special cart just to debug this on my terrible TV?

I have a few more things I can try to get it working better. If I'm going to spend the money on a flash cart, I want it to at least look good.  We'll see what happens.

Tuesday, January 19, 2016

Title screen

Thanks to the sample code of really smart people out there, I now have a working title screen!

The hardest part was similar to the last problems I talked about: cycle timings getting messed up while crossing a page boundary.

To get a nice large "hi-res" graphic on the atari, you have to take both sprite objects, tell the Atari to repeat them 3 times close together, and then stagger them.  (Imagine the 3 repeated planes on Combat, or the 3 players on Football. Then imagine 2 sets of those interleaved with each other) That gets you halfway there, but then you have to very exact timings to update the sprite's graphic data mid-scanline.  Because the Atari is so doggone slow, the timings are really tricky. (Although the technique eventually became fairly well-known -- any game with a 6-digit score display most likely used this technique).

I got the code all working thanks to that sample code I posted to above, but if I fiddled much with the graphics data, the timings would get off by 1 clock cycle, and it would fail. Turns out, again, that it was crossing a page boundary. This time with a LDA instruction (loading the accumulator from memory) -- if you do a "LDA foo,X" command, which loads the accumulator with whatever byte is at memory location (foo + the value of the X register), and foo+X crosses a page boundary from foo, it takes 5 cycles instead of 4.

Luckily the assembler gives you a nice "align" pseudo-opcode that lets you force alignment of your data into page boundaries, which fixed it.

After getting the title displayed, I wanted to make it pretty. I have 8 whole clock cycles free per line to do what I want with, but to update the color of the whole thing, I have to write to 2 registers (COLUP0 and COLUP1, the color registers for each sprite), which alone takes 6 cycles. There's not enough time left to pick or calculate the color for the scanline.

So I unrolled the kernel loop by half, which lets me use 16 clock cycles every 2 lines. That's plenty of time to load a base color, add to it based on the current line, and then write it to the color registers. The end result is a pretty animated title graphic:

Right now the PASSWD option doesn't do anything :-(

The half-unrolled loop ended up looking like:
.loop:
    sty     tmpVar              ; 3

    ;update the color
    tya                         ; 2
    adc     PlayerColorDef      ; 3
    sta     COLUP0              ; 3 = 11

    lda     (ptr+$0),y          ; 5
    sta     GRP0                ; 3
    lda     (ptr+$2),y          ; 5
    sta     GRP1                ; 3
    lda     (ptr+$4),y          ; 5
    sta     GRP0                ; 3
    lda     (ptr+$6),y          ; 5
    sta     tmpVar2             ; 3 = 32

    lax     (ptr+$a),y          ; 5
    lda     (ptr+$8),y          ; 5
    ldy     tmpVar2             ; 3
    sty     GRP1                ; 3        
    sta     GRP0                ; 3
    stx     GRP1                ; 3
    sta     GRP0                ; 3 = 25

    ldy     tmpVar              ; 3
    dey                         ; 2

    ;burning 3 cycles in place of the bpl since the loop is half-unrolled
    sty     tmpVar              ;3 (in place of the bpl)


    sty     tmpVar              ; 3

    ;update the color
    tya                         ; 2
    adc     PlayerColorDef      ; 3
    sta     COLUP1              ; 3 = 11

    lda     (ptr+$0),y          ; 5
    sta     GRP0                ; 3
    lda     (ptr+$2),y          ; 5
    sta     GRP1                ; 3
    lda     (ptr+$4),y          ; 5
    sta     GRP0                ; 3
    lda     (ptr+$6),y          ; 5
    sta     tmpVar2             ; 3 = 32

    lax     (ptr+$a),y          ; 5
    lda     (ptr+$8),y          ; 5
    ldy     tmpVar2             ; 3
    sty     GRP1                ; 3         
    sta     GRP0                ; 3
    stx     GRP1                ; 3
    sta     GRP0                ; 3 = 25

    ldy     tmpVar              ; 3
    dey                         ; 2

    bpl     .loop               ; 2/3 =  7/8

Saturday, January 16, 2016

Crossing Page Boundaries

For awhile, everything was working perfectly in my 3-enemy display kernel on Atari Anguna. Then this weekend, I added some new graphics (for the crocky boss monster at the end of dungeon 1).

Suddenly, things stopped working right. Enemies started jumping around horizontally instead of smoothly moving. It looked choppy and horrible. And all I did was add some new graphics data.

HUH?

Well, the issue was probably pretty obvious to any veteran Atari programmers.

On the Atari, when you reuse a sprite with a new horizontal position, you often get the weird black lines that appear on the left of the screen. I wrote a post about it awhile back, how if you write to the re-positioning register on exactly the 74th clock cycle the scanline, you'd prevent the line. If you did it earlier, you'd get the line. If you did it later, it might not HMOVE at all.

I've shown pictures of this before, but here's a sample of the black lines from doing the mid-frame HMOVE

Another important piece of the puzzle is the 6502's conditional branch opcodes. In general, they take 2 clock cycles if the jump wasn't taken, and 3 if they do. BUT if the jump passes a memory page boundary, it takes 4 cycles. (the 6502 divides memory into pages of 256 bytes each).

So it turns out, by adding additional graphics data, which ended up coming BEFORE my kernel code, it relocated the kernel code slightly, pushing one of my branches across a page boundary, and changing the clock cycle count of the routine by 1. Which made the HMOVE come too late, which made my re-position fail!

Well, the solution ended up being really easy, once I figured it out. Moving all the graphical data AFTER the kernel logic fixed it, and made sure that additional changes won't end up moving the kernel code.

WHEW.

And with that, I have most of a re-creation of the first dungeon of Anguna finished for the Atari. Since I had decided somewhere along the line that the first dungeon would be the same, but the rest would be mapped out differently, this means it's time to start doing level design again!

Fighting the Crocky boss. Like the GBA version, the Bow and Arrows make this fight easier!


Really, at this point, the majority of the game logic is done. I still want to add a title screen, game over sequence, maybe a subscreen that shows what items/keys/etc you have, maybe a password entry system (like old NES games) so you can save your progress, and if I'm not sick of the game by then, a shop where you can buy stuff.  Wow, that sounds like a lot when I list it that way....

Monday, January 11, 2016

Making things!

A few random updates:

  • My Life in Space game is done, I think. The Jam ends in about 5 days. I'm doing some last testing, and then will submit it. If anyone has an Android phone and wants to test for me, holler. It's pretty small compared to some of the crazy stuff that other people are doing for the jam, but I'm just happy to have a finished project that I think is interesting.
  • I'm finally about done with the crop insurance project, which means more time for hobby projects!
  • I've actually started working on Atari Anguna again in earnest. I'll probably be talking a bit more about that, but I've done a bunch of work on cleaning up my half-finished door code, fixed a number of small timing issues with my kernel, and even got the Bow and Arrow item ALMOST working!
  • I really liked having 2 projects at once with Robo-Ninja and Atari Anguna, so that means it's time to start thinking about my 2nd project.  Right now, the major options are either port Anguna to Android (using the C++ code that I had 2/3 finished from years ago when I attempted to port it to iPhone), or start on a NES game. I'm leaning toward the NES game, which means I might spend a lot of time here droning on about the interesting differences between the Atari and the NES.  (They both use the 6502 processor, but there's not much similarity beyond that!)

NES Anguna

Well, I had a little bit of time still, while Frankengraphics is finishing up her game Project Blue, to have a little downtime on Halcyon, s...