Elite on the BBC Micro and NES

# Drawing planets: PLL1 (Part 1 of 3)

## [BBC Micro disc version, Loader 3]

```       Name: PLL1 (Part 1 of 3)                                      [Show more]
Type: Subroutine
Category: Drawing planets
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* CHECK calls PLL1
* Elite loader (Part 1 of 3) calls PLL1

.PLL1

\ The following loop iterates CNT(1 0) times, i.e. &300
\ or 768 times, and draws the planet part of the

LDA VIA+&44            \ Read the 6522 System VIA T1C-L timer 1 low-order
STA RAND+1             \ counter (SHEILA &44), which decrements one million
\ times a second and will therefore be pretty random,
\ and store it in location RAND+1, which is among the
\ main game code's random seeds in RAND (so this seeds
\ the random number generator)

JSR DORND              \ Set A and X to random numbers, say A = r1

JSR SQUA2              \ Set (A P) = A * A
\           = r1^2

STA ZP+1               \ Set ZP(1 0) = (A P)
LDA P                  \             = r1^2
STA ZP

LDA #LO(OSBmod)        \ As part of the copy protection, the JSR OSB
STA OSBjsr+1           \ instruction at OSBjsr gets modified to point to OSBmod
\ instead of OSB, and this is where we modify the low
\ byte of the destination address

JSR DORND              \ Set A and X to random numbers, say A = r2

STA YY                 \ Set YY = A
\        = r2

JSR SQUA2              \ Set (A P) = A * A
\           = r2^2

TAX                    \ Set (X P) = (A P)
\           = r2^2

LDA P                  \ Set (A ZP) = (X P) + ZP(1 0)
STA ZP                 \ first adding the low bytes

TXA                    \ And then adding the high bytes

BCS PLC1               \ If the addition overflowed, jump down to PLC1 to skip
\ to the next pixel

STA ZP+1               \ Set ZP(1 0) = (A ZP)
\             = r1^2 + r2^2

LDA #1                 \ Set ZP(1 0) = &4001 - ZP(1 0) - (1 - C)
SBC ZP                 \             = 128^2 - ZP(1 0)
STA ZP                 \
\ (as the C flag is clear), first subtracting the low
\ bytes

LDA #&40               \ And then subtracting the high bytes
SBC ZP+1
STA ZP+1

BCC PLC1               \ If the subtraction underflowed, jump down to PLC1 to

\ If we get here, then both calculations fitted into
\ 16 bits, and we have:
\
\   ZP(1 0) = 128^2 - (r1^2 + r2^2)
\
\ where ZP(1 0) >= 0

JSR ROOT               \ Set ZP = SQRT(ZP(1 0))

LDA ZP                 \ Set X = ZP >> 1
LSR A                  \       = SQRT(128^2 - (a^2 + b^2)) / 2
TAX

LDA YY                 \ Set A = YY
\       = r2

CMP #128               \ If YY >= 128, set the C flag (so the C flag is now set
\ to bit 7 of A)

ROR A                  \ Rotate A and set the sign bit to the C flag, so bits
\ 6 and 7 are now the same, i.e. A is a random number in
\ one of these ranges:
\
\   %00000000 - %00111111  = 0 to 63    (r2 = 0 - 127)
\   %11000000 - %11111111  = 192 to 255 (r2 = 128 - 255)
\
\ The PIX routine flips bit 7 of A before drawing, and
\ that makes -A in these ranges:
\
\   %10000000 - %10111111  = 128-191
\   %01000000 - %01111111  = 64-127
\
\ so that's in the range 64 to 191

JSR PIX                \ Draw a pixel at screen coordinate (X, -A), i.e. at
\
\   (ZP / 2, -A)
\
\ where ZP = SQRT(128^2 - (r1^2 + r2^2))
\
\ So this is the same as plotting at (x, y) where:
\
\   r1 = random number from 0 to 255
\   r2 = random number from 0 to 255
\   (r1^2 + r2^2) < 128^2
\
\   y = r2, squished into 64 to 191 by negation
\
\   x = SQRT(128^2 - (r1^2 + r2^2)) / 2
\
\ which is what we want

.PLC1

DEC CNT                \ Decrement the counter in CNT (the low byte)

BNE PLL1               \ Loop back to PLL1 until CNT = 0

DEC CNT+1              \ Decrement the counter in CNT+1 (the high byte)

BNE PLL1               \ Loop back to PLL1 until CNT+1 = 0
```