Aviator on the BBC Micro

# Maths: ScaleDown (Part 3 of 4)

```       Name: ScaleDown (Part 3 of 4)                                 [Show more]
Type: Subroutine
Category: Maths
Summary: Scale the x-coordinate
Context: See this subroutine in context in the source code
References: No direct references to this subroutine in this source file

.down12

\ We now shift the x-coordinate in (SS QQ PP) by X
\ places in the correct direction, discarding the
\ fractional part in PP when we are done, but only after
\ rounding (SS QQ) to the nearest integer

TXA                    \ If X < 0, jump to down15 to shift the x-coordinate
BMI down15             \ right by X places, with A set to X

BNE down13             \ If X > 0, jump to down13 to shift the x-coordinate
\ left by X places

ASL PP                 \ X = 0, so shift bit 7 of PP into the C flag and jump
JMP down17             \ to down17 to round the result to the nearest integer,
\ without shifting the x-coordinate first

.down13

\ We now shift (SS QQ PP) left by X places

LDA QQ                 \ Set (SS A PP) = (SS QQ PP)

.down14

ASL PP                 \ Set (SS A PP) = (SS A PP) << 1
ROL A
ROL SS

DEX                    \ Decrement the shift counter

BNE down14             \ Loop back until we have shifted left by X places

STA QQ                 \ Set (SS QQ PP) = (SS A PP)

ASL PP                 \ Shift bit 7 of PP into the C flag, so it contains bit
\ 7 of the fractional part

JMP down17             \ Jump to down17 to round the result to the nearest
\ integer

.down15

\ If we get here then we want to shift the result right
\ by the number of places in A, where A is negative

EOR #&FF               \ Set X = -A so we can use it as a shift counter for the
CLC                    \ number of places to shift
TAX

\ We now shift (SS QQ PP) right by X places, and because
\ SS = 0 and we are going to discard the fractional part
\ in PP, we only actually need to shift QQ

LDA QQ                 \ Set A = QQ

.down16

LSR A                  \ Set A = A >> 1

DEX                    \ Decrement the shift counter

BNE down16             \ Loop back until we have shifted right by X places

STA QQ                 \ Set QQ = A, so now we have shifted (SS QQ) right by
\ X places, and the C flag is set to the last bit that
\ we shifted out of QQ, which would be bit 7 of the
\ fractional part

.down17

\ We now round up the result, if bit 7 of the fractional
\ part is set

\ The C flag contains the next bit that would have been
\ left-shifted out of PP into the result in (SS QQ), or
\ right-shifted out of the result in (SS QQ), so if that
\ bit is set, we need to round up the result

BCC down18             \ If the next bit is clear, then jump to down18 to move
\ on to scaling the y-coordinate, as we do not need to
\ round up the result

INC QQ                 \ Otherwise increment the low byte of the result in
BNE down18             \ (SS QQ) to round it up, and if we did that without
\ y-coordinate

INC SS                 \ If the increment overflowed the low byte, increment
\ the high byte of the result in (SS QQ) to round it up

LDA SS                 \ If the high byte is < &40, jump to down18 to move on
CMP #&40               \ to scaling the y-coordinate
BCC down18

LDA #&3F               \ Otherwise set (SS QQ) = &3FFF as the highest value we
STA SS                 \ can return as the x-coordinate
LDA #&FF
STA QQ
```