+Andrew Davie Posted August 27, 2019 Share Posted August 27, 2019 (edited) I think you are still not quite getting it. Consider the diagram above. In the section marked "HORIZONTAL BLANK", there is NOTHING being displayed on the TV. It's when the TV beam is starting "off the left edge of the visible screen" so to speak. When you write to WSYNC, you are synchronising the CPU with the TIA, so as soon as you do that write, the very next thing is that the TIA is at colour clock 0 and you're ready to setup the scanline - and you do the first PF0, PF1, PF2 writes before the TIA starts displaying them. Now, the PF0 is not displayed until TIA colour clock 68. That's about 22 CPU cycles later. (68/3). So, for those 22 CPU cycles you can start to get busy writing to PF0, PF1 and PF2. You want to write PF0 before it starts displaying (cycle 22 ish). You want to write PF1 before it starts displaying (about cycle 28), and PF2 before it starts displaying (about cycle 39). You don't need ANY sleeps in there, you just bang bang bang write PF0 PF1 and PF2. Once you've done that, the scanline is probably approaching half-done. You need to WAIT until PF0 is finished drawing before you write the new PF0 data for the right-hand side of the screen. So, PF0 right-side starts displaying around cycle 49. But PF0 left-side doesn't finish until cycle 28-ish. So, you need to SLEEP until the cycle is after 28, and then BANG you write PF0 so the right-side is setup and register has the data for when the TIA gets to the right-half and starts displaying PF0. Meanwhile, you are ready to write PF1. You can't do it while the left PF1 is being displayed - and that ends on cycle 38-ish. So, make sure you SLEEP at least until cycle 38... PF1 now finished drawing on left side... and BANG you write PF1 for the right side. Note that PF1 doesn't start displaying until cycle 55-ish. But you've written to the register well before that, hopefully, so it's all setup. And it's the same with right-side PF2. Wait until left-side PF2 has finished drawing... and... BANG. Once you've done the three writes for the right-side... you're basically done. You are just effectively waiting for the end of the line. So at that point, you do your line count decrement, and branch back to the start of the loop. And at the start of the loop... a WSYNC... which will halt the CPU until the very start of the NEXT scanline. Edited August 27, 2019 by Andrew Davie Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 29, 2019 Author Share Posted August 29, 2019 On 8/27/2019 at 12:28 AM, Andrew Davie said: I think you are still not quite getting it. Consider the diagram above. In the section marked "HORIZONTAL BLANK", there is NOTHING being displayed on the TV. It's when the TV beam is starting "off the left edge of the visible screen" so to speak. When you write to WSYNC, you are synchronising the CPU with the TIA, so as soon as you do that write, the very next thing is that the TIA is at colour clock 0 and you're ready to setup the scanline - and you do the first PF0, PF1, PF2 writes before the TIA starts displaying them. Now, the PF0 is not displayed until TIA colour clock 68. That's about 22 CPU cycles later. (68/3). So, for those 22 CPU cycles you can start to get busy writing to PF0, PF1 and PF2. You want to write PF0 before it starts displaying (cycle 22 ish). You want to write PF1 before it starts displaying (about cycle 28), and PF2 before it starts displaying (about cycle 39). You don't need ANY sleeps in there, you just bang bang bang write PF0 PF1 and PF2. Once you've done that, the scanline is probably approaching half-done. You need to WAIT until PF0 is finished drawing before you write the new PF0 data for the right-hand side of the screen. So, PF0 right-side starts displaying around cycle 49. But PF0 left-side doesn't finish until cycle 28-ish. So, you need to SLEEP until the cycle is after 28, and then BANG you write PF0 so the right-side is setup and register has the data for when the TIA gets to the right-half and starts displaying PF0. Meanwhile, you are ready to write PF1. You can't do it while the left PF1 is being displayed - and that ends on cycle 38-ish. So, make sure you SLEEP at least until cycle 38... PF1 now finished drawing on left side... and BANG you write PF1 for the right side. Note that PF1 doesn't start displaying until cycle 55-ish. But you've written to the register well before that, hopefully, so it's all setup. And it's the same with right-side PF2. Wait until left-side PF2 has finished drawing... and... BANG. Once you've done the three writes for the right-side... you're basically done. You are just effectively waiting for the end of the line. So at that point, you do your line count decrement, and branch back to the start of the loop. And at the start of the loop... a WSYNC... which will halt the CPU until the very start of the NEXT scanline. Finally managed to get the titlescreen working with 1 very minor issue, my scanline count went back down to 229.? Other then the sleep's to push everything into place, nothing else had changed in the kernel. ? Source: https://www.dropbox.com/sh/z6wn1u7hmrnflli/AACXSWLGETd7zEjWnhWELg4oa?dl=0 Quote Link to comment Share on other sites More sharing options...
+Karl G Posted August 29, 2019 Share Posted August 29, 2019 Do you understand how to adjust the scan line count with WSYNC loops on either side of your visible content when you make changes that affect the scanline count? It should be as simple as just adjusting one or two counters every time you make changes like that. Quote Link to comment Share on other sites More sharing options...
+Karl G Posted August 29, 2019 Share Posted August 29, 2019 Also, it looks like your cycle count is off by 3 (after WSYNC). The right PF2 data must be written after cycle 50, not 58 (which you do in your loop, but the cycle count is wrong in comments, as is your comment about when to write PF2): sta WSYNC ; (3 0) Wait for the previous line to finish lda pf0dataleft,y ; (4 7) load left pf0 data into the acumulator sta PF0 ; (3 10) and store it lda pf1dataleft,y ; (4 14) load left pf1 data into the acumulator sta PF1 ; (3 17) and store it lda pf2dataleft,y ; (4 21) load left pf2 data into the acumulator sta PF2 ; (3 24) and store it lda pf0dataright,y ; (4 28) load right pf0 data into the acumulator sta PF0 ; (3 31) and store it *MUST OCCUR AFTER CYCLE 28* SLEEP 2 ; (2 33) sleep for 2 cycles lda pf1dataright,y ; (4 37) load right pf1 data into the acumulator sta PF1 ; (3 40) and store it *MUST OCCUR AFTER CYCLE 38* SLEEP 12 ; (12 52) sleep for 12 cycles lda pf2dataright,y ; (4 56) load right pf2 data into the acumulator sta PF2 ; (3 59) and store it *MUST OCCUR AFTER CYCLE 58* dex ; (2 61) decrement x bne ScanLoop_TitleScreen ; (2/3 63/64) and repeat if we're not finished with all the scanlines. ldx #02 ; (2 65/66) load 2 into x register dey ; (2 67/68) subtract one off the line counter thingy bne ScanLoop_TitleScreen ; (2/3 69/70 70/71) and repeat if we're not finished with all the scanlines. ldy #16 ; (2 72/73 73/74) 16 scanlines of padding on the bottom What is the remaining minor issue? Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 30, 2019 Author Share Posted August 30, 2019 (edited) 12 hours ago, Karl G said: Also, it looks like your cycle count is off by 3 (after WSYNC). The right PF2 data must be written after cycle 50, not 58 (which you do in your loop, but the cycle count is wrong in comments, as is your comment about when to write PF2): sta WSYNC ; (3 0) Wait for the previous line to finish lda pf0dataleft,y ; (4 7) load left pf0 data into the acumulator sta PF0 ; (3 10) and store it lda pf1dataleft,y ; (4 14) load left pf1 data into the acumulator sta PF1 ; (3 17) and store it lda pf2dataleft,y ; (4 21) load left pf2 data into the acumulator sta PF2 ; (3 24) and store it lda pf0dataright,y ; (4 28) load right pf0 data into the acumulator sta PF0 ; (3 31) and store it *MUST OCCUR AFTER CYCLE 28* SLEEP 2 ; (2 33) sleep for 2 cycles lda pf1dataright,y ; (4 37) load right pf1 data into the acumulator sta PF1 ; (3 40) and store it *MUST OCCUR AFTER CYCLE 38* SLEEP 12 ; (12 52) sleep for 12 cycles lda pf2dataright,y ; (4 56) load right pf2 data into the acumulator sta PF2 ; (3 59) and store it *MUST OCCUR AFTER CYCLE 58* dex ; (2 61) decrement x bne ScanLoop_TitleScreen ; (2/3 63/64) and repeat if we're not finished with all the scanlines. ldx #02 ; (2 65/66) load 2 into x register dey ; (2 67/68) subtract one off the line counter thingy bne ScanLoop_TitleScreen ; (2/3 69/70 70/71) and repeat if we're not finished with all the scanlines. ldy #16 ; (2 72/73 73/74) 16 scanlines of padding on the bottom What is the remaining minor issue? Nothing the scanline count is the remaining issue. The thing is if you look at the number of bytes for the titlescreen and game playfield you will notice they are almost exactly the same minus the padding on the top and bottom of the titlescreen to save some space. While it's true that I could easily fix it by increasing the padding, my main concern is if both modes use the same number of scanline, why am i coming up short for the titlescreen? The sta WSYNC ; (3 0) Wait for the previous line to finish resets the cycle count to 0, but additionally take 3 cycles to complete which I add to the next instruction. Edited August 30, 2019 by Mallard Games Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 30, 2019 Share Posted August 30, 2019 11 minutes ago, Mallard Games said: sta WSYNC resets the cycle count to 0, but additionally take 3 cycles to complete which I add to the next instruction. No. You are not understanding what is happening. The write to WSYNC halts the CPU. Dead. As soon as you execute that 3 cycle instruction, and the write actually happens, the CPU is halted. It is only then re-enabled when the TIA gets to clock cycle #0 on the next line. And then the CPU starts 'working' again. And it is precisely in synch with the TIA insofar as the first instruction the CPU executes... starts with the TIA clock at zero. That's why you DO NOT count the WSYNC cycle times as part of the scanline about to be drawn. However, it DOES count for the previous scanline - those 3 cycles are a part of that previous line, and can push the line cycle count over 76 if you are not careful! So, again, count it as part of the previous scanline, not the current one. 1 Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 30, 2019 Author Share Posted August 30, 2019 12 minutes ago, Andrew Davie said: No. You are not understanding what is happening. The write to WSYNC halts the CPU. Dead. As soon as you execute that 3 cycle instruction, and the write actually happens, the CPU is halted. It is only then re-enabled when the TIA gets to clock cycle #0 on the next line. And then the CPU starts 'working' again. And it is precisely in synch with the TIA insofar as the first instruction the CPU executes... starts with the TIA clock at zero. That's why you DO NOT count the WSYNC cycle times as part of the scanline about to be drawn. However, it DOES count for the previous scanline - those 3 cycles are a part of that previous line, and can push the line cycle count over 76 if you are not careful! So, again, count it as part of the previous scanline, not the current one. Dead, as in completely stopped in it's tracks after the write happens until we're ready to start a new scanline??? You mean like the visual above. ^^^ Ok, then if that is the case then now i understand, but how exactly do you tag previous line counts or you just don't? Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 30, 2019 Share Posted August 30, 2019 (edited) 3 minutes ago, Mallard Games said: Dead, as in completely stopped in it's tracks after the write happens until we're ready to start a new scanline??? You mean like the visual above. ^^^ Ok, then if that is the case then now i understand, but how exactly do you tag previous line counts or you just don't? Yep. Dead stopped. You just have to make sure that CURRENT line (just drawn) uses no more than 73 cycles IF you are using WSYNC to wait for the start of the next line. Don't think of WSYNC as "start this line" so much as "end this line and stop until the start of the NEXT line". Of course, you don't need to use WSYNC at all, provided your cycle count on a line is EXACTLY 76. Sometimes you need those extra 3 cycles, and so you time everything, the whole screen, to the exact cycle, using 76 cycles on each and every line. And no WSYNCs. You can do it that way if you wish, but of course it's MUCH easier to include WSYNCS and just make sure you use no more than 73 cycles/line. Edited August 30, 2019 by Andrew Davie clarified WSYNC Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted August 30, 2019 Author Share Posted August 30, 2019 19 hours ago, Mallard Games said: Nothing the scanline count is the remaining issue. The thing is if you look at the number of bytes for the titlescreen and game playfield you will notice they are almost exactly the same minus the padding on the top and bottom of the titlescreen to save some space. While it's true that I could easily fix it by increasing the padding, my main concern is if both modes use the same number of scanline, why am i coming up short for the titlescreen? Still haven't figured out why if both kernels use the same number of scanline, why one comes out short while the other is over 262. Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted August 30, 2019 Share Posted August 30, 2019 1 hour ago, Mallard Games said: Still haven't figured out why if both kernels use the same number of scanline, why one comes out short while the other is over 262. Branches or data crossing pages add +1 to cycle counts. If this pushes the scanline over 76 cycles (including 3 for WSYNC at end of line), then the TIA will have already started drawing the next line. The WSYNC will push it to the line after that. That's one possibility. Another is that you have different values in your wait lines at beginning and/or end of the screen draws. The ones that "pad" the screens. 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.