The Challenge of Geometric Transformations

The Z80 has no native support for the complex trigonometric math needed for rotation, nor does it have floating-point math for precise scaling. All geometric transformations must be calculated using fixed-point math and look-up tables (LUTs).

Sprite Scaling (Zooming)

Scaling a sprite involves sampling the source image at mathematically calculated intervals and writing the result to the screen.

The Principle: To double the size of a sprite (Scale Factor = 2), you read every $1^{st}$ pixel from the source and draw it twice on the screen, both horizontally and vertically.

The Calculation: Scaling relies on Fixed-Point Arithmetic. Since the Z80 only does integers, we represent fractions by multiplying everything by a power of two (e.g., 256 or 65536).

  1. Fixed-Point Scale Factor: We store the scale factor as an integer (e.g., $1.0$ is stored as $256$).
  2. Tracking: Use 16-bit registers (HL and DE) to track the current position in the 16-bit source image coordinates (X_Source, Y_Source) with the fractional part stored in the low 8 bits.
  3. Sampling: In the inner loop, add the Fixed-Point Scale Factor to the X_Source tracker. When the integer part of X_Source increments, it’s time to sample the next pixel from the source image.

Sprite Rotation (Trigonometry)

Rotation is the most demanding graphical effect, requiring sine and cosine values to calculate the new X and Y coordinates.

The Formula: $$\text{New } X = X \cdot \cos(\theta) - Y \cdot \sin(\theta)$$ $$\text{New } Y = X \cdot \sin(\theta) + Y \cdot \cos(\theta)$$

The Z80 Solution: Look-Up Tables (LUTs) Performing four 16x16-bit multiplications for every single pixel in the sprite is too slow. Instead:

  1. Pre-calculate all $360^{\circ}$ (or $256$ angle points) of sine and cosine values and store them as fixed-point 16-bit integers in a massive LUT.
  2. The rotation routine simply uses the angle ($\theta$) as an index into the LUT to read the sine and cosine values.
  3. The complex formula is then simplified to a series of 16x16 fixed-point multiplications and additions, which are still slow, but manageable during the VBI.

Practical Trade-off: Due to the immense processing time, full 360-degree software rotation is often done only on smaller sprites or is calculated slowly over several frames.