Sunday, February 28, 2016

Subscreen Map

Well, I had originally said that I planned to wait and see how much space I had before making the subscreen map that I planned on.  But this past week, after working on the overworld, I realized that with my limited range of different screen layouts, the overworld was going to be a big boring place that's easy to get lost in.

What I really needed was a map.  With a map, at least the overworld becomes a big boring place that's not quite so easy to get lost in.


So I added the map on the subscreen. It took a bit of work to get the colors all lines up the right ways, using the different graphical objects available, but I think it's working now. The white dot tracks where you are on the world.


I did manage to get the kernel all working with my multiple colors, like I mentioned last time. I was even able to animate the water of the river, so the color moves down the screen, which is fun.



I think it's time to post some builds to the Atari homebrew forums to try to get some feedback.  That's scary.

Saturday, February 20, 2016

Squeezing and compacting

I've been plowing away at the game, adding some nicer graphics on the subscreen, fixing a bunch of minor issues, getting some bugs worked out with items, and starting on the overworld.

When I got to the overworld, I realized that my first couple screens were really boring.  Here is the hero standing outside of the cave that leads back to the first dungeon. I want to add some trees or something to the bottom half, but the way my engine works, each room only has 1 wall color.  I stared at this for awhile, but just wasn't happy with it.


Thus I started a new quest to squeeze yet one more thing into my display kernel. This seemed like crazy talk to me, as I already was having trouble getting all my timings right during the kernel. But Atari programming is all about crazy, so I stayed up WAY too late last night trying to find places to slightly tighten up the speed of my kernel code, so that I could squeeze in just a couple more instructions to update the color every few lines.

Turns out, by squeezing part of the calculation on one scanline, and the other half on the next, and by getting my timings just right so that I could eliminate a WSYNC, I got it working. (WSYNC is the instruction where you tell the Atari/TV that you are done with the current scanline, and it should start on the next. It takes 3 clock cycles -- but you can omit it, and the next scanline will just start when it's time. You often use it to force the timing to reset on each line, but if you have everything timed right, you can omit it and just start on the next line).

So now I have the ability to change the playfield color every 4 scanlines. The problem now is that this means that I have to devote 23 bytes of ROM to each different color layout that I want. And my 4k bank where the kernel and graphics live is already getting dangerously full.

Which meant that I started another crazy quest to tighten up the ROM space of the kernel code. Originally I had a lot of loops that were unrolled for the sake of speed, and no subroutines (which waste 12 clock cycles during the jump and return, which I generally can't afford in the kernel)  So now I'm going back and selectively re-rolling loops and moving things around, trying to free up a few bytes here and there. I've managed to free up about 200 so far (which is about 5% of the space of this ROM bank, so that's something), and have some ideas about places I can free up more.

So....progress is slowly happening. Although if I keep thinking of new features, I might no longer be able to squeeze things in anymore! (I'm already down to only 160 bytes of ROM left in my "main" bank, although that's less timing-intensive, so I can jump to other banks for subroutines if necessary)

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

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...