Get address of character on screen

Calculate the true address on screen of a character

Calculating the start address for a character might sound complicated due to its weird memory layout, but it is actually pretty simple.

The way the address is calculated is described with the Display File, however the following code allows you to calculate the address in Z80 machine code.

A link to download this routine is available under Resources at the top right of the page:

; *************************************************************************** ; Calculates the actual screen address for a character in BC (row,col) ; returning that address in HL. ; ; Author: Peter Mount, & Contributors ; URL: ; *************************************************************************** ; ; Although the memory layout for the spectrum screen seems weird, ; it's actually pretty logical. You can tell this weirdness is down to how ; the ULA works internally with the way the addressing is mapped, as shown ; at ; ; Address format: ; H L ; 010rrnnn rrrccccc where r=row, ; c=column, ; n=row in the character definition. ; ; To calculate the address of a character: ; High byte = &40 or (row and &18) ; Low byte = (row<<5) or column ; ; That would then be the top byte of the character. ; ; To get the next byte in the character just increment the high byte ; (e.g. n=1) & so on for the next 7 bytes. ; ; To get the next character's address then simply increment the low byte. ; Be careful however when wrapping around the end of the line as, after ; the first 8 lines the address will fail. ; ; Ideally you should calculate the address again at the start of each line. ; ; This might explain why the original spectrum editor was 8 lines long, as you ; only needed to set the high byte to the 8-line block in memory and set the ; low byte to the offset in the line being edited to get that characters ; screen address. ; ; On Entry: ; BC b=row, c=col in Spectrum 32x24 characters ; ; On Exit: ; HL address of top row if character definition in screen ; BC unchanged ; A undefined ; getSpectrumCharPos: ; Get Spectrum char pos (bc) into HL for physical screen address ld a, b ; first calculate high byte - get row and &18 ; Mask bits 4 & 5 from row or &40 ; set bit 6, this gives us the upper memory address ld h, a ; Set H ld a, b ; get row add a ; Shift left 5 to form low address add a ; use add not srl as this saves 1 byte and half the t-states add a ; per shift, especially as we don't need to worry about carry flag add a add a ; HA is now the address of the start of line or c ; Add column value ld l, a ; HL now address of top row of character ret

Note: This code is actually from my Teletext Mode 7 emulator for the Spectrum

Last modified November 3, 2021: Add additional notes to DISPLAYFILE (3a7f050)