Revs on the BBC Micro

# Screen buffer: CopyDashData

```       Name: CopyDashData                                            [Show more]
Type: Subroutine
Category: Screen buffer
Summary: Copy the dash data from the main game code to screen memory, and
vice versa
Deep dive: The jigsaw puzzle binary
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* MainDrivingLoop (Part 1 of 5) calls CopyDashData
* MainDrivingLoop (Part 5 of 5) calls CopyDashData

Arguments:

A                    The direction of the copy:

* Bit 7 clear = copy from game code to screen memory

* Bit 7 set = copy from screen memory to game code

.CopyDashData

STA T                  \ Store A in T, so bit 7 of T determines the direction
\ of the copy

LDX #3                 \ First, we copy the four bytes at dashDataAddress to
\ P, Q, R and S, so set a loop counter in X for the four
\ bytes

.dash1

LDA dashDataAddress,X  \ Copy the X-th byte of dashDataAddress to the X-th
STA P,X                \ byte of P

DEX                    \ Decrement the loop counter

BPL dash1              \ Loop back until we have copied all four bytes

\ So we now have the following:
\
\   (Q P) = the location of the first block in the main
\           game code
\
\   (S R) = the location of the first block in screen
\           memory (i.e. at the end of screen memory, as
\           the first block in the game code is the last
\           block in screen memory)
\
\ We now copy 41 blocks of memory from one address to
\ the other, with the direction determined by the value
\ of bit 7 in T (which we set above)
\
\ We work through each block by starting at offset 79
\ from the start of (Q P) and (S R), and decrementing
\ the offset until it matches the dashDataOffset value
\ for this block
\
\ We store the block number (which goes from 0 to 40)
\ in X, and the offset (which goes from 79 down to
\ dashDataOffset,X + 1) in Y

LDX #0                 \ Set a block counter in X to count through 41 blocks

.dash2

LDY #79                \ Each block we want to copy ends at the start address
\ plus 79, so set an index counter in Y, which we can
\ use to work our way backwards through each byte in
\ the block

LDA #0                 \ Set V = 0 to act as a byte counter to go from 0 to the
STA V                  \ number of bytes copied

.dash3

BIT T                  \ If bit 7 of T is set, skip the following two
BMI dash4              \ instructions so we copy from (S R) to (Q P)

LDA (P),Y              \ Copy the Y-th byte of (Q P) to the Y-th byte of (S R)
STA (R),Y

.dash4

LDA (R),Y              \ Copy the Y-th byte of (S R) to the Y-th byte of (Q P)
STA (P),Y

INC V                  \ Increment the byte counter

DEY                    \ Decrement the index counter

TYA                    \ If Y <> the dashDataOffset value for block X, loop
CMP dashDataOffset,X   \ to keep copying the contents of this block
BNE dash3

\ We have copied a block of memory, so we now need to
\ update (Q P) and (S R) to point to the next block to
\ copy
\
\ When in screen memory, the blocks are stored one after
\ the other, in reverse order, so the address of the
\ next block to copy is the start address of the block
\ we just copied in (S R), minus the size of the block
\ we just copied, which is in V, so the next block will
\ be at (S R) - V

LDA R                  \ Set (S R) = (S R) - V
SEC                    \
SBC V                  \ starting with the low bytes
STA R

BCS dash5              \ And decrementing the high byte of (S R) if the low
DEC S                  \ byte wraps around

.dash5

\ When in the main game code, the blocks are stored
\ every &80 bytes, so the address of the next block is
\ (Q P) + &80
\
\ Note that each block takes up a different amount of
\ memory, as follows:
\
\   Block starts at: (Q P) + dashDataOffset,X + 1
\   Block ends at:   (Q P) + 79
\
\ It's the value of (Q P) that is spaced out by &80 for
\ each block, rather than the actual data in the block
\ (for each block, (Q P) to (Q P) + dashDataOffset,X
\ is used for other purposes)

LDA P                  \ Set (Q P) = (Q P) + &80
CLC                    \
ADC #&80               \ starting with the low bytes
STA P

BCC dash6              \ And incrementing the high byte of (Q P) if the low
INC Q                  \ byte overflows

.dash6

INX                    \ Increment the block counter to point to the next block
\ to copy

CPX #41                \ Loop back to copy the next block until we have copied
BNE dash2              \ all 41 blocks

RTS                    \ Return from the subroutine
```