Elite on the BBC Micro

# Drawing planets: PLL1

```       Name: PLL1                                                    [Show more]
Type: Subroutine
Category: Drawing planets
Context: See this subroutine in context in the source code
Variations: See code variations for this subroutine in the different versions
References: This subroutine is called as follows:

.PLL1

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

STA RAND+1             \ Store A in RAND+1 among the hard-coded random seeds
\ in RAND. We set A to %00001111 before calling the PLL1
\ routine, so this sets the random number generator so
\ that it always generates the same numbers every time,
\ which is probably not what was intended (other
\ versions read the 6522 System VIA timer to use as a
\ seed, which is random). As a result, if you look at
\ exactly the same, every time you run the game

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

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

\ The following loop iterates CNT2(1 0) times, i.e. &1DD
\ or 477 times, and draws the background stars on the

.PLL2

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

TAX                    \ Set X = A
\       = r3

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

STA ZP+1               \ Set ZP+1 = A
\          = r3^2 / 256

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

STA YY                 \ Set YY = r4

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

ADC ZP+1               \ Set A = A + r3^2 / 256
\       = r4^2 / 256 + r3^2 / 256
\       = (r3^2 + r4^2) / 256

CMP #&11               \ If A < 17, jump down to PLC2 to skip to the next pixel
BCC PLC2

LDA YY                 \ Set A = r4

JSR PIX                \ Draw a pixel at screen coordinate (X, -A), i.e. at
\ (r3, -r4), where (r3^2 + r4^2) / 256 >= 17
\
\ Negating a random number from 0 to 255 still gives a
\ random number from 0 to 255, so this is the same as
\ plotting at (x, y) where:
\
\   x = random number from 0 to 255
\   y = random number from 0 to 255
\   (x^2 + y^2) div 256 >= 17
\
\ which is what we want

.PLC2

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

BNE PLL2               \ Loop back to PLL2 until CNT2 = 0

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

BNE PLL2               \ Loop back to PLL2 until CNT2+1 = 0

\ The following loop iterates CNT3(1 0) times, i.e. &333
\ screen's Saturn

.PLL3

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

STA ZP                 \ Set ZP = r5

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

STA ZP+1               \ Set ZP+1 = A
\          = r5^2 / 256

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

STA YY                 \ Set YY = r6

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

STA T                  \ Set T = A
\       = r6^2 / 256

ADC ZP+1               \ Set ZP+1 = A + r5^2 / 256
STA ZP+1               \          = r6^2 / 256 + r5^2 / 256
\          = (r5^2 + r6^2) / 256

LDA ZP                 \ Set A = ZP
\       = r5

CMP #128               \ If A >= 128, set the C flag (so the C flag is now set
\ to bit 7 of ZP, i.e. 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

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

ROR A                  \ Rotate A and set the sign bit to the C flag, so bits
\ 5-7 are now the same, i.e. A is a random number in one
\ of these ranges:
\
\   %00000000 - %00011111  = 0-31
\   %11100000 - %11111111  = 224-255
\
\ In terms of signed 8-bit integers, this is a random
\ number from -32 to 31. Let's call it r7

ADC YY                 \ Set A = A + YY
\       = r7 + r6

TAX                    \ Set X = A
\       = r6 + r7

JSR SQUA2              \ Set (A P) = A * A
\           = (r6 + r7)^2

TAY                    \ Set Y = A
\       = (r6 + r7)^2 / 256

ADC ZP+1               \ Set A = A + ZP+1
\       = (r6 + r7)^2 / 256 + (r5^2 + r6^2) / 256
\       = ((r6 + r7)^2 + r5^2 + r6^2) / 256

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

CMP #80                \ If A >= 80, jump down to PLC3 to skip to the next
BCS PLC3               \ pixel

CMP #32                \ If A < 32, jump down to PLC3 to skip to the next pixel
BCC PLC3

TYA                    \ Set A = Y + T
ADC T                  \       = (r6 + r7)^2 / 256 + r6^2 / 256
\       = ((r6 + r7)^2 + r6^2) / 256

CMP #16                \ If A >= 16, skip to PL1 to plot the pixel
BCS PL1

LDA ZP                 \ If ZP is positive (i.e. r5 < 128), jump down to PLC3 to

.PL1

\ If we get here then the following is true:
\
\   32 <= ((r6 + r7)^2 + r5^2 + r6^2) / 256 < 80
\
\ and either this is true:
\
\   ((r6 + r7)^2 + r6^2) / 256 >= 16
\
\ or both these are true:
\
\   ((r6 + r7)^2 + r6^2) / 256 < 16
\   r5 >= 128

LDA YY                 \ Set A = YY
\       = r6

JSR PIX                \ Draw a pixel at screen coordinate (X, -A), where:
\
\   X = (random -32 to 31) + r6
\   A = r6
\
\ Negating a random number from 0 to 255 still gives a
\ random number from 0 to 255, so this is the same as
\ plotting at (x, y) where:
\
\   r5 = random number from 0 to 255
\   r6 = random number from 0 to 255
\   r7 = r5, squashed into -32 to 31
\
\   x = r5 + r7
\   y = r5
\
\   32 <= ((r6 + r7)^2 + r5^2 + r6^2) / 256 < 80
\
\   Either: ((r6 + r7)^2 + r6^2) / 256 >= 16
\
\   Or:     ((r6 + r7)^2 + r6^2) / 256 <  16
\           r5 >= 128
\
\ which is what we want

.PLC3

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

BNE PLL3               \ Loop back to PLL3 until CNT3 = 0

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

BNE PLL3               \ Loop back to PLL3 until CNT3+1 = 0
```