Dagger Posted February 19 Share Posted February 19 Been working on a clone of Bomberman as a project to further learn the art of coding the 2600. I feel like I'm hitting a bit of a wall with Playfield drawing, and getting the code in shape so that there's plenty of cycles to draw multiple sprites, missiles, and the like. The current Playfield + P0 sprite code I have, though it doesn't feel like is doing much, is taking up more cycles than I expect. It's also causing the P0 sprite to become corrupted depending on where the player is standing. This is leaving me not feeling confident about adding P1 sprites and missiles to the draw loop, and I'm feeling at a bit of an impasse on the direction I should take. Is the setup I have telling me that I should be working on a 2-line kernel, or doing something smarter about the draw loop such that I'm not processing as much data per wsync? A little bit about the setup: I have a playfield setup that updates every 15 lines. The arena only uses PF1 and PF2, so I don't update PF0 at all (I was hoping that this approach was going to save me a nice amount of cycles). In the screenshot, you can see how standing in certain parts of the screen results in the sprite becoming corrupted as the PF0 is getting written too as the beam is drawing. This tells me that I need to be writing to them earlier or later, but so far my attempts at doing so result in the problem getting pushed over to the playfield, which starts its own flickering. Here's the portion of code that draws the gameplay arena ; Cycles Total - Comment .SLINE_LOOP ; - Gameplay Zone Scanline Loop sta WSYNC ; 3 0/78 - Start new Scanline .ARENA_COUNT_DOWN ; (7/8 Cycles) - Every 15 scanlines update PF1 and PF2 dec ARENACOUNTER ; 5 5 - Count down arena draw counter bne .INSIDE_P0 ; 2/3 7/9 - Jump to sprite check if no arena update needed .RST_ARENA_COUNTER ; (5 Cycles) - [UPDATE ARENA] Reset update counter lda #15 ; 2 9 - Reset Arena map update counter sta ARENACOUNTER ; 3 12 - Store the arena draw counter .DRAW_ARENA ; (22 Cycles) - ldy ARENAINDEX ; 3 15 - Get the map data offset lda ARENA_0_PF1,y ; 4 19 - Load PF1 sta PF1 ; 3 22 - set PF1 slice lda ARENA_0_PF2,y ; 4 26 - Load PF2 sta PF2 ; 3 29 - Set PF2 slice inc ARENAINDEX ; 5 34 - Move to next line of arena map data .INSIDE_P0: ; (13/14 Cycles) - P0 Position draw check txa ; 2 36 - Transfer X to A sec ; 2 38 - Set carry before subtraction sbc P0POSY ; 3 41 - Subtract sprite Y coord cmp #P0_HGT ; 2 43 - Current scanline inside p0 sprite bounds? bcc .DRAWSPRP0 ; 2/3 45 - Draw P0 sprite routine lda #0 ; 2 47 - else, index to 0 .DRAWSPRP0: ; (23 Cycles) - P0 Draw sprite slice clc ; 2 49 - adc P0ANMSET ; 3 52 - tay ; 2 54 - load Y so we can work with pointer lda (P0SPRPTR),Y ; 5 59 - sta GRP0 ; 3 62 - set graphics for player0 lda (P0COLPTR),Y ; 5 67 - sta COLUP0 ; 3 70 - set color of player 0 .DECREMENT_SCANLINE ; (5 Cycles) - Decrement Scanline loop dex ; 2 72 - Reduce scanline counter (x) bne .SLINE_LOOP ; 3 75 - repeat until screen is drawn ;-------------------- END OF GAME PLAY ZONE Added sourcecode and compiled bin for full review. BMan2600.zip bman2600.asm.bin Quote Link to comment Share on other sites More sharing options...
easmith Posted February 20 Share Posted February 20 (edited) 2 line kernel is an easy solution, though you will lose a little detail on your sprites if they are small . Draw the sprites on different lines right after the WSYNC in the horizontal blank period. This should correct the shearing issue on the sprites. You can use the VDEL to line up the sprites . Similar for updates of colors, PF , etc. You want the object updated before it needs to be drawn . you also could do away with the arena counter and just update PFs every other line after one of the 2 line kernel WSYNCS. With a 2 line kernel you could put in an entire table for the arena and it will be half as many bytes using 2 LK Edited February 20 by easmith 2 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted February 20 Share Posted February 20 I second the 2 Line Kernel suggestion, commonly referred to as 2LK. You might like to check out Collect, my tutorial for writing a 2K game from scratch. It uses a 2LK so it can draw both players, both missiles, the ball, as well as the playfield using PF0, PF1, and PF2. Collect in action: In Stella's debug color mode, which makes it clear which red block is the ball: These are the colors Stella uses for each object in Debug Color mode: Note: there are 3 shades of purple to clearly show the 3 PF registers. Same occurs with the other objects, as seen by the 3 shades of yellow and green in Combat to show the 3 copies of player 1 and missile 1: 4 Quote Link to comment Share on other sites More sharing options...
Verdant Posted March 16 Share Posted March 16 (edited) Hi, I don't know if you're still looking for advice for this, but I've rewritten your scanline loop so that it now redraws the screen without errors/tearing... mostly. I changed the arena rows to be 16 scanlines high rather than 15, but I didn't change any of the other code, so the player character no longer lines up with the visible playfield. Despite that, what I've written might give you some ideas. The parts that I've changed are marked with the text "*ALTERATION". Even though this code now (theoretically) draws the player sprite and the background without issue, there aren't many cycles left for anything else, like placing enemies or boxes. I think some sort of solution based on switching between pre-selected "chunks", rather than using a single scanline counter for the whole screen, might open things up a bit, since you wouldn't need to do as much branching. The real issue is to change visual items at a point on each scanline when you are certain they won't be mid-draw. I started by storing the sprite data for the next line in RAM, and then pulling these right after the HBlank. Then I update the playfield right at the end of the scanline, just after PF1 has finished drawing. I also pre-filled a buffer for the arena data in RAM, and used stack instructions to load it for drawing. Finally, I changed the height of the rows to 16 so that a simple AND with the scanline counter would tell when the playfield needs to be updated. I hope it helps! bman2600_alt01.asm Edited March 16 by Verdant 1 Quote Link to comment Share on other sites More sharing options...
Dagger Posted March 23 Author Share Posted March 23 On 3/16/2024 at 5:44 AM, Verdant said: Hi, I don't know if you're still looking for advice for this, but I've rewritten your scanline loop so that it now redraws the screen without errors/tearing... mostly. I changed the arena rows to be 16 scanlines high rather than 15, but I didn't change any of the other code, so the player character no longer lines up with the visible playfield. Despite that, what I've written might give you some ideas. The parts that I've changed are marked with the text "*ALTERATION". Even though this code now (theoretically) draws the player sprite and the background without issue, there aren't many cycles left for anything else, like placing enemies or boxes. I think some sort of solution based on switching between pre-selected "chunks", rather than using a single scanline counter for the whole screen, might open things up a bit, since you wouldn't need to do as much branching. The real issue is to change visual items at a point on each scanline when you are certain they won't be mid-draw. I started by storing the sprite data for the next line in RAM, and then pulling these right after the HBlank. Then I update the playfield right at the end of the scanline, just after PF1 has finished drawing. I also pre-filled a buffer for the arena data in RAM, and used stack instructions to load it for drawing. Finally, I changed the height of the rows to 16 so that a simple AND with the scanline counter would tell when the playfield needs to be updated. I hope it helps! bman2600_alt01.asm 38.72 kB · 1 download Thanks for taking a look Verdant. I'll have a read through. Based on Darrell's feedback, I did update the code and aggressively cut things down. Just as you mentioned, I could see how few cycles I had before even beginning to look at things like enemy placement so just wanted to focus on getting the arena and basic movement done as tight as possible before getting into the fancier stuff like animation and color. I'm sure I'll learn some tricks from your changes. bman2600.asm bman2600.asm.bin 2 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.