# Maths: ScaleSigned

```       Name: ScaleSigned                                             [Show more]
Type: Subroutine
Category: Maths
Summary: Scale an indicator value by 4 or 16, retaining the sign and adding
sensitivity for smaller values
Context: See this subroutine in context in the source code
References: This subroutine is called as follows:
* UpdateIndicator (Part 13 of 15) calls ScaleSigned
* UpdateIndicator (Part 14 of 15) calls ScaleSigned

This routine is used to scale the values for the following indicators:

* The joystick position display (indicator 8 or 10), where the x-coordinate
is scaled by 16 and the y-coordinate by 4, as the display is taller than
it is wide

* Rudder (indicator 9), which is divided by 16

When scaling down by a factor of 16, some smaller values scale to 1 instead of
0 (specifically, 4 to 7), and in all cases the final scaling is rounded up, so
this routine shows small deviations on the rudder and joystick indicators that
otherwise wouldn't register.

Arguments:

A                    The value to scale

C flag               Determines the scale factor:

* C flag set = divide A by 16

* C flag clear = divide A by 4

.ScaleSigned

PHP                    \ Store the flags on the stack, so we can check later
\ what their values were on entry

BPL scsi1              \ If A is positive, jump to scsi1 to skip the following
\ three instructions

EOR #&FF               \ Set A = -A using two's complement, so A is positive
CLC

.scsi1

\ By this point, A = |A|

LSR A                  \ Set A = |A| / 2

PLP                    \ Restore the flags from the stack, leaving them on the
PHP                    \ stack for later

BCC scsi3              \ If the C flag is clear, jump to scsi3 so we only
\ divide the original value by 4

\ If we get here then the C flag was set on entry, so we
\ want to divide A by 16 using four shifts in total

LSR A                  \ Set A = A / 2
\       = |A| / 4

CMP #1                 \ If A <> 1, skip the following instruction
BNE scsi2

LDA #2                 \ A = 1 (so the original |A| was in the range 4 to 7),
\ so set A = 2, which will give us an end result of 1
\
\ In other words, this scales smaller values to 1 that
\ would otherwise scale to 0, like this:
\
\   * 0 to 3 scale down to 0
\   * 4 to 23 scale down to 1
\   * 24 to 39 scale down to 2
\   * 40 to 55 scale down to 3
\
\ and so on

.scsi2

LSR A                  \ Set A = A / 2
\       = |A| / 8

.scsi3

LSR A                  \ Set A = A / 2
\
\ so this is:
\
\   * |A| / 16 if the C flag was set on entry
\   * |A| / 4  if the C flag was clear on entry

ADC #0                 \ Increment A if the value of A before the LSR was odd
\ (so the result of the last division gets rounded up)
\
\ This works because the LSR will set the C flag if bit
\ 0 of A was set before the shift, so A gets bumped up
\ by 1 by the ADC

PLP                    \ Restore the flags from the stack

BPL scsi4              \ If the N flag is clear, then the result already has