Mallard Games Posted August 31, 2019 Share Posted August 31, 2019 When doing loops, if you want to iterate against say 64 items the formula is: x-1 for example lda #63 ; loop 64 times and not lda #64 ; loop 64 times correct? Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted August 31, 2019 Share Posted August 31, 2019 If you are using zero as part of the loop count. This: ldx #64 Loop: lda Datatable-1,x sta destination-1,x dex bne Loop ...has the same result as: ldx #63 Loop: lda Datatable,x sta destination,x dex bpl Loop The difference is that X will be #$FF at the end of the loop in the second example. X will be zero in the first, also the LDA/STA instructions will add a cycle if Datatable/destination are on page breaks. Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted September 1, 2019 Author Share Posted September 1, 2019 2 hours ago, Nukey Shay said: If you are using zero as part of the loop count. This: ldx #64 Loop: lda Datatable-1,x sta destination-1,x dex bne Loop ...has the same result as: ldx #63 Loop: lda Datatable,x sta destination,x dex bpl Loop The difference is that X will be #$FF at the end of the loop in the second example. X will be zero in the first, also the LDA/STA instructions will add a cycle if Datatable/destination are on page breaks. We're talking about this loop: ldy #64 ; Y is going to hold how many lines we have to do ; ...we're going to count scanlines here. theoretically ; since this example is ass simple, we could just repeat ; the timer trick, but often its important to know ; just what scan line we're at. sta WSYNC ; We do a WSYNC just before that so we don't turn on sta VBLANK ; End the VBLANK period with the zero ;*********************** Scan line Loop ScanLoop_TitleScreen sta WSYNC ; (3 0) Wait for the previous line to finish lda pf0dataleft,y ; (4 4) load left pf0 data into the acumulator sta PF0 ; (3 7) and store it lda pf1dataleft,y ; (4 11) load left pf1 data into the acumulator sta PF1 ; (3 14) and store it lda pf2dataleft,y ; (4 17) load left pf2 data into the acumulator sta PF2 ; (3 21) and store it lda pf0dataright,y ; (4 25) load right pf0 data into the acumulator sta PF0 ; (3 28) and store it *MUST OCCUR AFTER CYCLE 28* SLEEP 3 ; (3 31) sleep for 3 cycles lda pf1dataright,y ; (4 35) load right pf1 data into the acumulator sta PF1 ; (3 38) and store it *MUST OCCUR AFTER CYCLE 38* SLEEP 5 ; (5 43) sleep for 5 cycles lda pf2dataright,y ; (4 47) load right pf2 data into the acumulator sta PF2 ; (3 50) and store it *MUST OCCUR AFTER CYCLE 50* dey ; (2 58/59) subtract one off the line counter thingy bne ScanLoop_TitleScreen ; (2/3 60/61 61/62) and repeat if we're not finished with all the scanlines. That's 64 lines right? If I change it to: ldy #63 ; Y is going to hold how many lines we have to do ; ...we're going to count scanlines here. theoretically ; since this example is ass simple, we could just repeat ; the timer trick, but often its important to know ; just what scan line we're at. sta WSYNC ; We do a WSYNC just before that so we don't turn on sta VBLANK ; End the VBLANK period with the zero ;*********************** Scan line Loop ScanLoop_TitleScreen sta WSYNC ; (3 0) Wait for the previous line to finish lda pf0dataleft,y ; (4 4) load left pf0 data into the acumulator sta PF0 ; (3 7) and store it lda pf1dataleft,y ; (4 11) load left pf1 data into the acumulator sta PF1 ; (3 14) and store it lda pf2dataleft,y ; (4 17) load left pf2 data into the acumulator sta PF2 ; (3 21) and store it lda pf0dataright,y ; (4 25) load right pf0 data into the acumulator sta PF0 ; (3 28) and store it *MUST OCCUR AFTER CYCLE 28* SLEEP 3 ; (3 31) sleep for 3 cycles lda pf1dataright,y ; (4 35) load right pf1 data into the acumulator sta PF1 ; (3 38) and store it *MUST OCCUR AFTER CYCLE 38* SLEEP 5 ; (5 43) sleep for 5 cycles lda pf2dataright,y ; (4 47) load right pf2 data into the acumulator sta PF2 ; (3 50) and store it *MUST OCCUR AFTER CYCLE 50* dey ; (2 58/59) subtract one off the line counter thingy bpl ScanLoop_TitleScreen ; (2/3 60/61 61/62) and repeat if we're not finished with all the scanlines. would it be more efficient for looping through 64 scanlines of playfield data? Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted September 1, 2019 Share Posted September 1, 2019 Neither is more-efficient, the loop counter is doing the same thing in both. Example 1: Y counts down from 64, abandoning at 0 for a total 64 iterations Example 2: Y counts down from 63, abandoning -1 for a total 64 iterations I would like to point out that you did not subtract -1 for each of the data tables in the first example (lda pf0dataleft-1,y etc). So those lda instructions are NOT doing the same thing in both examples. As written, each of the data tables would need to be padded with a dummy byte...since the loop is abandoned immediately when Y = 0. One thing that can be an advantage using the first example is that Y is zero when the loop is over (so you can use it to clear PF registers instead of having to INY first...saving 1 byte of Rom). As stated, the drawback is that no data table in the loop can originate on a page break...or the code will suffer a +1 cycle penalty wherever it occurs. Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted September 1, 2019 Author Share Posted September 1, 2019 (edited) 1 hour ago, Nukey Shay said: Neither is more-efficient, the loop counter is doing the same thing in both. Example 1: Y counts down from 64, abandoning at 0 for a total 64 iterations Example 2: Y counts down from 63, abandoning -1 for a total 64 iterations I would like to point out that you did not subtract -1 for each of the data tables in the first example (lda pf0dataleft-1,y etc). So those lda instructions are NOT doing the same thing in both examples. As written, each of the data tables would need to be padded with a dummy byte...since the loop is abandoned immediately when Y = 0. One thing that can be an advantage using the first example is that Y is zero when the loop is over (so you can use it to clear PF registers instead of having to INY first...saving 1 byte of Rom). As stated, the drawback is that no data table in the loop can originate on a page break...or the code will suffer a +1 cycle penalty wherever it occurs. How do I subtract 1 from the data tables? This is just a snippet of the full source but, I just double checked and I do dey In both examples. I don't clear my PF registers after each scanline is that bad, should I be worried? Edited September 1, 2019 by Mallard Games Quote Link to comment Share on other sites More sharing options...
Lillapojkenpåön Posted September 1, 2019 Share Posted September 1, 2019 (edited) I think he meant that you have to add an extra line in those tables since it never loops on zero so pretend the second line is zero, I think you could just load 64 and dey at the beginning of the loop instead of bottom to keep it the same size Edited September 1, 2019 by Lillapojkenpåön Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted September 1, 2019 Author Share Posted September 1, 2019 Just reread the example he gave, he meant I should lda pf0dataleft-1,y Instead of lda pf0dataleft,y and then I can remove the padding byte. 1 Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 1, 2019 Share Posted September 1, 2019 Remember, too, that the dey/bpl version will NOT work if Y starts > 128 1 1 Quote Link to comment Share on other sites More sharing options...
Lillapojkenpåön Posted September 1, 2019 Share Posted September 1, 2019 Would that be minus? I have a basic loop question, you can use bpl with both x and y right? So if any of them is > 128 it will not loop, is that how it works? Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 1, 2019 Share Posted September 1, 2019 30 minutes ago, Lillapojkenpåön said: Would that be minus? I have a basic loop question, you can use bpl with both x and y right? So if any of them is > 128 it will not loop, is that how it works? BPL is just checking that the N flag in the status register is zero. The N-flag is set/cleared by a variety of operations, but in particular when a value in accumulator, X or Y is negative. For example, "DEY" will set the zero flag if Y=0 after the operation, and the N flag will be zero of the result is positive (<128) and 1 if negative (>=128). The various branches do not depend on the registers - they depend on the status flags. And the status flags are set by operations on any of the registers, along with a variety of other instructions (for example, 'BIT' will set/clear flags in the status register). INC and DEC also affect the status flags, but they do not operate on ANY of the registers. You can DEC variable/BPL positive. So, my comment was basically saying that if, after the "DEY" instruction, the N flag is SET (that is, if the resultant value is >=128), then the loop would not be taken. So, in other words, you can't start with a Y value of >128 because the loop won't ... loop. Yes, "128" is effectively a negative number. Remember it's 2's complement, though - so -1 is the same as %11111111 which is of course 255. 128 is -128 in two's complement thinking. 1 Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted September 1, 2019 Share Posted September 1, 2019 1 hour ago, Mallard Games said: I don't clear my PF registers after each scanline is that bad, should I be worried? I was referring to clearing the PF registers after the entire loop has run it's course...not after each scanline. Quote Link to comment Share on other sites More sharing options...
Mallard Games Posted September 2, 2019 Author Share Posted September 2, 2019 On 9/1/2019 at 2:23 AM, Nukey Shay said: I was referring to clearing the PF registers after the entire loop has run it's course...not after each scanline. Is it necessary to clear the PF register At the end if the loop? Quote Link to comment Share on other sites More sharing options...
+Andrew Davie Posted September 2, 2019 Share Posted September 2, 2019 (edited) 25 minutes ago, Mallard Games said: Is it necessary to clear the PF register At the end if the loop? Think of it like this. When the TIA needs to draw on the screen it accesses the appropriate bits in the PF registers for where it is currently drawing. And it draws whatever is there. So, if at the left of the screen it starts to draw PF0, then you better have the correct data in PF0 before it starts using it. Other than that, you don't have to worry about clearing. Just make sure the PF registers (PF0, PF1, PF2) **ALWAYS** have correct data in them before the TIA uses them. So no, you do not need to clear. But you do need to make sure the correct data is there for the NEXT line before the TIA "gets there". EDIT: So after you have finished drawing your screen, if the PF registers are non-zero, what will happen... mmh? Edited September 2, 2019 by Andrew Davie Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted September 2, 2019 Share Posted September 2, 2019 If a loop is covering the *entire* visible display, you wouldn't need to...VBLANK/on overrides the lower portion of the display until it's turned off for the top of the next frame. If you are going to have an "empty loop" of WSYNCs to fill the rest, the uncleared registers will continue to spill whatever values were last written. Likewise, the beginning of the next frame also will (until it encounters PF writes to alter the values). Incidentally, this is why vertical bars appear onscreen whenever you turn a console on without a cartridge. There's no program to instruct the console what to do, so it just spills the garbage data existing in the registers over and over (usually with an annoying audio tone, because there's no program present changing those registers either. 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.