Robert Gremillion Posted May 5, 2022 Share Posted May 5, 2022 I am drawing these 2 sprites and want to reduce the cycles in the kernel. What are the better methods? I am looping through x 96 times... Thanks, .IsInsideSpriteP0Check: ; check if should render sprite player0 txa ; 2 transfer X to A sec ; 2 make sure carry flag is set sbc RiderYPos ; 3 subtract sprite Y coordinate cmp #RIDER_HEIGHT ; 2 are we inside the sprite height bounds? bcc .DrawSpriteP0 ; 2 if result < SpriteHeight, call subroutine lda #0 ; 2 else, set lookup index to 0 .DrawSpriteP0: tay ; 2 load Y so we can work with pointer lda (RiderSpritePtr),Y ; 5 load player bitmap slice of data sta GRP0 ; 3 set graphics for player 0 .IsInsideSpriteP1Check: ; check if should render sprite player1 txa ; 2 transfer X to A sec ; 2 make sure carry flag is set sbc CoasterYPos ; 3 subtract sprite Y coordinate cmp #COASTER_HEIGHT ; 2 are we inside the sprite height bounds? bcc .DrawSpriteP1 ; 2 if result < SpriteHeight, call subroutine lda #0 ; 2 else, set index to 0 .DrawSpriteP1: tay ; 2 lda (CoasterSpritePtr),Y ; 5 load player bitmap slice of data sta GRP1 ; 3 set graphics for player 0 lda (CoasterColorPtr),Y ; 5 load player color from lookup table sta COLUP1 ; 3 set color for player 0 slice Thank you! Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted May 6, 2022 Share Posted May 6, 2022 There are usually trade-offs in these things. This might help you... 1 Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted May 6, 2022 Share Posted May 6, 2022 Just in case you weren't aware; your cycle counts look OK... but remember the branch is +1 cycle when taken, and +1 more cycle if the branch crosses a page boundary. 1 Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 6, 2022 Author Share Posted May 6, 2022 1 hour ago, Andrew Davie said: Just in case you weren't aware; your cycle counts look OK... but remember the branch is +1 cycle when taken, and +1 more cycle if the branch crosses a page boundary. Thanks for responding. I will see if I can get that method to work. I thought I saw another method that took 15 cycles??? Did I dream that? ? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 6, 2022 Share Posted May 6, 2022 22 minutes ago, Robert Gremillion said: I thought I saw another method that took 15 cycles??? Did I dream that? ? Using a mask takes 13 cycles for monochrome player, 21 for multicolor. Trade off is it uses more RAM and ROM. 1 Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 6, 2022 Author Share Posted May 6, 2022 21 minutes ago, SpiceWare said: Using a mask takes 13 cycles for monochrome player, 21 for multicolor. Trade off is it uses more RAM and ROM. I don't understand what's happening with a Mask. I have this sprite that can be monochrome. RiderSprite: .byte #%00000000 ; .byte #%00011000 ; ## .byte #%00100100 ; # # .byte #%01101010 ; ## # # .byte #%11100110 ; ## ## .byte #%11101010 ; ## # # .byte #%10100101 ; # # # # .byte #%10011001 ; # ## # .byte #%10000001 ; # # Does the mask match the size of the sprite? Or does it match the size of the arena? Thanks! 21 minutes ago, SpiceWare said: Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 6, 2022 Share Posted May 6, 2022 the mask is a bunch of $00, followed by enough $FF to match the height of your image, followed by a bunch of $00. When you set the pointer for the mask you calculate it so that the $FF section will be read during the same scanlines that the graphics should show up. During the kernel: Above the graphic the AND (MASK),y points at a $00. Any value AND $00 = $00, so no graphic is put into GRP0. During the graphic the AND (MASK),y points at a $FF. Any value AND $FF = the value, so the graphic data is put into GRP0. Below the graphic the AND (MASK),y points at a $00. Any value AND $00 = $00, so no graphic is put into GRP0. Do note that if your use a mask large enough to cover the screen you'll end up crossing the page, which adds a +1 to the cycle count, so it would be 14 cycles instead of 13. For Stay Frosty I used zones (each platform is the bottom of a zone), so the mask only had to be large enough for the biggest zone. Using zones uses more RAM as you need a graphic pointer and a mask pointer for each zone. If you're not able to grasp it I can write you up a quick demo, but it won't be until next week as I have family in town. 3 Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 6, 2022 Author Share Posted May 6, 2022 5 minutes ago, SpiceWare said: If you're not able to grasp it I can write you up a quick demo, but it won't be until next week as I have family in town. I will play around with it this weekend and see if I can "get" it. I did create a post asking for a simple Mask example using my Sprite. I might need help next week if I cannot get it. Thank you for responding! P.S. I see you are in Houston! I am in Clear Lake! Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 6, 2022 Share Posted May 6, 2022 You're welcome! I'm over in Fresno, near highway 6 and FM 521. Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 6, 2022 Author Share Posted May 6, 2022 5 hours ago, SpiceWare said: If you're not able to grasp it I can write you up a quick demo, but it won't be until next week as I have family in town. Yeah, I guess I need help. The part that is messing me up is setting the Mask pointer. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted May 6, 2022 Share Posted May 6, 2022 2 hours ago, Robert Gremillion said: Yeah, I guess I need help. The part that is messing me up is setting the Mask pointer. Was able to whip up a quick demo using Step 3 of my Collect Tutorial as a starting point. mask.zip BLUE = player 0, used to show graphics without the mask applied BLACK = ball, used to show the mask GREEN = player 1, used to show graphics with the mask applied If you move the the player up, the mask moves up as well: I purposely made the 0 padding below the player too small so you can see what happens if you don't have enough 0s: ds 100, $00 ; below the player RiderMask: ds 8, $ff ds 190, $00 ; above the player The graphics and the mask are purposely intermingled with the code. I would usually put then together towards the end, along side the digit graphics, but then a bunch of 0s show up with the graphics making it difficult to see what's going on: 2 1 Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 6, 2022 Author Share Posted May 6, 2022 40 minutes ago, SpiceWare said: Was able to whip up a quick demo using Step 3 of my Collect Tutorial as a starting point. AWESOME. Thank you! Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 7, 2022 Author Share Posted May 7, 2022 2 hours ago, SpiceWare said: Was able to whip up a quick demo using Step 3 of my Collect Tutorial as a starting point. I was able to make it work!!! I made the sprites both 8 lines high so I could share the same mask graphic. I have some weird issues when it falls through the screen. My main goal was to reduce the drawing speed so I could draw double track lines. You can see the before and after videos here... I don't have enough clock cycles to color the coaster sprite. I think it looks better with the gray bottom. ldy #96 ; X counts the number of remaining scanlines .GameLineLoop: ;-------------------------------------------------------------------------------------------- .SetupPlayfield: sta WSYNC ; first scanline ldx PFOffset ; 3 03 lda $80,x ; 4 07 sta PF0 ; 3 10 lda $81,x ; 4 14 sta PF1 ; 3 17 lda $82,x ; 4 21 sta PF2 ; 3 24 ; set PF0, PF1, and PF2 playfield/terrain pattern lda (RiderSpritePtr),y ; 5 29 and (RiderMaskPtr),Y ; 5 34 sta GRP0 ; 3 37 lda $83,x ; 4 41 sta PF0 ; 3 44 lda $84,x ; 4 48 sta PF1 ; 3 51 lda $85,x ; 4 54 sta PF2 ; 3 57 ; set PF0, PF1, and PF2 playfield/terrain pattern lda (CoasterSpritePtr),Y ; 5 62 and (CoasterMaskPtr),Y ; 5 67 sta GRP1 ; 3 70 ;lda (CoasterColorPtr),y ;sta COLUP1 ;-------------------------------------------------------------------------------------------- sta WSYNC ; second scanline ldx PFOffset lda $80,x sta PF0 lda $81,x sta PF1 lda $82,x sta PF2 ; set PF0, PF1, and PF2 playfield/terrain pattern nop nop lda $83,x sta PF0 lda $84,x sta PF1 lda $85,x sta PF2 ; set PF0, PF1, and PF2 playfield/terrain pattern cpy #55 ; compare x to 55 bcs .SkipSetPlayfields ; cpy #44 ; compare x to 44 bcc .SkipSetPlayfields ; lda PFOffset ; this code is upping the offset by 6 sbc #6 ; move this code near end of frame sta PFOffset ; update if over x over 45 lines ; stop incrementing if x over 55 lines? .SkipSetPlayfields dey ; Y-- bne .GameLineLoop ; repeat next main game scanline until finished I don't know if I will keep the double lines or not. If I get rid of them I guess I could add a ball or missile? Thanks for helping me!!!! 2 Quote Link to comment Share on other sites More sharing options...
glurk Posted May 7, 2022 Share Posted May 7, 2022 (edited) 37 minutes ago, Robert Gremillion said: I don't have enough clock cycles to color the coaster sprite. I think it looks better with the gray bottom. I think that if that first part had the color change added back in, and it was EXACTLY 76 cycles (which it almost is) then the WSYNC for the second scanline could be left out and you'd still be starting exactly on cycle 0 for that line. That said, I'm not really a 2600 programmer, but I've ported a few to 8-bits... EDIT: And I suppose the 'ldx PFOffset' would need to be moved to BEFORE the first WSYNC to give the extra time... Edited May 7, 2022 by glurk Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 7, 2022 Author Share Posted May 7, 2022 9 hours ago, glurk said: EDIT: And I suppose the 'ldx PFOffset' would need to be moved to BEFORE the first WSYNC to give the extra time... I did have ldx PFOffset above the first WSYNC in one of my tests but I still didn't have enough time to get the coaster color set up. I think the two commented out lines take 8 cycles to perform. 10 hours ago, Robert Gremillion said: ;lda (CoasterColorPtr),y ;sta COLUP1 There was one more method to show the sprite without a mask. I don't know if that can be used here also to save 5 cycles from the rider being drawn??? Thanks for responding! Quote Link to comment Share on other sites More sharing options...
+MarcoJ Posted May 7, 2022 Share Posted May 7, 2022 If your bankswitching scheme has lots of free ram, can also have a huge screen height sized sprite that the kernel draws every line with no decisions required. It could be 192 bytes or 96 bytes depending if it's a 1 or 2 line kernel. The kernel loads sprite data from ram with a LDA ABCD,X or LDA ABCD,y format, depending on which register manages the screen line. Then it's up to the pre-kernel processing to blot out sections in the RAM where there is no sprite needed with "0's". The lack of decision making within the kernel allows the most efficient time-wise method to draw a sprite. But, it comes at a cost of wasting ram and precious overscan/vblank time on "rendering" the sprite. 1 Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 7, 2022 Author Share Posted May 7, 2022 12 minutes ago, MarcoJ said: If your bankswitching scheme My dream is to make something that doesn't need bankswitching. Thanks for responding! 1 Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted May 7, 2022 Share Posted May 7, 2022 The last example you posted has a 2-line kernel... in which you're setting both sprites on only one of those lines. If you're okay with the double resolution that provides, you can split your sprite graphics/color across those two lines. Do sprite 0 color/graphics one line 1 and do sprite 1 color/graphics on line 2. My Congo Bongo POC does that for it's kernel. 1 Quote Link to comment Share on other sites More sharing options...
+MarcoJ Posted May 7, 2022 Share Posted May 7, 2022 1 minute ago, Robert Gremillion said: My dream is to make something that doesn't need bankswitching. The 4K ROM / 128byte RAM programming model is the purest form of 2600 programming. It is thrilling and humbling to see programmers still trying to push the console to its limits within the very restricted boundaries, despite there being a growing array of "turbocharger" addons available these days. 1 1 Quote Link to comment Share on other sites More sharing options...
Robert Gremillion Posted May 7, 2022 Author Share Posted May 7, 2022 50 minutes ago, splendidnut said: The last example you posted has a 2-line kernel... in which you're setting both sprites on only one of those lines. If you're okay with the double resolution that provides, you can split your sprite graphics/color across those two lines. Do sprite 0 color/graphics one line 1 and do sprite 1 color/graphics on line 2. My Congo Bongo POC does that for it's kernel. I tried to re-arrange the lines like this but had no luck getting the track lines to look OK. I will try again on Sunday and see if I can squeeze this down. Thanks for responding!!! Quote Link to comment Share on other sites More sharing options...
Ecernosoft Posted August 18, 2022 Share Posted August 18, 2022 On 5/7/2022 at 7:59 AM, MarcoJ said: The 4K ROM / 128byte RAM programming model is the purest form of 2600 programming. It is thrilling and humbling to see programmers still trying to push the console to its limits within the very restricted boundaries, despite there being a growing array of "turbocharger" addons available these days. See It's Conner time which complies with those ristrictions, includes a (Hopefully not terrible) sound track and is only just over 2K. Quote Link to comment Share on other sites More sharing options...
Ecernosoft Posted August 18, 2022 Share Posted August 18, 2022 On 5/7/2022 at 7:58 AM, splendidnut said: The last example you posted has a 2-line kernel... in which you're setting both sprites on only one of those lines. If you're okay with the double resolution that provides, you can split your sprite graphics/color across those two lines. Do sprite 0 color/graphics one line 1 and do sprite 1 color/graphics on line 2. My Congo Bongo POC does that for it's kernel. I think you need to mention that it means while you have a 2-scanline kernal, you can have finer vertical movement because you have VDELP0 and VDELP1. So you can have an 8 bit YPOS instead of a 7 bit one. Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted August 18, 2022 Share Posted August 18, 2022 37 minutes ago, Ecernosoft said: I think you need to mention that it means while you have a 2-scanline kernal, you can have finer vertical movement because you have VDELP0 and VDELP1. So you can have an 8 bit YPOS instead of a 7 bit one. I don't need to mention anything... you just did. Quote Link to comment Share on other sites More sharing options...
Ecernosoft Posted August 18, 2022 Share Posted August 18, 2022 Just now, splendidnut said: I don't need to mention anything... you just did. I meant to say "Forgot" instead of "Need" there. Quote Link to comment Share on other sites More sharing options...
+splendidnut Posted August 18, 2022 Share Posted August 18, 2022 1 minute ago, Ecernosoft said: I meant to say "Forgot" instead of "Need" there. I probably didn't forget to mention that either. My Congo Bongo POC doesn't currently use VDELPx for the sprites on the playfield. Only for the score kernel. 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.