JeremiahK Posted November 23, 2017 Author Share Posted November 23, 2017 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! Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted November 25, 2017 Author Share Posted November 25, 2017 (edited) 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 November 25, 2017 by JeremiahK 2 Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted November 25, 2017 Author Share Posted November 25, 2017 (edited) 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. Edited November 25, 2017 by JeremiahK Quote Link to comment Share on other sites More sharing options...
vidak Posted November 25, 2017 Share Posted November 25, 2017 Nice!! Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted November 27, 2017 Author Share Posted November 27, 2017 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. nyancat.bin 3 Quote Link to comment Share on other sites More sharing options...
TheHoboInYourRoom Posted November 27, 2017 Share Posted November 27, 2017 This is incredible already! 1 Quote Link to comment Share on other sites More sharing options...
vidak Posted November 28, 2017 Share Posted November 28, 2017 Yeah this is /very/ good. I am very jealous. 1 Quote Link to comment Share on other sites More sharing options...
Tjoppen Posted December 10, 2017 Share Posted December 10, 2017 That's a very clever way of drawing this kitty ? 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 12, 2017 Share Posted December 12, 2017 You've got a bug in your code. As a developer, you should always do this in Stella: enter the debugger (hit `) select the TIA tab check the option Drive unused TIA pins randomly on a read/peek select the I/O tab 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) 1 Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 12, 2017 Author Share Posted December 12, 2017 (edited) 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 December 12, 2017 by JeremiahK Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 12, 2017 Author Share Posted December 12, 2017 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? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 12, 2017 Share Posted December 12, 2017 Yep, that's the way to do it. 1 Quote Link to comment Share on other sites More sharing options...
ZackAttack Posted December 12, 2017 Share Posted December 12, 2017 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. 1 Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 12, 2017 Author Share Posted December 12, 2017 (edited) 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 December 12, 2017 by JeremiahK Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 12, 2017 Share Posted December 12, 2017 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). Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 12, 2017 Author Share Posted December 12, 2017 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. Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 13, 2017 Author Share Posted December 13, 2017 (edited) 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. nyancat.bin Edited December 13, 2017 by JeremiahK 3 Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 13, 2017 Author Share Posted December 13, 2017 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. Quote Link to comment Share on other sites More sharing options...
Tjoppen Posted December 13, 2017 Share Posted December 13, 2017 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 Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 13, 2017 Author Share Posted December 13, 2017 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. 1 Quote Link to comment Share on other sites More sharing options...
JeremiahK Posted December 14, 2017 Author Share Posted December 14, 2017 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 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 14, 2017 Share Posted December 14, 2017 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 2 Quote Link to comment Share on other sites More sharing options...
CPUWIZ Posted December 14, 2017 Share Posted December 14, 2017 Why wouldn't you just load #2 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted December 14, 2017 Share Posted December 14, 2017 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 Quote Link to comment Share on other sites More sharing options...
CPUWIZ Posted December 14, 2017 Share Posted December 14, 2017 Gotcha, could be confusing for newer programmers, is all. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.