# Calculating screen address

If we are drawing a sprite, we use our pixel coordinates to define the upper-left coordinate of the sprite.

Since the CPC and KC Compact do not have sprite hardware, we will need to plot the sprites using a software function.

If we want to plot graphics to the display, e.g. to draw a sprite, then we will need to be able to calculate a memory address from our pixel coordinates.

This document will describe how this is done.

The CPC display hardware generates a memory address by using the CRTC MA (MA0-MA13) and RA (RA0-RA5) outputs in the following way:

Memory address Signal | Signal Source | Signal name
--- | --- | ---
A15 | 6845 | MA13
A14 | 6845 | MA12
A13 | 6845 | RA2
A12 | 6845 | RA1
A11 | 6845 | RA0
A10 | 6845 | MA9
A9 | 6845 | MA8
A8 | 6845 | MA7
A7 | 6845 | MA6
A6 | 6845 | MA5
A5 | 6845 | MA4
A4 | 6845 | MA3
A3 | 6845 | MA2
A2 | 6845 | MA1
A1 | 6845 | MA0
A0 | Gate-Array | CCLK

Notes

- CRTC register 9 defines the number of scanlines per CRTC character.
- CRTC register 1 defines the width of the visible area in CRTC characters. The CPC display hardware fetches two bytes per CRTC character. Therefore the length of a CRTC scanline in bytes is (R1*2).
- CRTC register 6 defines the height of the visible area in CRTC character lines. Therefore the total height of the visible area in CRTC scanlines is (R9+1)*R6

The screen has the following form:

When R9 is 7:

line 0 | 0 + &000
line 1 | 0 + &800
line 2 | 0 + &1000
line 3 | 0 + &1800
line 4 | 0 + &2000
line 5 | 0 + &2800
line 6 | 0 + &3000
line 7 | 0 + &3800
line 8 | ((R1*1)*2) + &000
line 9 | (R1*2) + &800
line 10 | (R1*2) + &1000
line 11 | (R1*2) + &1800
line 12 | (R1*2) + &2000
line 13 | (R1*2) + &2800
line 14 | (R1*2) + &3000
line 15 | (R1*2) + &3800
line 16 | (R1*2) + &000
line 17 | (R1*2) + &800
line 18 | (R1*2) + &1000
line 19 | (R1*2) + &1800
line 20 | (R1*2) + &2000
line 21 | (R1*2) + &2800
line 22 | (R1*2) + &3000
line 23 | (R1*2) + &3800

CRTC character row = (y_coordinate/(R9+1))

CRTC character scan line = y_coordinate - (CRTC character row*(R9+1));

Byte offset to CRTC row start = CRTC character row * (R1*2)

Byte offset to CRTC character scan line = CRTC character scan line * &0800

Byte offset to start of line = Byte offset to CRTC row start + Byte offset to CRTC character scan line

For a 16k screen:

screen start byte offset = (((R12 & 0x03)*256) + (R13 & 255))*2

For a 32k screen:

screen start byte offset = (((R12 & 15)*256) + (R13 & 255))*2

On a hardware scrolling screen, there is a problem:

C7FF->C000
CFFF->C800
D7FF->D000
DFFF->D800
E7FF->E000
EFFF->E800
F7FF->F000
FFFF->F800