SavedByZero Posted December 30, 2019 Share Posted December 30, 2019 (edited) Ah okay, so there are some syntatic variations. Some examples above show people using rol directly on variable names (rol PATTERN_SF1), but when I do that, it looks like it starts to rotate, but the screen then goes dark permanently. I would think this would simply rotate PATTERN one bit to the left (a mod of an earlier example program from the website, only instead of increasing the value by 1, I'm trying to rotate the bits):. iny cpy TIMETOCHANGE ; has it reached our "change point"? bne notyet ; no, so branch past ldy #1 ; reset speed count rol PATTERN notyet lda PATTERN; sta PF1; Edited December 30, 2019 by SavedByZero Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted December 30, 2019 Author Share Posted December 30, 2019 1 hour ago, SavedByZero said: Ah okay, so there are some syntatic variations. Some examples above show people using rol directly on variable names (rol PATTERN_SF1), but when I do that, it looks like it starts to rotate, but the screen then goes dark permanently. I would think this would simply rotate PATTERN one bit to the left (a mod of an earlier example program from the website, only instead of increasing the value by 1, I'm trying to rotate the bits):. iny cpy TIMETOCHANGE ; has it reached our "change point"? bne notyet ; no, so branch past ldy #1 ; reset speed count rol PATTERN notyet lda PATTERN; sta PF1; It's not a great idea to use UPPERCASE for variable names. It is convention to reserve UPPERCASE for ROM registers/names, and CONSTANTS, and use lowercase or camelCase for variables. For example, in the above snipped I can't tell if you have a bug because TIMETOCHANGE is a constant or a variable. In my code it would be a constant, written like that, and an immediately obvious bug (cpy #TIMETOCHANGE). You may like UPPERCASE, and of course you're free to use whatever you want, but conventions are there for a good reason. It helps others read and understand your code - especially useful if you want help. As to your problem, "rol" will rotate the bits in a byte, but it shifts the carry bit in to the low bit, too. So after 8 "rol" instructions, if you haven't managed your carry bit properly then you've got a blank byte, which could explain your blackness. You not only need to roll the bits, you also need to have the correct bit ready to put in that low bit (i.e., sitting in the carry). But, it gets much worse than this. You CANNOT simply roll the bits in playfield bytes and expect things to work, because of the weirdness in the orientation/flipping of the playfield display. PF0 and PF2 are mirrored, PF1 is not. PF0 only uses the top 4 bits, too. There's a diagram I did somewhere that should explain all this clearly. Quote Link to comment Share on other sites More sharing options...
SavedByZero Posted December 31, 2019 Share Posted December 31, 2019 (edited) Oh yeah, I know I have way more work ahead of me than simply rotating left; this was mainly my introduction to those commands. I was trying to see if that command did what I expected it with PF1, since PF1 is the only playfield register that's remotely straightforward. I'll deal with the others once I know what I'm doing with the commands. Anyhow, I figured out the blacking out was because I had accidentally erased a line of code that stored a positive value in the accumulator for the first overscan line, sta WSYNC. HOWEVER...I don't have a blank byte after 8 bits, now that I see it working...I have a full one. It starts as 00000001 and ends as 11111111...slowly filling with 1s as it rotates left...which was not what I expected, carry bit or no carry bit. I would have expected the carry bit to remain 0 as all those initial 0s get rotated through it, no? Edited December 31, 2019 by SavedByZero Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted December 31, 2019 Author Share Posted December 31, 2019 (edited) 5 hours ago, SavedByZero said: Oh yeah, I know I have way more work ahead of me than simply rotating left; this was mainly my introduction to those commands. I was trying to see if that command did what I expected it with PF1, since PF1 is the only playfield register that's remotely straightforward. I'll deal with the others once I know what I'm doing with the commands. Anyhow, I figured out the blacking out was because I had accidentally erased a line of code that stored a positive value in the accumulator for the first overscan line, sta WSYNC. HOWEVER...I don't have a blank byte after 8 bits, now that I see it working...I have a full one. It starts as 00000001 and ends as 11111111...slowly filling with 1s as it rotates left...which was not what I expected, carry bit or no carry bit. I would have expected the carry bit to remain 0 as all those initial 0s get rotated through it, no? The carry bit is rolled onto D0 (least significant bit), and D& (the most significant bit) is rolled off INTO the carry. You can't actually roll PF registers - they are write-only. I'm pretty sure. You roll your ram variables, and then write the result to PF registers. Edit: don't forget your carry bit is also affected by things such as compares. Edited December 31, 2019 by Andrew Davie Quote Link to comment Share on other sites More sharing options...
SavedByZero Posted December 31, 2019 Share Posted December 31, 2019 (edited) 11 hours ago, Andrew Davie said: You can't actually roll PF registers - they are write-only. I'm pretty sure. You roll your ram variables, and then write the result to PF registers. Ahh, now that would explain what I'm seeing. Thanks. Though oddly enough, rol pattern, followed by lda pattern and sta PF1 still has the same result. BTW, in session 13, you declare a ram variable named PATTERN and later call "inc PATTERN" (so I know it wasn't a constant, I don't think? I know PATTERN referenced an address, but that 'inc' call did change the value at said address. But maybe I'm confusing ram variables with a different kind of declaration) -- I was copying that format when I used it. EDIT^2: Okay, this finally worked: lda pattern; AND #%10000000 bne dontclear clc; dontclear rol pattern; notyet lda pattern So yay, I can now "scroll" the easiest part of the playfield. On to the harder stuff... Edited December 31, 2019 by SavedByZero Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted January 1, 2020 Share Posted January 1, 2020 LDA pattern ROL ROL pattern Quote Link to comment Share on other sites More sharing options...
SavedByZero Posted February 14, 2020 Share Posted February 14, 2020 (edited) Onto the "Wall" exercise. Would anyone see immediately why, when I try to increase the y register or even load a value into it, it seems to be ignored? I would think this code would draw a solid pattern for a while (I initialized the playfields to 8, across the board, earlier in the code) and then only draw side walls. However, it draws only side walls for the entire frame, as if it's never branching to "Notyet". Why is it never branching to "Notyet"? ldx #192 ldy #0 ; start y at 0 Picture iny ;increase 1 cpy #50 ;compare y to 50 bne Notyet ; if not 50, skip this next part and don't change the playfield yet. ldy #49; ;once y hits 50, go here and use this to make sure it stays at 50 when it's increased next time. lda #%00010000 ; change playfield to be mostly empty, except for the sides (mirror flag is set) sta pattern_pf0; lda #%00000000 sta pattern_pf1 sta pattern_pf2 Notyet lda pattern_pf0; sta PF0; lda pattern_pf1 sta PF1; sta PF2 lda #1 sta WSYNC ; wait till end of scanline dex cpx #0 bne Picture ;loop until it's time for the blanking period Edited February 14, 2020 by SavedByZero Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted February 14, 2020 Author Share Posted February 14, 2020 (edited) 7 hours ago, SavedByZero said: Onto the "Wall" exercise. Would anyone see immediately why, when I try to increase the y register or even load a value into it, it seems to be ignored? I would think this code would draw a solid pattern for a while (I initialized the playfields to 8, across the board, earlier in the code) and then only draw side walls. However, it draws only side walls for the entire frame, as if it's never branching to "Notyet". Why is it never branching to "Notyet"? ldx #192 ldy #0 ; start y at 0 Picture iny ;increase 1 cpy #50 ;compare y to 50 bne Notyet ; if not 50, skip this next part and don't change the playfield yet. ldy #49; ;once y hits 50, go here and use this to make sure it stays at 50 when it's increased next time. lda #%00010000 ; change playfield to be mostly empty, except for the sides (mirror flag is set) sta pattern_pf0; lda #%00000000 sta pattern_pf1 sta pattern_pf2 Notyet lda pattern_pf0; sta PF0; lda pattern_pf1 sta PF1; sta PF2 lda #1 sta WSYNC ; wait till end of scanline dex cpx #0 bne Picture ;loop until it's time for the blanking period Not sure yet what your problem is, but a few comments... Firstly, you don't show the initial values of "pattern_pf0" and "pattern_pf1" Secondly, this is not C/C++/C#, so you don't need semicolons on the end of lines... that's really just an empty comment you have there WSYNC is a strobe so that means you don't write a value to it, you just write to it. So the "lda #1" before the "sta WSYNC" is superfluous. When you decrement/increment a register or memory, the flags are set accordingly. So with "dex", when it gets to 0, the Z flag is set. Thus you do not need the "cpx #0" - that has effectively already been done as far as that particular usage goes. Ditch it. What I would suggest is using the stella emulator to step through this code. Quick usage: load the program, hit the tilde key and you get to the debugger. type "break Picture" and then "run" If things go well, you should see the program debugger stopped, and you can then "step" and watch instruction by instruction what's happening, and examine the contents of memory (e.g., "dump pattern_pf0") and see the registers. Could be useful! Edited February 14, 2020 by Andrew Davie Quote Link to comment Share on other sites More sharing options...
SavedByZero Posted February 14, 2020 Share Posted February 14, 2020 (edited) 11 hours ago, Andrew Davie said: Not sure yet what your problem is, but a few comments... Firstly, you don't show the initial values of "pattern_pf0" and "pattern_pf1" Secondly, this is not C/C++/C#, so you don't need semicolons on the end of lines... that's really just an empty comment you have there WSYNC is a strobe so that means you don't write a value to it, you just write to it. So the "lda #1" before the "sta WSYNC" is superfluous. When you decrement/increment a register or memory, the flags are set accordingly. So with "dex", when it gets to 0, the Z flag is set. Thus you do not need the "cpx #0" - that has effectively already been done as far as that particular usage goes. Ditch it. What I would suggest is using the stella emulator to step through this code. Quick usage: load the program, hit the tilde key and you get to the debugger. type "break Picture" and then "run" If things go well, you should see the program debugger stopped, and you can then "step" and watch instruction by instruction what's happening, and examine the contents of memory (e.g., "dump pattern_pf0") and see the registers. Could be useful! Force of habit with the darn semicolons. Ah, okay -- I assumed that strobing meant any positive value over 0 would set wsync to true. Initial playfield values, above all that in the once-only initialization area: lda #%11111111 sta pattern_pf1 sta pattern_pf0 sta pattern_pf2 I will definitely play with the debugger -- thanks. Edited February 14, 2020 by SavedByZero Quote Link to comment Share on other sites More sharing options...
freshbrood Posted January 29, 2021 Share Posted January 29, 2021 I apologize if this is the wrong thread to ask- but using the standard kernel with both player color kernels in bbasic, and pfcolors, have we figured out a way to remove the "stairstep" effect on the left side of the screen? On RT's page it says this is a known issue when combining the 3 kernels. It's really distracting. Also, question 2. Without using superchip ram, what is the smallest size the playfield blocks can be? Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted January 29, 2021 Author Share Posted January 29, 2021 7 hours ago, freshbrood said: Also, question 2. Without using superchip ram, what is the smallest size the playfield blocks can be? A more generic answer - Bb may be different - but assume you have about 120 bytes you're willing to devote to holding a playfield in RAM. At the very least you need 5 bytes to hold 40 bits (across) of playfield. So, 120/5 = 24 playfield blocks vertical x 40 horizontal. It's possible to have an asymmetric playfield and don't use the PF0 on either side, and then you have 32 bits of playfield per scanline. That only needs 4 bytes and therefore 120/4 = 30 playfield blocks vertical. Having said that, you'd be hard-pressed to write the rest of your game using the 8 remaining RAM bytes. 1 Quote Link to comment Share on other sites More sharing options...
CapitanClassic Posted January 29, 2021 Share Posted January 29, 2021 7 hours ago, freshbrood said: I apologize if this is the wrong thread to ask- but using the standard kernel with both player color kernels in bbasic, and pfcolors, have we figured out a way to remove the "stairstep" effect on the left side of the screen? On RT's page it says this is a known issue when combining the 3 kernels. It's really distracting. Also, question 2. Without using superchip ram, what is the smallest size the playfield blocks can be? It depends. You could make the PF blocks 1 scanline high. You could devote just 6 bytes to the Playfield, 3 for PF0, PF1, PF2 for scanline1 (Reflected) and 3 for scanline2 (PF0-PF2). Then you can cycle between the 2 RAM locations when drawing the playfield. You could do this in even less RAM, it is only for example. If you want full control over the Playfield for both left and right side of the screen you need 6 (really 5, since only 4 bits are used in PF0) bytes. You only have 128 bytes available. If you try to make the largest size arena, (160w x 192h) is a common screen resolution for NTSC, (but technically you could draw the screen taller) then you could replicate each pf block of size (4w x 9h) in RAM using 126 bytes, leaving you 2 bytes for other things. Of course, you could use RAM as pointers into the game ROM and use that to draw the screen. That would likely only require two bytes for a pointer into ROM and then copy the ROM data directly to the PF pixel registers. 1 Quote Link to comment Share on other sites More sharing options...
freshbrood Posted January 29, 2021 Share Posted January 29, 2021 (edited) Standard kernel? This sounds like you mean DPC+ ? Also I have only used bbasic. I'm not sure I know how to do this. Edited January 29, 2021 by freshbrood Quote Link to comment Share on other sites More sharing options...
freshbrood Posted January 29, 2021 Share Posted January 29, 2021 6 hours ago, Andrew Davie said: A more generic answer - Bb may be different - but assume you have about 120 bytes you're willing to devote to holding a playfield in RAM. At the very least you need 5 bytes to hold 40 bits (across) of playfield. So, 120/5 = 24 playfield blocks vertical x 40 horizontal. It's possible to have an asymmetric playfield and don't use the PF0 on either side, and then you have 32 bits of playfield per scanline. That only needs 4 bytes and therefore 120/4 = 30 playfield blocks vertical. Having said that, you'd be hard-pressed to write the rest of your game using the 8 remaining RAM bytes. I figured. Not sure if you're familiar with the Ninja Kombat port I have in development, but memory space seems crucial to make it playable at all. I can live with chunky blocks. But is there a way to eliminate the waterfall/stairstep at least? Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted January 29, 2021 Author Share Posted January 29, 2021 1 hour ago, freshbrood said: I figured. Not sure if you're familiar with the Ninja Kombat port I have in development, but memory space seems crucial to make it playable at all. I can live with chunky blocks. But is there a way to eliminate the waterfall/stairstep at least? What you are seeing may be heavily dependent on the Bb kernel you are using, and so it limited by whatever that is doing. But again, a more generic answer - if you are referring to the HMOVE blanks - the black lines at the start of every line where a HMOVE is being done - yes, it is in fact possible to get rid of these. I believe the solution is to do your HMOVE at exactly cycle 74 on the scanline. Really, these sorts of issues are good reasons to develop your own kernel. If you're using Bb, perhaps the best bet is to put up with the limitations and concentrate on the gameplay. Bb is wonderful and designed to pre-package stuff so you can do just that - gameplay - but if you start wanting tweaks and changes to the kernels, then you need to be doing things at a lower level and understand/modify the kernel code. By the time you're doing that sort of thing, you're not too far from programming in assembler anyway. 2 Quote Link to comment Share on other sites More sharing options...
RevEng Posted January 30, 2021 Share Posted January 30, 2021 It's not the HMOVE blanks he's talking about. In the bB standard kernel there's not enough cycles in the blank bit of the scanline, when you enable all of the kernel options he's talking about, so one of colour updates happens during the visible portion of the screen. Freshbrood, this is probably the wrong place to be asking these bB questions, unless you're looking to make your own kernel with priorities that suit you better. 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.