Jump to content

Photo

Nyan Cat Game - Work in Progress

WIP work in progress 2600 Nyan Cat

102 replies to this topic

#26 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Thu Nov 23, 2017 3:17 PM

Thanks for the suggestions! That sounds like it should work nicely. I was actually planning on using the free bit in the color values, but I wouldn't need to because of PF0. Your plan should free up quite a few cycles!

#27 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Fri Nov 24, 2017 11:23 PM

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, Fri Nov 24, 2017 11:37 PM.


#28 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Fri Nov 24, 2017 11:35 PM

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, Fri Nov 24, 2017 11:38 PM.


#29 vidak OFFLINE  

vidak

    Moonsweeper

  • 424 posts
  • Location:Sydney, Australia

Posted Sat Nov 25, 2017 1:18 AM

Nice!!

#30 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Sun Nov 26, 2017 11:25 PM

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

Attached Files



#31 TheHoboInYourRoom OFFLINE  

TheHoboInYourRoom

    Moonsweeper

  • 374 posts
  • Whackadoo thingamajig
  • Location:Illinois

Posted Mon Nov 27, 2017 5:15 PM

:lust: This is incredible already!



#32 vidak OFFLINE  

vidak

    Moonsweeper

  • 424 posts
  • Location:Sydney, Australia

Posted Mon Nov 27, 2017 10:16 PM

Yeah this is /very/ good. I am very jealous.



#33 Tjoppen OFFLINE  

Tjoppen

    Chopper Commander

  • 211 posts

Posted Sun Dec 10, 2017 5:43 PM

That's a very clever way of drawing this kitty 😺

#34 SpiceWare OFFLINE  

SpiceWare

    Draconian

  • 12,204 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Mon Dec 11, 2017 7:17 PM

You've got a bug in your code.  

 

Screen Shot 2017-12-11 at 6.59.11 PM.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)



#35 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Tue Dec 12, 2017 12:51 AM

Thank you so much! I will look at that tomorrow. I remember you telling me about that before, and I thought I had done it, but I guess I forgot.

 

EDIT: Wow, I only had the box checked for "Randomize zero page/RAM".


Edited by JeremiahK, Tue Dec 12, 2017 10:47 AM.


#36 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Tue Dec 12, 2017 11:57 AM

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?



#37 SpiceWare OFFLINE  

SpiceWare

    Draconian

  • 12,204 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Tue Dec 12, 2017 12:12 PM

Yep, that's the way to do it.



#38 ZackAttack OFFLINE  

ZackAttack

    Dragonstomper

  • 688 posts
  • Location:Orlando, FL US

Posted Tue Dec 12, 2017 12:18 PM

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.



#39 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Tue Dec 12, 2017 12:28 PM

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, Tue Dec 12, 2017 12:30 PM.


#40 SpiceWare OFFLINE  

SpiceWare

    Draconian

  • 12,204 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Tue Dec 12, 2017 12:41 PM

Glad you found it!

 

I explain in reply 91 why that works on some systems, but not all.  Check replies 86 and 87 just above that for a nice tutorial on using Stella's debugger (though keep in mind my corrections in 91).



#41 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Tue Dec 12, 2017 12:45 PM

Thanks.  I love Stella's debugger, it actually helped me solve this problem.  I noticed that the Y register was being set way too high in the "waste time and draw nothing" loop, so it was pretty obvious.



#42 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Tue Dec 12, 2017 6:03 PM

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

Attached Files


Edited by JeremiahK, Tue Dec 12, 2017 6:12 PM.


#43 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Tue Dec 12, 2017 11:51 PM

I found out the answer to the timing bug.  It turns out that there is a way for 1 CPU cycle to move a player by 1 color clock.  I was using a cycle-73 HMOVE to avoid the comb lines, and it got bumped back to a cycle-72 HMOVE.  Simple as that.



#44 Tjoppen OFFLINE  

Tjoppen

    Chopper Commander

  • 211 posts

Posted Wed Dec 13, 2017 2:10 AM

It seems you don't set PF1 quite right the first line about half of the time. There's plenty of NOPs before that loop, so shouldn't be difficult to adjust I assume

Attached Thumbnails

  • nyancat.jpg


#45 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Wed Dec 13, 2017 2:17 AM

That's just an artifact that shows up in 1 of the 2 cat kernels. It has to set PF0's graphics after the cat is drawn, because of extremely tight timing constraints. The first line will have to be pre-loaded.

#46 JeremiahK OFFLINE  

JeremiahK

    Chopper Commander

  • Topic Starter
  • 162 posts
  • Location:Indiana, USA

Posted Wed Dec 13, 2017 6:38 PM

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.

Attached Files



#47 SpiceWare OFFLINE  

SpiceWare

    Draconian

  • 12,204 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Wed Dec 13, 2017 7:22 PM

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

 



#48 CPUWIZ OFFLINE  

CPUWIZ

    Commander

  • 34,002 posts
  • I am the one who knocks!
  • Location:SoCal

Posted Wed Dec 13, 2017 7:26 PM

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



#49 SpiceWare OFFLINE  

SpiceWare

    Draconian

  • 12,204 posts
  • Medieval Mayhem
  • Location:Planet Houston

Posted Wed Dec 13, 2017 7:50 PM

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


#50 CPUWIZ OFFLINE  

CPUWIZ

    Commander

  • 34,002 posts
  • I am the one who knocks!
  • Location:SoCal

Posted Wed Dec 13, 2017 7:53 PM

Gotcha, could be confusing for newer programmers, is all. :)







Also tagged with one or more of these keywords: WIP, work in progress, 2600, Nyan Cat

0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users