Jump to content
IGNORED

Loop Counter Basics


Mallard Games

Recommended Posts

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.

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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 by Mallard Games
Link to comment
Share on other sites

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.

 

 

  • Thanks 1
Link to comment
Share on other sites

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 by Andrew Davie
Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...