Jump to content
IGNORED

Nyan Cat Game - Work in Progress


JeremiahK

Recommended Posts

Using your suggestions, and adding a few more changes, I have come up with this plan for the kernel:

 
.KernelLoop
    ; 14 cycles to prepare rainbow colors
    lda RamBowGfx,y	; 4
    sta COLUBK		; 3
    lda RamBowGfx+1,y	; 4
    sta COLUPF		; 3
    
    ; 8 cycles to prepare cat face graphics
    lda (CatFaceGfx),y	; 5
    sta GRP0		; 3
    
    ; 8 cycles to prepare tart graphics
    lda (TartGfxPtr),y	; 5
    sta PF1		; 3
    
    ; 5 cycles to set tart color
    lda #COL_CAT_TART	; 2 (25)
    sta COLUPF		; 3 (28) MUST end on cycle 28
    
    ; 6 cycles to clear PF/BK colors to black
    ; x is pre-loaded with 0, the color black
    stx COLUBK		; 3 (31) MUST end on cycle 31
    stx COLUPF		; 3 (34)
    
    ; 14 cycles to prepare 1st food item graphics
    lda (FoodGfxPtr1),y	; 5
    sta GRP1		; 3
    lda FoodColor1	; 3
    sta COLUP1		; 3
    
    ; 14 cycles to prepare 2nd food item graphics
    lda (FoodGfxPtr2),y	; 5
    sta GRP1		; 3
    lda FoodColor2	; 3
    sta COLUP1		; 3
    
    ; 5 cycles to finish the loop
    dey			; 2
    bne .KernelLoop	; 3
    
    ; 74 cycles total, 2 to spare. Quite a tight squeeze!

This wouldn't draw the rear paws, but that is fine with me as long as everything else in intact. The pop-tart would be drawn with PF1.

Note that the background color will be changed from dark blue to black. This is neccesary, as it makes the face color the same as the background color. Also, it will help with the flickering food items, avoiding the classic yellow "ghost" effect from Atari's Pac-Man.

 

The 11 cycles for the tart color writing and PF/BK color resetting need to be perfectly aligned, but all the rest of the cycles can be re-arranged to allow the 3 kernel versions. Each version would write the food item graphics at different times, depending on where they are on the screen.

Edited by JeremiahK
  • Like 2
Link to comment
Share on other sites

Also, this example uses rainbow color graphics that are pre-loaded into RAM to save 1 cycle per read (2 reads). Since there are 2 cycles to spare, it may be possible to read from ROM instead (using pointers), using every cycle, as long as it is still possible to rearrange the writes to the food item graphics. This would be optimal for obvious reasons. :D

Edited by JeremiahK
Link to comment
Share on other sites

I have finished a working test demo of the kernel, and it can draw the cat and rainbow properly, along with food items. Note that the food items are not actually drawn correctly (they are both the same), but it is actually updating the graphics and color for player 1 twice per scanline. I just wanted to share this with you all.

 

Please keep in mind that this is not at all final. Ignore the crazy playfield bars and bland grey colors. Also, good luck if you try to look at the code (it's a mess right now). There is no engine controling the movement of the food items, their position is just set to modulus 64 of the frame count to show that they can move. I would have added a simple way to animate the rainbow, but it would need to be re-written anyway, so I didn't bother.

 

I also had some fun today making the food item graphics. There are 16 items total, one blank, six fruits (yummy items), six veggies (yucky items, health loss), two high point-value items, and a health item. The kernel currently flickers the food items so I could test the look on a real 2600, and they look pretty good if I do say so myself.

 

Hh1tWdU.png

nyancat.bin

  • Like 3
Link to comment
Share on other sites

  • 2 weeks later...

You've got a bug in your code.

 

post-3056-0-69075700-1513040420_thumb.png

 

As a developer, you should always do this in Stella:

  1. enter the debugger (hit `)
  2. select the TIA tab
  3. check the option Drive unused TIA pins randomly on a read/peek
  4. select the I/O tab
  5. check the 6 options below When loading a ROM: to randomize everything

and you'll now be able to recreate the bug. Most likely what's up is somewhere in your code is an LDA $XX instruction that's supposed to be an LDA #$XX instruction.

 

Tracking down and fixing your bug should help you to understand why we suggested this to you in the past ;) (there's some nice screenshots there showing exactly what to check)

  • Like 1
Link to comment
Share on other sites

I am sifting through all the code, trying to find the bug.

I created a file to declare constants for the TIA values I am using that can be ORed together during assembly. This way, instead of having something confusing like this:

lda #%00010001
sta CTRLPF

lda #%00010011
sta NUSIZ0
sta NUSIZ1

I can have something much easier to read, like this:

lda #BALL_SIZE_2 | PF_REFLECT
sta CTRLPF

lda #MSL_SIZE_2 | THREE_CLOSE
sta NUSIZ0
sta NUSIZ1

Is this the correct syntax for doing this?

Link to comment
Share on other sites

If the problem is a load ZP in place of what was supposed to be a load # you could probably find it with a regex search pretty quickly. Something like ld[a-z] [^#]\d should find all the loads that are loading an arbitrary address instead of an immediate value. Of course this is assuming you've used labels for all your addresses and won't intentionally be doing lda $f000 instead of lda MyData.

 

It would be cool if you could configure dasm to error out when a load is attempted with a number instead of a label and it's not an immediate addressing mode.

  • Like 1
Link to comment
Share on other sites

OK, so I just found the bug. In the rows before and after the cat's rows, I had temporarily set it up to draw 14 empty scanlines, but instead of loading Y with #14, I was loading it with 14, exactly as you suspected. This obviously screwed up the scanline count bigtime.

 

I'm just amazed that the code worked at all. The bug has been there for months. I had even been testing it on real hardware, and never had an issue. Thanks again for bringing this to my attention!

Edited by JeremiahK
Link to comment
Share on other sites

Here's a new update. There are now two moving food items being drawn on each row, including the row with the cat. The row beneath the cat is blank, but ignore that for now.

 

Right now Player0's position is only being set once, before the first row. It will eventually be reset every row, making it possible to have each row's food items uniquely aligned.

 

I have discovered a strange issue, however. I am storing each row's food position in RAM as the number of color clocks to skip before drawing the first copy of the player. The position can be in the range of 0-88. This morning, it worked perfectly, so that a position of 0 would put the first player copy at the extreme left edge of the screen, while a position of 88 would do the opposite for the second player copy. Now, the player is shifted one color clock to the right for some reason. I can't imagine why this happened, as I didn't touch the player positioning code. I thought it might have been caused by a page boundary that moved, but I would expect a shift of 3 color clocks, not 1.

 

RTAfggy.png

nyancat.bin

Edited by JeremiahK
  • Like 3
Link to comment
Share on other sites

I have added player repositioning before every row, so now each one can have a unique food position and speed. I'm not doing anything fancy for the speeds right now, it's just a simple subtraction or shift from the previous row's position. It would be nice to have multiple row speeds as a game option, but if I want fine speed control, I will have to use more RAM.

 

I think I will take a break from adding features to the spaghetti dinner my code has become, and start optimizing it, managing pages, and otherwise cleaning it up. Code, polish, rinse, repeat.

nyancat.bin

  • Like 1
Link to comment
Share on other sites

It would be nice to have multiple row speeds as a game option, but if I want fine speed control, I will have to use more RAM.

 

You can pull off 8 speeds by using superfluous bits within your pointers. Per your source you're using $F000 as the start of your cartridge. If one of your pieces of graphic data were to be located at say $F456, then due to how the Atari's designed these 8 values all point to that same image:

  • $1456
  • $3456
  • $5456
  • $7456
  • $9456
  • $b456
  • $d456
  • $f456

This is known as mirrored memory, and it's not just the ROM that's mirrored - everything in the 2600 shows up in multiple locations. Kroko posted some handy files in this topic.

 

If you look at those values in binary you'll see them as:

  • %0001010001010110
  • %0011010001010110
  • %0101010001010110
  • %0111010001010110
  • %1001010001010110
  • %1011010001010110
  • %1101010001010110
  • %1111010001010110

and can see that the upper 3 bits are unique, while the rest are all the same. So you can use those upper 3 bits to select from 8 different speeds and not need any extra RAM.

 

To retrieve the speed you'd do this:

lda FoodGfxPtr1+1 ; get the high-byte of pointer
lsr ; 5 bit shifts right
lsr
lsr
lsr
lsr
; at this point A has the value of 0-7


If you want to set the speed to 2, you'd do this:

lda FoodGfxPtr1+1   ; get the high-byte of pointer
and #%00011111      ; remove the current speed
sta FoodGfxPtr1+1   ; save the graphic pointer (lower 5 bits)
lda #2 ; set speed to 2
asl ; 5 bit shifts left
asl
asl
asl
asl
ora FoodGfxPtr1+1 ; merge the speed (upper 3 bits of the accumulator) with the graphic pointer (lower 5 bits of RAM)
sta FoodGfxPtr1+1 ; and save


  • Like 2
Link to comment
Share on other sites

Why wouldn't you just load #2 << 5?

Sure, was showing how to get a value of 0-7 shifted to the correct bit location which would be useful if a menu option was setting initial speeds.

 

lda FoodGfxPtr1+1   ; get the high-byte of pointer
and #%00011111      ; remove the current speed
sta FoodGfxPtr1+1   ; save the graphic pointer (lower 5 bits)
lda #2 << 5 ; set speed to 2 (DASM shifts it to upper 3 bits at compile time)
ora FoodGfxPtr1+1 ; merge the speed (upper 3 bits of the accumulator) with the graphic pointer (lower 5 bits of RAM)
sta FoodGfxPtr1+1 ; and save

On that note, this would increase the speed by 1:

clc
lda FoodGfxPtr1+1
adc #%00100000
sta FoodGfxPtr1+1

while this would decrease it by 1

sec
lda FoodGfxPtr1+1
sbc #%00100000
sta FoodGfxPtr1+1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...