Aviator on the BBC Micro

# Maths: ScaleDown (Part 4 of 4)

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

.down18

\ We now shift the y-coordinate in (RR Q P) by Y
\ places in the correct direction, discarding the
\ fractional part in P when we are done, but only after
\ rounding (RR Q) to the nearest integer

TYA                    \ If Y < 0, jump to down21 to shift the y-coordinate
BMI down21             \ right by Y places, with A set to Y

BNE down19             \ If Y > 0, jump to down19 to shift the y-coordinate
\ right by Y places

ASL P                  \ Y = 0, so shift bit 7 of P into the C flag and jump
JMP down23             \ to down23 to round the result to the nearest integer,
\ without shifting the y-coordinate first

.down19

\ We now shift (RR Q P) left by X places

LDA Q                  \ Set (RR A P) = (RR Q P)

.down20

ASL P                  \ Set (RR A P) = (RR A P) << 1
ROL A
ROL RR

DEY                    \ Decrement the shift counter

BNE down20             \ Loop back until we have shifted left by Y places

STA Q                  \ Set (RR Q P) = (RR A P)

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

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

.down21

\ 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 Y = -A so we can use it as a shift counter for the
CLC                    \ number of places to shift
TAY

\ We now shift (RR Q P) right by Y places, and because
\ RR = 0 and we are going to discard the fractional part
\ in P, we only actually need to shift Q

LDA Q                  \ Set A = Q

.down22

LSR A                  \ Set A = A >> 1

DEY                    \ Decrement the shift counter

BNE down22             \ Loop back until we have shifted right by Y places

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

.down23

\ 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 (RR Q), or
\ right-shifted out of the result in (RR Q), so if that
\ bit is set, we need to round up the result

BCC down24             \ If the next bit is clear, then jump to return from the
\ subroutine, as we do not need to round up the result

INC Q                  \ Otherwise increment the low byte of the result in
BNE down24             \ (RR Q) to round it up, and if we did that without
\ subroutine as we now have our result

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

LDA RR                 \ If the high byte is < &40, jump to down24 to return
CMP #&40               \ from the subroutine as we now have our result
BCC down24

LDA #&3F               \ Otherwise set (RR Q) = &3FFF as the highest value we
STA RR                 \ can return as the y-coordinate
LDA #&FF
STA Q

.down24

RTS                    \ Return from the subroutine
```