Website logo

Z80 TV Game - Assembly Startup Routine

This startup routine can be used as a starting point for your Z80 TV Game programs. It does three things: You can copy and paste this code into a text editor, or download a more complete set of routines I've written for the Z80 TV Game here.

 ; Z80 TV Game startup routine - 21.03.2026, Alex J. Lowry
 ;
 ; Based on the Z80 TV Game startup routine developed by Inufuto for the Cate
 ;   compiler.
 ;
 ; https://github.com/inufuto/Cate_examples/blob/main/z80tvg/aerial/Startup.asm
 ;
 ; This startup routine will automatically determine whether the system has an
 ;   8255 or Z80PIO installed, and configure the correct operating mode for
 ;   either chip. This procedure does not cause any adverse effects on the Z80
 ;   TV Game 2, and is 100% cross-compatible with all known Z80 TV Game
 ;   variants that currently exist.
 ;
 ; This source code was written for the AZ80 assembler for Windows and DOS,
 ;   and may need some modification to work with other assemblers. For
 ;   example, many Z80 assemblers expect a colon after each address label
 ;   declaration.
 ;
 ; You can download the AZ80 assembler here:
 ;   https://www.retrotechnology.com/restore/az80.html
 ;
 ; Video memory locations:
 ;
 ; Byte in upper left corner:  $C1E4
 ; Byte in upper right corner: $C1F8  ...  Upper left + $14
 ; Byte in lower left corner:  $DA62  ...  Upper left + ($1E * $D1)
 ; Byte in lower right corner: $DA76  ...  Upper left + $14 + ($1E * $D1)
 ;
 ;        Number of visible byte columns: Hex 15 / Dec 21
 ;           Number of visible scanlines: Hex D2 / Dec 210
 ;
 ; Number of visible pixel (bit) columns: Hex A8 / Dec 168
 ;

SysRAMStart equ $8000    ; Start of system RAM.
SysRAMEnd   equ $bfff    ; End of system RAM.

VRAMStart   equ $c000    ; Start of video RAM.
VRAMEnd     equ $dfff    ; End of video RAM.

ScrStart    equ $c1e4    ; First visible byte. This value can be
                         ;   readjusted to match TV offset as
                         ;   required. The value
                         ;   $c1e4 - ($1e * $10) will position the
                         ;   image at the highest possible point in
                         ;   video memory.

ScrLine     equ $001e    ; Length of one scanline.

JoyPort1    equ $00      ; Location of input port for player 1
                         ;   controller.
JoyPort2    equ $01      ; Location of input port for player 2
                         ;   controller. (Only on Z80 TV Game 2)

AudioPort   equ $02      ; Location of audio output port.

  di                     ; Disable interrupts.

StartClearMem
  ld a,  $00             ; Load blank byte into A.
  ld de, SysRAMStart
  ld bc, VRAMEnd         ; Initialize address pointers for clearing system and
                         ;   video RAM.

StartClearMem1
  ld (de), a             ; Load current address with value of A.
  ld a, c
  cp e                   ; Compare low byte of BC and DE.
  jr nz, StartClearMem2  ;   If not equal, keep running the loop. Otherwise...
  ld a, b                ;
  cp d                   ; Compare high byte of BC/DE.
  jr z, StartClearMemEnd ;   If equal, end loop.

StartClearMem2
  ld a, $00              ; Reset A with blank byte.
  inc de                 ; Continue to next screen address.
  jr StartClearMem1      ; Loop back.

StartClearMemEnd

  ld sp, SysRAMEnd + 1   ; Initialize stack pointer.

  ld a, $90              ; Does this system have an 8255 or a Z80 PIO?
  out ($03), a           ; $90 to Port $03 - 8255 control register and PIO port.
                         ;   $02 control register.

  ; If this is an 8255-based system, the control register has now been properly
  ;   set.
  ;
  ;  1 - Mode Set Flag Active          (Bit 7)
  ;  0 - \__ Group A Mode = 0          (Bit 6)
  ;  0 - /                             (Bit 5)
  ;  1 - Port A = Input ($00)          (Bit 4)
  ;  0 - Port C (Upper) = Output ($02) (Bit 3)
  ;  0 - Group B Mode = 0              (Bit 2)
  ;  0 - Port B = Output ($01)         (Bit 1)
  ;  0 - Port C (Lower) = Output ($02) (Bit 0)

  ld a, $aa              ; $AA to Port $01 - 8255 unused output port and PIO
  out ($01), a           ;   port $00 ctrl. register.

  in a, ($01)            ; Query for input from $01.
  cp $aa                 ; An 8255 will return the value in its port $01
                         ;   register, while a Z80PIO will return some other
                         ;   value. Unfortunately there isn't much
                         ;   documentation on this particular functionality of
                         ;   the Z80PIO, so I don't know exactly what value it
                         ;   returns.
  jr z, Test8255         ; If the returned value is not $AA, continue to the
                         ;   Z80PIO initialization routine. Otherwise, jump
                         ;   forward to a second test to make sure this is an
                         ;   8255-based system.

StartupPIO               ; Initialize Z80PIO. This code will only be run if the
                         ;   system is a Z80PIO-based Z80TVG or a Z80TVG2.
    ld a, $4f            ;
    out ($01), a         ; $4F to Port $01 - PIO control port for port $00.
    ld a, $0f            ;
    out ($03), a         ; $0F to Port $03 - PIO control port for port $00.
  jr EndStartup          ; Jump to the end of this startup routine.

  ; If this is an PIO-based system, the control register has now been properly
  ;   set.
  ;
  ; Port $01 (control register for port $00):
  ;  0 - \__ Input Mode
  ;  1 - /
  ;  0 - (unused)
  ;  0 - (unused)
  ;  1 - \
  ;  1 -  \__ Signifies that the operating
  ;  1 -  /   mode is being set
  ;  1 - /
  ;
  ; Port $03 (control register for port $02):
  ;  0 - \__ Output Mode
  ;  0 - /
  ;  0 - (unused)
  ;  0 - (unused)
  ;  1 - \
  ;  1 -  \__ Signifies that the operating
  ;  1 -  /   mode is being set
  ;  1 - /

Test8255
    ld a, $55            ; Send some data to Port $01.
    out ($01), a         ;
    in a, ($01)          ; Try receiving data from the same port.
    cp $55               ; An 8255 will return the value in its port $01
                         ;   register, while a Z80PIO will return some other
                         ;   value. Unfortunately there isn't much
                         ;   documentation on this particular functionality of
                         ;   the Z80PIO, so I don't know exactly what value it
                         ;   returns.
  jr nz, StartupPIO      ; If the returned value is not $55, jump to the Z80PIO
                         ;   initialization routine. Otherwise, continue
                         ;   onward.

EndStartup


Thanks to:
    Mr. Isizu: The original designer of the Z80 TV Game.

    Inufuto: Developer of Cate, a multi-platform compiler that can generate software for the Z80 TV Game.
    All the games he has created with it thus far have Z80 TV Game versions.
    Inufuto has also designed a PCB version of the Z80 TV Game that outputs VGA video via a Raspberry Pi Pico.

    Takeda Toshiya: Developer of eZ80TVGAME, a Z80 TV Game emulator for Windows.

    lsluk: Developer of vdmgr, a multi-platform emulator for Windows that supports the Z80 TV Game.

    RobertK: Developer of several games for the Z80 TV Game.

Last updated on Mar 23, 2026.
This page was first uploaded on Mar 23, 2026.
visitors since Dec 26, 2025.