;--------------------------------------------------------------------------------------------------------
;-
;- Name:            sharpmz-test.asm
;- Created:         October 2018
;- Author(s):       Philip Smart
;- Description:     Sharp MZ series tester utility.
;-                  This assembly language program is a quick coding to aid in testing components
;-                  of the SharpMZ Series FPGA emulation and more recently the tranZPUter
;-                  and video module offshoots. It is a rough and ready program just to aid
;-                  exercising of hardware changes to verify they work and are reliable.
;-
;-                  Currently it aids in testing:
;-                      1. Tape Read
;-                      2. Tape Write
;-                      3. Memory Test
;-                      4. Graphics RAM Test
;-
;- Credits:         
;- Copyright:       (c) 2018-20 Philip Smart <philip.smart@net2net.org>
;-
;- History:         October 2018   - Merged 2 utilities to create this compilation.
;-                  September 2020 - Updated to enable testing of the Video Module v2.0
;-
;--------------------------------------------------------------------------------------------------------
;- This source file is free software: you can redistribute it and-or modify
;- it under the terms of the GNU General Public License as published
;- by the Free Software Foundation, either version 3 of the License, or
;- (at your option) any later version.
;-
;- This source file is distributed in the hope that it will be useful,
;- but WITHOUT ANY WARRANTY; without even the implied warranty of
;- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;- GNU General Public License for more details.
;-
;- You should have received a copy of the GNU General Public License
;- along with this program.  If not, see <http://www.gnu.org/licenses/>.
;--------------------------------------------------------------------------------------------------------

GETL:                   EQU     00003h
LETNL:                  EQU     00006h
NL:                     EQU     00009h
PRNTS:                  EQU     0000Ch
PRNT:                   EQU     00012h
MSG:                    EQU     00015h
MSGX:                   EQU     00018h
MROMINIT:               EQU     00000h
MONIT:                  EQU     00086h
ST1:                    EQU     00095h
PRTHL:                  EQU     003BAh
PRTHX:                  EQU     003C3h
DPCT:                   EQU     00DDCh
?BRK:                   EQU     00D11h
?RSTR1:                 EQU     00EE6h
TPSTART:                EQU     010F0h
MEMSTART:               EQU     01200h
GRAMSTART:              EQU     0C000h
GRAMEND:                EQU     0FFFFh
MSTART:                 EQU     0B800h
MEMCHKEND:              EQU     0B8H

;-----------------------------------------------
; IO ports in hardware and values.
;-----------------------------------------------
MMCFG                   EQU     060H                                     ; Memory management configuration latch.
SETXMHZ                 EQU     062H                                     ; Select the alternate clock frequency.
SET2MHZ                 EQU     064H                                     ; Select the system 2MHz clock frequency.
CLKSELRD                EQU     066H                                     ; Read clock selected setting, 0 = 2MHz, 1 = XMHz
SVCREQ                  EQU     068H                                     ; I/O Processor service request.
CPLDSTATUS              EQU     06BH                                     ; Version 2.1 CPLD status register.
CPUCFG                  EQU     06CH                                     ; Version 2.2 CPU configuration register.
CPUSTATUS               EQU     06CH                                     ; Version 2.2 CPU runtime status register.
CPUINFO                 EQU     06DH                                     ; Version 2.2 CPU information register.
CPLDCFG                 EQU     06EH                                     ; Version 2.1 CPLD configuration register.
CPLDINFO                EQU     06FH                                     ; Version 2.1 CPLD version information register.
VMPNUM                  EQU     0A0H                                     ; Set the parameter number to update.
VMPLBYTE                EQU     0A1H                                     ; Update the lower selected parameter byte.
VMPUBYTE                EQU     0A2H                                     ; Update the upper selected parameter byte.
PALSLCTOFF              EQU     0A3H                                     ; set the palette slot Off position to be adjusted.
PALSLCTON               EQU     0A4H                                     ; set the palette slot On position to be adjusted.
PALSETRED               EQU     0A5H                                     ; set the red palette value according to the PALETTE_PARAM_SEL address.
PALSETGREEN             EQU     0A6H                                     ; set the green palette value according to the PALETTE_PARAM_SEL address.
PALSETBLUE              EQU     0A7H                                     ; set the blue palette value according to the PALETTE_PARAM_SEL address.
VMPALETTE               EQU     0B0H                                     ; Select Palette:
                                                                         ;    0xB0 sets the palette. The Video Module supports 4 bit per colour output but there is only enough RAM for 1 bit per colour so the pallette is used to change the colours output.
                                                                         ;      Bits [7:0] defines the pallete number. This indexes a lookup table which contains the required 4bit output per 1bit input.
                                                                         ; GPU:
GPUPARAM                EQU     0B2H                                     ;    0xB2 set parameters. Store parameters in a long word to be used by the graphics command processor.
                                                                         ;      The parameter word is 128 bit and each write to the parameter word shifts left by 8 bits and adds the new byte at bits 7:0.
GPUCMD                  EQU     0B3H                                     ;    0xB3 set the graphics processor unit commands.
GPUSTATUS               EQU     0B3H                                     ;         [7;1] - FSM state, [0] - 1 = busy, 0 = idle
                                                                         ;      Bits [5:0] - 0 = Reset parameters.
                                                                         ;                   1 = Clear to val. Start Location (16 bit), End Location (16 bit), Red Filter, Green Filter, Blue Filter
                                                                         ; 
VMCTRL                  EQU     0B8H                                     ; Video Module control register. [2:0] - 0000 = MZ80K, 0001 = MZ80C, 0010 = MZ1200, 0011 = MZ80A, 0100 = MZ700, 0101 = MZ800, 0110 = MZ1500, 0111 = MZ80B, 1000 = MZ2000, 1001 = MZ2200, 1010 = MZ2500. [4] = 0 - 40 col, 1 - 80 col.
VMGRMODE                EQU     0B9H                                     ; Video Module graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR), 5=GRAM Output Enable, 4 = VRAM Output Enable, 3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect), 1/0=Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
VMREDMASK               EQU     0BAH                                     ; Video Module Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMGREENMASK             EQU     0BBH                                     ; Video Module Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMBLUEMASK              EQU     0BCH                                     ; Video Module Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
VMPAGE                  EQU     0BDH                                     ; Video Module memory page register. [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. Bits [1:0] = page, 00 = off, 01 = Red, 10 = Green, 11 = Blue. This overrides all MZ700/MZ80B page switching functions. [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.
VMVGATTR                EQU     0BEH                                     ; Select VGA Border colour and attributes. Bit 2 = Red, 1 = Green, 0 = Blue.
VMVGAMODE               EQU     0BFH                                     ; Select VGA output mode. Bits [3:0] - Output mode.
GDCRTC                  EQU     0CFH                                     ; MZ-800 CRTC control register
GDCMD                   EQU     0CEH                                     ; MZ-800 CRTC Mode register
GDGRF                   EQU     0CDH                                     ; MZ-800      read format register
GDGWF                   EQU     0CCH                                     ; MZ-800      write format register
MMIO0                   EQU     0E0H                                     ; MZ-700/MZ-800 Memory Management Set 0
MMIO1                   EQU     0E1H                                     ; MZ-700/MZ-800 Memory Management Set 1
MMIO2                   EQU     0E2H                                     ; MZ-700/MZ-800 Memory Management Set 2
MMIO3                   EQU     0E3H                                     ; MZ-700/MZ-800 Memory Management Set 3
MMIO4                   EQU     0E4H                                     ; MZ-700/MZ-800 Memory Management Set 4
MMIO5                   EQU     0E5H                                     ; MZ-700/MZ-800 Memory Management Set 5
MMIO6                   EQU     0E6H                                     ; MZ-700/MZ-800 Memory Management Set 6
MMIO7                   EQU     0E7H                                     ; MZ-700/MZ-800 Memory Management Set 7
SYSCTRL                 EQU     0F0H                                     ; System board control register. [2:0] - 000 MZ80A Mode, 2MHz CPU/Bus, 001 MZ80B Mode, 4MHz CPU/Bus, 010 MZ700 Mode, 3.54MHz CPU/Bus.
GRAMMODE                EQU     0F4H                                     ; MZ80B Graphics mode.  Bit 0 = 0, Write to Graphics RAM

;-----------------------------------------------
; GPU commands.
;-----------------------------------------------
GPUCLEARVRAM            EQU     001H                                     ; Clear the VRAM without updating attributes.
GPUCLEARVRAMCA          EQU     002H                                     ; Clear the VRAM/ARAM with given attribute byte,
GPUCLEARVRAMP           EQU     003H                                     ; Clear the VRAM/ARAM with parameters.
GPUCLEARGRAM            EQU     081H                                     ; Clear the entire Framebuffer.
GPUCLEARGRAMP           EQU     082H                                     ; Clear the Framebuffer according to parameters.
GPURESET                EQU     0FFH                                     ; Reset the GPU, return to idle state.

;-----------------------------------------------
; Memory mapped ports in hardware.
;-----------------------------------------------
SCRN:                   EQU     0D000H
ARAM:                   EQU     0D800H
DSPCTL:                 EQU     0DFFFH                                   ; Screen 40/80 select register (bit 7)
KEYPA:                  EQU     0E000h
KEYPB:                  EQU     0E001h
KEYPC:                  EQU     0E002h
KEYPF:                  EQU     0E003h
CSTR:                   EQU     0E002h
CSTPT:                  EQU     0E003h
CONT0:                  EQU     0E004h
CONT1:                  EQU     0E005h
CONT2:                  EQU     0E006h
CONTF:                  EQU     0E007h
SUNDG:                  EQU     0E008h
TEMP:                   EQU     0E008h
MEMSW:                  EQU     0E00CH
MEMSWR:                 EQU     0E010H
INVDSP:                 EQU     0E014H
NRMDSP:                 EQU     0E015H
SCLDSP:                 EQU     0E200H
SCLBASE:                EQU     0E2H

;-----------------------------------------------
; CPLD Configuration constants.
;-----------------------------------------------
MODE_MZ80K              EQU     0                                        ; Set to MZ-80K mode.
MODE_MZ80C              EQU     1                                        ; Set to MZ-80C mode.
MODE_MZ1200             EQU     2                                        ; Set to MZ-1200 mode.
MODE_MZ80A              EQU     3                                        ; Set to MZ-80A mode (base mode on MZ-80A hardware).
MODE_MZ700              EQU     4                                        ; Set to MZ-700 mode (base mode on MZ-700 hardware).
MODE_MZ800              EQU     5                                        ; Set to MZ-800 mode.
MODE_MZ80B              EQU     6                                        ; Set to MZ-80B mode.
MODE_MZ2000             EQU     7                                        ; Set to MZ-2000 mode.
MODE_VIDEO_FPGA         EQU     8                                        ; Bit flag (bit 3) to switch CPLD into using the new FPGA video hardware.
MODE_RESET_PRESERVE     EQU     080H                                     ; Preserve register configuration through reset.

;-----------------------------------------------
; CPLD Command Instruction constants.
;-----------------------------------------------
CPLD_RESET_HOST         EQU     1                                        ; CPLD level command to reset the host system.
CPLD_HOLD_HOST_BUS      EQU     2                                        ; CPLD command to hold the host bus.
CPLD_RELEASE_HOST_BUS   EQU     3                                        ; CPLD command to release the host bus.

;-----------------------------------------------
; Video Module control bits.
;-----------------------------------------------
MODE_80CHAR             EQU     010H                                     ; Enable 80 character display.
MODE_COLOUR             EQU     020H                                     ; Enable colour display.
SYSMODE_MZ80A           EQU     000H                                     ; System board mode MZ80A, 2MHz CPU/Bus.
SYSMODE_MZ80B           EQU     020H                                     ; System board mode MZ80B, 4MHz CPU/Bus.
SYSMODE_MZ2000          EQU     020H                                     ; System board mode MZ2000, 4MHz CPU/Bus.
SYSMODE_MZ700           EQU     042H                                     ; System board mode MZ700, 3.54MHz CPU/Bus.
VMMODE_MZ80K            EQU     000H                                     ; Video mode = MZ80K
VMMODE_MZ80C            EQU     001H                                     ; Video mode = MZ80C
VMMODE_MZ1200           EQU     002H                                     ; Video mode = MZ1200
VMMODE_MZ80A            EQU     003H                                     ; Video mode = MZ80A
VMMODE_MZ700            EQU     004H                                     ; Video mode = MZ700
VMMODE_MZ800            EQU     005H                                     ; Video mode = MZ800
VMMODE_MZ1500           EQU     006H                                     ; Video mode = MZ1500
VMMODE_MZ80B            EQU     007H                                     ; Video mode = MZ80B
VMMODE_MZ2000           EQU     008H                                     ; Video mode = MZ2000
VMMODE_MZ2200           EQU     009H                                     ; Video mode = MZ2200
VMMODE_MZ2500           EQU     00AH                                     ; Video mode = MZ2500
VMMODE_VGA_OFF          EQU     000H                                     ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT          EQU     000H                                     ; Set VGA mode off, external monitor is driven by standard internal 60Hz signals.
VMMODE_VGA_INT50        EQU     001H                                     ; Set VGA mode off, external monitor is driven by standard internal 50Hz signals.
VMMODE_VGA_640x480      EQU     002H                                     ; Set external monitor to VGA 640x480 @ 60Hz mode.
VMMODE_VGA_800x600      EQU     003H                                     ; Set external monitor to VGA 800x600 @ 60Hz mode.

;-----------------------------------------------
; tranZPUter SW Memory Management modes
;-----------------------------------------------
TZMM_ENIOWAIT           EQU     020H                                     ; Memory management IO Wait State enable - insert a wait state when an IO operation to E0-FF is executed.
TZMM_ORIG               EQU     000H                                     ; Original Sharp MZ80A mode, no tranZPUter features are selected except the I/O control registers (default: 0x60-063).
TZMM_BOOT               EQU     001H                                     ; Original mode but E800-EFFF is mapped to tranZPUter RAM so TZFS can be booted.
TZMM_TZFS               EQU     002H + TZMM_ENIOWAIT                     ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-FFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected.
TZMM_TZFS2              EQU     003H + TZMM_ENIOWAIT                     ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 1.
TZMM_TZFS3              EQU     004H + TZMM_ENIOWAIT                     ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 2.
TZMM_TZFS4              EQU     005H + TZMM_ENIOWAIT                     ; TZFS main memory configuration. all memory is in tranZPUter RAM, E800-EFFF is used by TZFS, SA1510 is at 0000-1000 and RAM is 1000-CFFF, 64K Block 0 selected, F000-FFFF is in 64K Block 3.
TZMM_CPM                EQU     006H + TZMM_ENIOWAIT                     ; CPM main memory configuration, all memory on the tranZPUter board, 64K block 4 selected. Special case for F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
TZMM_CPM2               EQU     007H + TZMM_ENIOWAIT                     ; CPM main memory configuration, F000-FFFF are on the tranZPUter board in block 4, 0040-CFFF and E800-EFFF are in block 5, mainboard for D000-DFFF (video), E000-E800 (Memory control) selected.
                                                                         ; Special case for 0000:003F (interrupt vectors) which resides in block 4, F3C0:F3FF & F7C0:F7FF (floppy disk paging vectors) which resides on the mainboard.
TZMM_COMPAT             EQU     008H + TZMM_ENIOWAIT                     ; Original mode but with main DRAM in Bank 0 to allow bootstrapping of programs from other machines such as the MZ700.
TZMM_HOSTACCESS         EQU     009H + TZMM_ENIOWAIT                     ; Mode to allow code running in Bank 0, address E800:FFFF to access host memory. Monitor ROM 0000-0FFF and Main DRAM 0x1000-0xD000, video and memory mapped I/O are on the host machine, User/Floppy ROM E800-FFFF are in tranZPUter memory. 
TZMM_MZ700_0            EQU     00AH + TZMM_ENIOWAIT                     ; MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the mainboard.
TZMM_MZ700_1            EQU     00BH + TZMM_ENIOWAIT                     ; MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
TZMM_MZ700_2            EQU     00CH + TZMM_ENIOWAIT                     ; MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is on the tranZPUter in block 6.
TZMM_MZ700_3            EQU     00DH + TZMM_ENIOWAIT                     ; MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 0, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
TZMM_MZ700_4            EQU     00EH + TZMM_ENIOWAIT                     ; MZ700 Mode - 0000:0FFF is on the tranZPUter board in block 6, 1000:CFFF is on the tranZPUter board in block 0, D000:FFFF is inaccessible.
TZMM_MZ800              EQU     00FH + TZMM_ENIOWAIT                     ; MZ800 Mode - Tracks original hardware mode offering MZ700/MZ800 configurations.
TZMM_MZ2000             EQU     010H + TZMM_ENIOWAIT;                    ; MZ2000 Mode - Running on MZ2000 hardware, configuration set according to runtime configuration registers.
TZMM_FPGA               EQU     015H + TZMM_ENIOWAIT                     ; Open up access for the K64F to the FPGA resources such as memory. All other access to RAM or mainboard is blocked.
TZMM_TZPUM              EQU     016H + TZMM_ENIOWAIT                     ; Everything in on mainboard, no access to tranZPUter memory.
TZMM_TZPU               EQU     017H + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU0              EQU     018H + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 0 is selected.
;TZMM_TZPU1              EQU     019H + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 1 is selected.
;TZMM_TZPU2              EQU     01AH + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 2 is selected.
;TZMM_TZPU3              EQU     01BH + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 3 is selected.
;TZMM_TZPU4              EQU     01CH + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 4 is selected.
;TZMM_TZPU5              EQU     01DH + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 5 is selected.
;TZMM_TZPU6              EQU     01EH + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 6 is selected.
;TZMM_TZPU7              EQU     01FH + TZMM_ENIOWAIT                     ; Everything is in tranZPUter domain, no access to underlying Sharp mainboard unless memory management mode is switched. tranZPUter RAM 64K block 7 is selected.

;-----------------------------------------------
;    BIOS WORK AREA (MZ80A)
;-----------------------------------------------
TZVARMEM:               EQU     0F4A0H
TZSVCMEM:               EQU     0F560H                                   ; Start of a memory structure used to communicate with the K64F I/O processor for services such as disk access.
TZSVCSIZE:              EQU     00280H                                   ;
TZSVCDIRSZ:             EQU     20                                       ; Size of the directory/file name.
TZSVCFILESZ:            EQU     17                                       ; Size of a Sharp filename.
TZSVCLONGFILESZ:        EQU     31                                       ; Size of a standard filename.
TZSVCLONGFMTSZ:         EQU     20                                       ; Size of a formatted standard filename for use in directory listings.
TZSVCWILDSZ:            EQU     20                                       ; Size of the wildcard.
TZSVCSECSIZE:           EQU     512
TZSVCDIR_ENTSZ:         EQU     32                                       ; Size of a directory entry.
TZSVCWAITIORETRIES:     EQU     500                                      ; Wait retries for IO response.
TZSVCWAITCOUNT:         EQU     65535                                    ; Wait retries for IO request response.
TZSVC_FTYPE_MZF:        EQU     0                                        ; File type being handled is an MZF
TZSVC_FTYPE_CAS:        EQU     1                                        ; File type being handled is an CASsette BASIC script.
TZSVC_FTYPE_BAS:        EQU     2                                        ; File type being handled is an BASic script
TZSVC_FTYPE_ALL:        EQU     10                                       ; Handle any filetype.
TZSVC_FTYPE_ALLFMT:     EQU     11                                       ; Special case for directory listings, all files but truncated and formatted.
; TZ Service Commands
TZSVC_CMD_READDIR       EQU     01H                                      ; Service command to open a directory and return the first block of entries.
TZSVC_CMD_NEXTDIR       EQU     02H                                      ; Service command to return the next block of an open directory.
TZSVC_CMD_READFILE      EQU     03H                                      ; Service command to open a file and return the first block.
TZSVC_CMD_NEXTREADFILE  EQU     04H                                      ; Service command to return the next block of an open file.
TZSVC_CMD_WRITEFILE     EQU     05H                                      ; Service command to create a file and save the first block.
TZSVC_CMD_NEXTWRITEFILE EQU     06H                                      ; Service command to write the next block to the open file.
TZSVC_CMD_CLOSE         EQU     07H                                      ; Service command to close any open file or directory.
TZSVC_CMD_LOADFILE      EQU     08H                                      ; Service command to load a file directly into tranZPUter memory.
TZSVC_CMD_SAVEFILE      EQU     09H                                      ; Service command to save a file directly from tranZPUter memory. 
TZSVC_CMD_ERASEFILE     EQU     0aH                                      ; Service command to erase a file on the SD card.
TZSVC_CMD_CHANGEDIR     EQU     0bH                                      ; Service command to change the active directory on the SD card.
TZSVC_CMD_LOAD40ABIOS   EQU     20H                                      ; Service command requesting that the 40 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD80ABIOS   EQU     21H                                      ; Service command requesting that the 80 column version of the SA1510 BIOS is loaded.
TZSVC_CMD_LOAD700BIOS40 EQU     22H                                      ; Service command requesting that the MZ700 1Z-013A 40 column BIOS is loaded.
TZSVC_CMD_LOAD700BIOS80 EQU     23H                                      ; Service command requesting that the MZ700 1Z-013A 80 column patched BIOS is loaded.
TZSVC_CMD_LOAD80BIPL    EQU     24H                                      ; Service command requesting the MZ-80B IPL is loaded.
TZSVC_CMD_LOAD800BIOS   EQU     25H                                      ; Service command requesting that the MZ800 9Z-504M BIOS is loaded.
TZSVC_CMD_LOAD2000IPL   EQU     26H                                      ; Service command requesting the MZ-2000 IPL is loaded.
TZSVC_CMD_LOADTZFS      EQU     2FH                                      ; Service command requesting the loading of TZFS. This service is for machines which normally dont have a monitor BIOS. ie. MZ-80B/MZ-2000 and manually request TZFS.
TZSVC_CMD_LOADBDOS      EQU     30H                                      ; Service command to reload CPM BDOS+CCP.
TZSVC_CMD_ADDSDDRIVE    EQU     31H                                      ; Service command to attach a CPM disk to a drive number.
TZSVC_CMD_READSDDRIVE   EQU     32H                                      ; Service command to read an attached SD file as a CPM disk drive.
TZSVC_CMD_WRITESDDRIVE  EQU     33H                                      ; Service command to write to a CPM disk drive which is an attached SD file.
TZSVC_CMD_CPU_BASEFREQ  EQU     40H                                      ; Service command to switch to the mainboard frequency.
TZSVC_CMD_CPU_ALTFREQ   EQU     41H                                      ; Service command to switch to the alternate frequency provided by the K64F.
TZSVC_CMD_CPU_CHGFREQ   EQU     42H                                      ; Service command to set the alternate frequency in hertz.
TZSVC_CMD_CPU_SETZ80    EQU     50H                                      ; Service command to switch to the external Z80 hard cpu.
TZSVC_CMD_CPU_SETT80    EQU     51H                                      ; Service command to switch to the internal T80 soft cpu.
TZSVC_CMD_CPU_SETZPUEVO EQU     52H                                      ; Service command to switch to the internal ZPU Evolution soft cpu.
TZSVC_CMD_EMU_SETMZ80K  EQU     53H                                      ; Service command to switch to the internal Sharp MZ Series Emulation of the MZ80K.
TZSVC_CMD_EMU_SETMZ80C  EQU     54H                                      ; ""                             ""                       ""                 MZ80C.
TZSVC_CMD_EMU_SETMZ1200 EQU     55H                                      ; ""                             ""                       ""                 MZ1200.
TZSVC_CMD_EMU_SETMZ80A  EQU     56H                                      ; ""                             ""                       ""                 MZ80A.
TZSVC_CMD_EMU_SETMZ700  EQU     57H                                      ; ""                             ""                       ""                 MZ700.
TZSVC_CMD_EMU_SETMZ800  EQU     58H                                      ; ""                             ""                       ""                 MZ800.
TZSVC_CMD_EMU_SETMZ1500 EQU     59H                                      ; ""                             ""                       ""                 MZ1500.
TZSVC_CMD_EMU_SETMZ80B  EQU     5AH                                      ; ""                             ""                       ""                 MZ80B.
TZSVC_CMD_EMU_SETMZ2000 EQU     5BH                                      ; ""                             ""                       ""                 MZ2000.
TZSVC_CMD_EMU_SETMZ2200 EQU     5CH                                      ; ""                             ""                       ""                 MZ2200.
TZSVC_CMD_EMU_SETMZ2500 EQU     5DH                                      ; ""                             ""                       ""                 MZ2500.
TZSVC_CMD_EXIT          EQU     07FH                                     ; Service command to terminate TZFS and restart the machine in original mode.
TZSVC_STATUS_OK         EQU     000H                                     ; Flag to indicate the K64F processing completed successfully.
TZSVC_STATUS_REQUEST    EQU     0FEH                                     ; Flag to indicate the Z80 has made a request to the K64F.
TZSVC_STATUS_PROCESSING EQU     0FFH                                     ; Flag to indicate the K64F is processing a command.


           ORG      TPSTART

SPV:
IBUFE:                                                                   ; TAPE BUFFER (128 BYTES)
;ATRB:                   DS      virtual 1                               ; ATTRIBUTE
ATRB:                   DB      01h                                      ; Code Type, 01 = Machine Code.
;NAME:                   DS      virtual 17                              ; FILE NAME
NAME:                   DB      "SHARPMZ TEST V1", 0Dh, 00h              ; Title/Name (17 bytes).
;SIZE:                   DS      virtual 2                               ; BYTESIZE
SIZE:                   DW      MEND - MSTART                            ; Size of program.
;DTADR:                  DS      virtual 2                               ; DATA ADDRESS
DTADR:                  DW      MSTART                                   ; Load address of program.
;EXADR:                  DS      virtual 2                               ; EXECUTION ADDRESS
EXADR:                  DW      MSTART                                   ; Exec address of program.
COMNT:                  DS      104                                      ; COMMENT
KANAF:                  DS      virtual 1                                ; KANA FLAG (01=GRAPHIC MODE)
DSPXY:                  DS      virtual 2                                ; DISPLAY COORDINATES
MANG:                   DS      virtual 27                               ; COLUMN MANAGEMENT
FLASH:                  DS      virtual 1                                ; FLASHING DATA
FLPST:                  DS      virtual 2                                ; FLASHING POSITION
FLSST:                  DS      virtual 1                                ; FLASHING STATUS
FLSDT:                  DS      virtual 1                                ; CURSOR DATA
STRGF:                  DS      virtual 1                                ; STRING FLAG
DPRNT:                  DS      virtual 1                                ; TAB COUNTER
TMCNT:                  DS      virtual 2                                ; TAPE MARK COUNTER
SUMDT:                  DS      virtual 2                                ; CHECK SUM DATA
CSMDT:                  DS      virtual 2                                ; FOR COMPARE SUM DATA
AMPM:                   DS      virtual 1                                ; AMPM DATA
TIMFG:                  DS      virtual 1                                ; TIME FLAG
SWRK:                   DS      virtual 1                                ; KEY SOUND FLAG
TEMPW:                  DS      virtual 1                                ; TEMPO WORK
ONTYO:                  DS      virtual 1                                ; ONTYO WORK
OCTV:                   DS      virtual 1                                ; OCTAVE WORK
RATIO:                  DS      virtual 2                                ; ONPU RATIO
BUFER:                  DS      virtual 81                               ; GET LINE BUFFER



           ORG      MSTART
           JP       START

           ; Graphics Initialisation. Needs to be in memory before C000-FFFF
           ;
           ; 0x6E CPLD Configuration register.
           ;
           ; The mode can be changed by a Z80 transaction write into the register and it is acted upon if the mode switches between differing values. The Z80 write is typically used
           ; by host software such as RFS.
           ;
           ; [2:0] - Mode/emulated machine.
           ;         000 = MZ-80K
           ;         001 = MZ-80C
           ;         010 = MZ-1200
           ;         011 = MZ-80A
           ;         100 = MZ-700
           ;         101 = MZ-800
           ;         110 = MZ-80B
           ;         111 = MZ-2000
           ; [3]   - Mainboard Video - 1 = Enable, 0 = Disable - This flag allows Z-80 transactions in the range D000:DFFF to be directed to the mainboard. When disabled all transactions
           ;                                                     can only be seen by the FPGA video logic. The FPGA uses this flag to enable/disable it's functionality.
           ; [6:4] = Mainboard/CPU clock.
           ;         000 = Sharp MZ80A 2MHz System Clock.
           ;         001 = Sharp MZ80B 4MHz System Clock.
           ;         010 = Sharp MZ700 3.54MHz System Clock.
           ;         011 -111 = Reserved, defaults to 2MHz System Clock.
           ;
           ;
           ; 0xF8 set the video mode. 
           ;                       Bits [2:0] define the Video Module machine compatibility. 000 = MZ80K, 001 = MZ80C, 010 = MZ1200, 011 = MZ80A, 100 = MZ-700, 101 = MZ-800, 110 = MZ-80B, 111 = MZ2000,
           ;                       Bit    [3] defines the 40/80 column mode, 0 = 40 col, 1 = 80 col.
           ;                       Bit    [4] defines the colour mode, 0 = mono, 1 = colour - ignored on certain modes.
           ;                       Bit    [5] defines wether PCGRAM is enabled, 0 = disabled, 1 = enabled.
           ;                       Bits [7:6] define the VGA mode.
           ; 0xF9 set the graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR),
           ;                               5 = GRAM Output Enable (=0), 4 = VRAM Output Enable (=0),
           ;                             3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect),
           ;                             1/0 = Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
           ; 0xFA set the Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
           ; 0xFB set the Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
           ; 0xFC set the Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
           ; 0xFD set the Video memory page in block C000:FFFF 
           ;                            [1:0] switches in 1 16Kb page (3 pages) of graphics ram to C000 - FFFF. 00 = disabled, standard VRAM, 01 = Red page, 10 = Blue page, 11 = Green page.
           ;                            [7] 0 - normal, 1 - switches in CGROM for upload at D000:DFFF.

GRAMINIT:  OUT      (VMGRMODE),A                           ; Set provided graphics mode.
           LD       A,1                                    ; Switch graphics page into C000:FFFF memory bank 
           OUT      (VMPAGE),A
GRAM0:     LD       HL,GRAMSTART                           ; Start of graphics page.
           LD       BC,GRAMEND - GRAMSTART                 ; Size of graphics page (16KB).
GRAM1:     LD       A,000h                                 ; Clear memory.
           LD       (HL),A
           INC      HL
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GRAM1
           LD       A,0                                    ; Revert to normal memory.
           OUT      (VMPAGE),A
           RET

           ; Graphics Test. Needs to be in memory before C000-FFFF
           ;
GRAMTEST:  OUT      (VMGRMODE),A
           LD       A,1                                    ; Switch graphics page into C000:FFFF memory bank 
           OUT      (VMPAGE),A
           LD       D, 1                                   ; Number of iterations.
           LD       E,080h
GRAMTST0:  LD       HL,GRAMSTART
           LD       BC,GRAMEND - GRAMSTART
GRAMTST1:  LD       A,E
           LD       (HL),A
           INC      HL
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GRAMTST1
           RR       E
           JR       NZ,GRAMTST0
          ;JR       C,GRAMTST0
           DEC      D
           JR       NZ,GRAMTST0
           LD       A,0                                    ; Revert to normal memory.
           OUT      (VMPAGE),A
           RET
           ;
GRAMTEST2: OUT      (VMGRMODE),A
           LD       A,1                                    ; Switch graphics page into C000:FFFF memory bank 
           OUT      (VMPAGE),A
           LD       E,0FFH
GRAMTST4:  LD       HL,GRAMSTART
           LD       BC,GRAMEND - GRAMSTART
GRAMTST5:  LD       A,E
           LD       (HL),A
           INC      HL
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GRAMTST5
           LD       A,0                                    ; Revert to normal memory.
           OUT      (VMPAGE),A
           RET

           ; Graphics Test routine.
           ;
           ;   Graphics mode:- 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR),
           ;                     5 = GRAM Output Enable  0 = active.
           ;                     4 = VRAM Output Enable, 0 = active.
           ;                   3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect),
           ;                   1/0 = Read mode  (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
           ;
GRAPHICS1: LD       B, 128
GRAPH0:    PUSH     BC
           LD       A,010h                 ; Red page read/write.
           CALL     GRAMTEST
           LD       A,015h                 ; Green page read/write.
           CALL     GRAMTEST
           LD       A,01Ah                 ; Blue page.
           CALL     GRAMTEST
           POP      BC
           DJNZ     GRAPH0
           JP       GETL1


GRAPHICS2: LD       A, 0FFH                ; Run through the filter mask.
           OUT      (VMREDMASK),A
           OUT      (VMGREENMASK),A
           OUT      (VMBLUEMASK),A
GRAPH1:    LD       A, 01Ch                ; Set graphics mode to Indirect Page write.
           CALL     GRAMTEST2
           IN       A,(VMREDMASK)
           DEC      A
           OUT      (VMREDMASK),A
           JR       NZ, GRAPH1
           IN       A,(VMGREENMASK)
           DEC      A
           OUT      (VMGREENMASK),A
           JR       NZ, GRAPH1
           IN       A,(VMBLUEMASK)
           DEC      A
           OUT      (VMBLUEMASK),A
           JR       NZ, GRAPH1
           JP       GETL1

           ; Graphics progress bar indicator. Needs to be in memory before C000-FFFF
           ;
GRPHIND:   LD       HL,(GRPHPOS)            ; Get position of graphics progress line.
           LD       A,001H
           OUT      (VMPAGE),A              ; Enable graphics memory.
           LD       A,0FFh
           LD       (HL),A
           LD       A,0
           OUT      (VMPAGE),A              ; Disable graphics memory.
           INC      HL
           LD       (GRPHPOS),HL
           LD       A,08CH
           OUT      (VMGRMODE),A
           RET
           

           ;
           ; Start of main program.
           ;
START:     
           LD       HL,0066H                                             ; Set NMI so it doesnt bother us.
           LD       (HL), 0EDH                                           ; Set to RETN instruction.
           INC      HL
           LD       (HL), 045H

           IN       A, (CPLDINFO)                                        ; Get hardware information.
           AND      07H                                                  ; Remove version.
           LD       D, A
           OR       MODE_VIDEO_FPGA                                      ; Ensure the video hardware is enabled.
           OUT      (CPLDCFG),A
           LD       A,D
           CP       MODE_MZ80A
           JR       NZ,START2
           LD       A,VMMODE_MZ700                                       ; Switch to MZ700 video mode for colour testing.
           JR       START3
          ;IN       A,(VMCTRL)
          ;AND      0C0H                                                 ; Mask out all but VGA mode.
START2:    OR       D                                                    ; Bring in mode.
START3:    OUT      (VMCTRL),A                                           ; Activate.
           LD       A, VMMODE_VGA_800x600                                ; VGA mode 800x600
           OUT      (VMVGAMODE),A
           ;
SIGNON:    LD       A,016H
           CALL     PRNT
           LD       A,071H                                               ; Blue background, white characters in colour mode. Bit 7 is set as a write to bit 7 @ DFFFH selects 80Char mode.
           LD       HL,ARAM
           CALL     CLR8
           CALL     NL
           LD       DE,TITLE
           CALL     MSG
           CALL     LETNL
           CALL     LETNL

           ; 0x6E CPLD Configuration register.
           ;
           ; The mode can be changed by a Z80 transaction write into the register and it is acted upon if the mode switches between differing values. The Z80 write is typically used
           ; by host software such as RFS.
           ;
           ; [2:0] - Mode/emulated machine.
           ;         000 = MZ-80K
           ;         001 = MZ-80C
           ;         010 = MZ-1200
           ;         011 = MZ-80A
           ;         100 = MZ-700
           ;         101 = MZ-800
           ;         110 = MZ-80B
           ;         111 = MZ-2000
           ; [3]   - Mainboard Video - 1 = Enable, 0 = Disable - This flag allows Z-80 transactions in the range D000:DFFF to be directed to the mainboard. When disabled all transactions
           ;                                                     can only be seen by the FPGA video logic. The FPGA uses this flag to enable/disable it's functionality.
           ; [6:4] = Mainboard/CPU clock.
           ;         000 = Sharp MZ80A 2MHz System Clock.
           ;         001 = Sharp MZ80B 4MHz System Clock.
           ;         010 = Sharp MZ700 3.54MHz System Clock.
           ;         011 -111 = Reserved, defaults to 2MHz System Clock.
           ;
           ;
           ; 0xF8 set the video mode. 
           ;                       Bits [2:0] define the Video Module machine compatibility. 000 = MZ80K, 001 = MZ80C, 010 = MZ1200, 011 = MZ80A, 100 = MZ-700, 101 = MZ-800, 110 = MZ-80B, 111 = MZ2000,
           ;                       Bit    [3] defines the 40/80 column mode, 0 = 40 col, 1 = 80 col.
           ;                       Bit    [4] defines the colour mode, 0 = mono, 1 = colour - ignored on certain modes.
           ;                       Bit    [5] defines wether PCGRAM is enabled, 0 = disabled, 1 = enabled.
           ;                       Bits [7:6] define the VGA mode.
           ; 0xF9 set the graphics mode. 7/6 = Operator (00=OR,01=AND,10=NAND,11=XOR),
           ;                               5 = GRAM Output Enable (=0), 4 = VRAM Output Enable (=0),
           ;                             3/2 = Write mode (00=Page 1:Red, 01=Page 2:Green, 10=Page 3:Blue, 11=Indirect),
           ;                             1/0 = Read mode (00=Page 1:Red, 01=Page2:Green, 10=Page 3:Blue, 11=Not used).
           ; 0xFA set the Red bit mask (1 bit = 1 pixel, 8 pixels per byte).
           ; 0xFB set the Green bit mask (1 bit = 1 pixel, 8 pixels per byte).
           ; 0xFC set the Blue bit mask (1 bit = 1 pixel, 8 pixels per byte).
           ; 0xFD set the Video memory page in block C000:FFFF bit 0, set the CGROM upload access in bit 7.

INITGRPH:  LD       DE,MSG_INITGR
           CALL     MSG
           CALL     LETNL
           LD       A,0FFh                 ; Set Red filter.
           OUT      (VMREDMASK),A
           LD       A,0FFh                 ; Set Green filter.
           OUT      (VMGREENMASK),A
           LD       A,0FFh                 ; Set Blue filter.
           OUT      (VMBLUEMASK),A
           LD       A,010h                 ; Enable graphics output and character display output. Initialise Red page.
           CALL     GRAMINIT
           LD       A,015h                 ; Initialise Green page.
           CALL     GRAMINIT
           LD       A,01Ah                 ; Initialise Blue page.
           CALL     GRAMINIT
           LD       A, 0ECh                ; Set graphics mode to Indirect Page write, disable graphics output.
           OUT      (VMGRMODE),A
           LD       HL,0DE00h
           LD       (GRPHPOS),HL
           ;
INITMEM:   LD       DE,MSG_INITM
           CALL     MSG
           CALL     LETNL
           LD       HL,1200h
           LD       BC,MSTART - 1200h
CLEAR1:    LD       A,00h
           LD       (HL),A
           INC      HL
           DEC      BC
           LD       A,B
           OR       C
           JP       NZ,CLEAR1
           JP       HELP                   ; Output known commands at startup.

GETL1:     LD       A, 0ECh                ; Set graphics mode to VRAM enable, GRAM disable.
           OUT      (VMGRMODE),A
           CALL     NL
GETL1A:    LD       A,03EH
           CALL     PRNT
           LD       DE,BUFER
           CALL     GETL

CMDCMP:    LD       HL,CMDTABLE
CMDCMP0:   LD       DE,BUFER+1                                           ; First command byte after the * prompt.
           LD       A,(HL)
           CP       000H
           JR       Z,GETL1A                                             ; Skip processing on lines where just CR pressed.
           BIT      7,A                                                  ; Bit 7 set on command properties indicates table end, exit if needed.
           JR       NZ,CMDNOCMP
           LD       C,A                                                  ; Command properties into C
           SET      6,C                                                  ; Assume command match.
           AND      007H                                                 ; Mask out bytes in command mask.
           LD       B,A                                                  ; Number of bytes in command.
           INC      HL
CMDCMP1:   LD       A,(DE)                                               ; Compare all bytes and reset match bit if we find a difference.
           CP       (HL)
           JR       Z, CMDCMP2
           RES      6,C                                                  ; No command match.
CMDCMP2:   INC      DE
           INC      HL
           DJNZ     CMDCMP1
           BIT      6,C                                                  ; Bit 7 is still set then we have a command match.
           JR       NZ,CMDCMP3
           INC      HL
           INC      HL                                                   ; Skip over function address
           JR       CMDCMP0                                              ; Try match next command.
CMDCMP3:   LD       A,(HL)                                               ; Command function address into HL
           INC      HL
           LD       H,(HL)
           LD       L,A
           PUSH     HL
           LD       (TMPADR),DE                                          ; Store the key buffer location where arguments start.
           LD       HL,CMDCMPEND                                         ; Location to return to after function is called.
           EX       (SP),HL                                              ; Swap the return location with the location to call.
           PUSH     HL                                                   ; Put location to call at top of stack.
           RET                                                           ; Pop into PC and run.
           ;
CMDNOCMP:  LD      DE,MSGBADCMD
           CALL    MSG
           CALL    NL
CMDCMPEND: JP      GETL1A


            ; Monitor command table. This table contains the list of recognised commands along with the 
            ; handler function and bank in which it is located.
            ;
            ;         7     6     5:3    2:0
            ;        END  MATCH  UNUSED  SIZE 
CMDTABLE:  
           DB       000H | 000H | 000H | 004H
           DB       "HELP"                    
           DW       HELP
           DB       000H | 000H | 000H | 005H
           DB       "GRPH1"                    
           DW       GRAPHICS1
           DB       000H | 000H | 000H | 005H
           DB       "GRPH2"                    
           DW       GRAPHICS2
           DB       000H | 000H | 000H | 004H
           DB       "GPU1"                    
           DW       GPU1
           DB       000H | 000H | 000H | 004H
           DB       "GPU2"                    
           DW       GPU2
           DB       000H | 000H | 000H | 003H
           DB       "PAL"                    
           DW       PALETTE
           DB       000H | 000H | 000H | 007H
           DB       "MEMTEST"                    
           DW       MEMTEST
           DB       000H | 000H | 000H | 004H
           DB       "LOAD"                    
           DW       LOAD
           DB       000H | 000H | 000H | 005H
           DB       "TIMER"                    
           DW       TIMERTST
           DB       000H | 000H | 000H | 004H
           DB       "SAVE"                    
           DW       SAVE
           DB       000H | 000H | 000H | 004H
           DB       "QUIT"                    
           DW       MROMINIT
           DB       000H | 000H | 000H | 004H
           DB       "VGA0"                                               ; Set VGA mode.
           DW       VGA0
           DB       000H | 000H | 000H | 004H
           DB       "VGA1"                                               ; Set VGA mode.
           DW       VGA1
           DB       000H | 000H | 000H | 004H
           DB       "VGA2"                                               ; Set VGA mode.
           DW       VGA2
           DB       000H | 000H | 000H | 004H
           DB       "VGA3"                                               ; Set VGA mode.
           DW       VGA3
           DB       000H | 000H | 000H | 001H

VGA0:      IN       A,(VMVGAMODE)
           AND      0F0H
           OUT      (VMVGAMODE),A
           JP       GETL1
VGA1:      IN       A,(VMVGAMODE)
           AND      0F0H
           OR       000H
           OUT      (VMVGAMODE),A
           JP       GETL1
VGA2:      IN       A,(VMVGAMODE)
           AND      0F0H
           OR       001H
           OUT      (VMVGAMODE),A
           JP       GETL1
VGA3:      IN       A,(VMVGAMODE)
           AND      0F0H
           OR       002H
           OUT      (VMVGAMODE),A
           JP       GETL1

           ; Simple commands to exercise the GPU functions.
           ;
           ; First up, character clear with parameters. Create descending cleared areas with incremental
           ; character and colour. This puts a lot of pressure on the GPU/Video memory, not so pretty to watch
           ; but does test it out.
GPU1:      XOR      A
           LD       (GPUCHAR),A
           LD       (GPUATTR),A
           LD       (GPUSTARTX),A

GPUNEXT0:  XOR      A
           LD       (GPUSTARTY),A

GPUNEXT1:  LD       A,(GPUSTARTX)
           LD       (GPUENDX),A

GPUNEXT2:  LD       A,(GPUSTARTY)
           LD       (GPUENDY),A

           ; Wait for the GPU to become ready.
GPUWAIT1:  IN       A,(GPUSTATUS)
           BIT      0,A
           JR       NZ,GPUWAIT1

           ; Setup the GPU parameters to fill area.
GPUNEXT3:  LD       A,(GPUSTARTX)
           OUT      (GPUPARAM),A
           LD       A,(GPUSTARTY)
           OUT      (GPUPARAM),A
           LD       A,(GPUENDX)
           OUT      (GPUPARAM),A
           LD       A,(GPUENDY)
           OUT      (GPUPARAM),A
           LD       A,(GPUCHAR)
           OUT      (GPUPARAM),A
           LD       A,(GPUATTR)
           OUT      (GPUPARAM),A
           ; Issue the GPU command.
           LD       A,GPUCLEARVRAMP
           OUT      (GPUCMD),A

           ; Next End Y loop.
           LD       A,(GPUENDY)
           INC      A
           LD       (GPUENDY),A
           CP       25
           JP       C, GPUWAIT1

           ; Change the character.
           LD       A,(GPUCHAR)
           INC      A
           LD       (GPUCHAR),A

           ; Next End X loop.
           LD       A,(GPUENDX)
           INC      A
           LD       (GPUENDX),A
           CP       40
           JP       C, GPUNEXT2

           ; Wait for the GPU to become ready.
GPUWAIT2:  IN       A,(GPUSTATUS)
           BIT      0,A
           JR       NZ,GPUWAIT2

           ; Setup the GPU parameters to clear area.
           LD       A,(GPUSTARTX)
           OUT      (GPUPARAM),A
           LD       A,(GPUSTARTY)
           OUT      (GPUPARAM),A
           LD       A,(GPUENDX)
           OUT      (GPUPARAM),A
           LD       A,(GPUENDY)
           OUT      (GPUPARAM),A
           LD       A,000H                            ; Space
           OUT      (GPUPARAM),A
           LD       A,071H                            ; Default white on blue.
           OUT      (GPUPARAM),A
           ; Issue the GPU command.
           LD       A,GPUCLEARVRAMP
           OUT      (GPUCMD),A

           ; Adjust back colour.
           LD       A,(GPUATTR)
           LD       C,A
           AND      0F8H
           LD       D,A
           LD       A,C
           INC      A
           AND      007H
           OR       D
           LD       (GPUATTR),A

           ; Next Start Y loop.
           LD       A,(GPUSTARTY)
           INC      A
           LD       (GPUSTARTY),A
           CP       25
           JP       C, GPUNEXT1

           ; Adjust front colour.
           LD       A,(GPUATTR)
           LD       C,A
           AND      08FH
           LD       D,A
           LD       A,C
           SRL      A
           SRL      A
           SRL      A
           SRL      A
           INC      A
           AND      007H
           SLA      A
           SLA      A
           SLA      A
           SLA      A
           AND      070H
           OR       D
           LD       (GPUATTR),A

           ; Next Start X loop.
           LD       A,(GPUSTARTX)
           INC      A
           LD       (GPUSTARTX),A
           CP       40
           JP       C, GPUNEXT0
           JP       GETL1

           ; Second up, same as above but end co-ordinates are fixed.
GPU2:      XOR      A
           LD       (GPUCHAR),A
           LD       (GPUATTR),A
           LD       (GPUSTARTX),A

GPUNEXT5:  XOR      A
           LD       (GPUSTARTY),A

           ; Setup the GPU parameters to fill area.
GPUNEXT6:  LD       A,(GPUSTARTX)
           OUT      (GPUPARAM),A
           LD       A,(GPUSTARTY)
           OUT      (GPUPARAM),A
           LD       A,39
           OUT      (GPUPARAM),A
           LD       A,24
           OUT      (GPUPARAM),A
           LD       A,(GPUCHAR)
           OUT      (GPUPARAM),A
           LD       A,(GPUATTR)
           OUT      (GPUPARAM),A
           ; Issue the GPU command.
           LD       A,GPUCLEARVRAMP
           OUT      (GPUCMD),A
           ; Wait for the command to complete.
GPUWAIT3:  IN       A,(GPUSTATUS)
           BIT      0,A
           JR       NZ,GPUWAIT3

           LD       BC,0
GPUWAIT5:  DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GPUWAIT5

           ; Setup the GPU parameters to clear area.
           LD       A,(GPUSTARTX)
           OUT      (GPUPARAM),A
           LD       A,(GPUSTARTY)
           OUT      (GPUPARAM),A
           LD       A,(GPUENDX)
           OUT      (GPUPARAM),A
           LD       A,(GPUENDY)
           OUT      (GPUPARAM),A
           LD       A,000H                            ; Space
           OUT      (GPUPARAM),A
           LD       A,071H                            ; Default white on blue.
           OUT      (GPUPARAM),A
           ; Issue the GPU command.
           LD       A,GPUCLEARVRAMP
           OUT      (GPUCMD),A
           ; Wait for the command to complete.
GPUWAIT4:  IN       A,(GPUSTATUS)
           BIT      0,A
           JR       NZ,GPUWAIT4

           ; Adjust back colour.
           LD       A,(GPUATTR)
           LD       C,A
           AND      0F8H
           LD       D,A
           LD       A,C
           INC      A
           AND      007H
           OR       D
           LD       (GPUATTR),A

           ; Next Start Y loop.
           LD       A,(GPUSTARTY)
           INC      A
           LD       (GPUSTARTY),A
           CP       25
           JP       C, GPUNEXT6

           ; Change the character.
           LD       A,(GPUCHAR)
           INC      A
           LD       (GPUCHAR),A

           ; Adjust front colour.
           LD       A,(GPUATTR)
           LD       C,A
           AND      08FH
           LD       D,A
           LD       A,C
           SRL      A
           SRL      A
           SRL      A
           SRL      A
           INC      A
           AND      007H
           SLA      A
           SLA      A
           SLA      A
           SLA      A
           AND      070H
           OR       D
           LD       (GPUATTR),A

           ; Next Start X loop.
           LD       A,(GPUSTARTX)
           INC      A
           LD       (GPUSTARTX),A
           CP       40
           JP       C, GPUNEXT5
           JP       GETL1

           ; Draw bars in descending colours prior to palette test.
PALETTE:   LD       A,GPUCLEARVRAM
           OUT      (GPUCMD),A
           ; Wait for the command to complete.
PALWAIT1:  IN       A,(GPUSTATUS)
           BIT      0,A
           JR       NZ,PALWAIT1

           XOR      A
           LD       (GPUCHAR),A
           LD       (GPUSTARTX),A
           LD       (GPUSTARTY),A
           LD       A,030H
           LD       (GPUATTR),A

           ; Setup the GPU parameters to fill area.
PALNEXT1:  LD       A,(GPUSTARTX)
           OUT      (GPUPARAM),A
           LD       A,(GPUSTARTY)
           OUT      (GPUPARAM),A
           LD       A,39
           OUT      (GPUPARAM),A
           LD       A,24
           OUT      (GPUPARAM),A
           LD       A,(GPUCHAR)
           OUT      (GPUPARAM),A
           LD       A,(GPUATTR)
           OUT      (GPUPARAM),A
           ; Issue the GPU command.
           LD       A,GPUCLEARVRAMP
           OUT      (GPUCMD),A
           ; Wait for the command to complete.
PALWAIT2:  IN       A,(GPUSTATUS)
           BIT      0,A
           JR       NZ,PALWAIT2

           ; Change the character.
           LD       A,(GPUCHAR)
           INC      A
           LD       (GPUCHAR),A

           ; Adjust back colour.
           LD       A,(GPUATTR)
           LD       C,A
           AND      0F8H
           LD       D,A
           LD       A,C
           INC      A
           AND      007H
           LD       E,A
           OR       D
           LD       (GPUATTR),A

           ; Adjust front colour.
           LD       A,(GPUATTR)
           LD       C,A
           AND      08FH
           LD       D,A
           LD       A,C
           SRL      A
           SRL      A
           SRL      A
           SRL      A
           INC      A
           AND      007H
           SLA      A
           SLA      A
           SLA      A
           SLA      A
           AND      070H
           OR       D
           LD       (GPUATTR),A

           ; Next Start Y loop.
PALNEXT2:  LD       A,(GPUSTARTY)
           INC      A
           LD       (GPUSTARTY),A
           CP       25
           JP       C, PALNEXT1


           LD       A,0FFH               ; Choose palette 255 for tests.
           OUT      (VMPALETTE),A
           OUT      (PALSLCTON),A        ; Enable writes to the ON values of palette 255
           ;
           LD       E,0                  ; Red
           LD       D,0                  ; Green
           LD       L,0                  ; Blue
PALNEXT5:  LD       A,E
           OUT      (PALSETRED),A
           LD       A,D
           OUT      (PALSETGREEN),A
           LD       A,L
           OUT      (PALSETBLUE),A

           LD       BC,32768
PALWAIT4:  DEC      BC
           LD       A,B
           OR       C
           JR       NZ,PALWAIT4

           INC      L
           LD       A,L
           CP       020H
           JR       C, PALNEXT5
           LD       L,0
           INC      D
           LD       A,D
           CP       020H
           JR       NZ, PALNEXT5
           LD       D,0
           INC      E
           LD       A,E
           CP       020H
           JR       NZ, PALNEXT5

           XOR      A
PALNEXT3:  OUT      (VMPALETTE),A

           LD       BC,0
PALWAIT3:  DEC      BC
           LD       A,B
           OR       C
           JR       NZ,PALWAIT3

           IN       A, (VMPALETTE)
           INC      A
           OR       A
           JR       NZ, PALNEXT3
           JP       GETL1
         

MEMTEST:   LD       B,240       ; Number of loops
LOOP:      LD       HL,MEMSTART ; Start of checked memory,
           LD       D,MEMCHKEND ; End memory check
LOOP1:     LD       A,000h
           CP       L
           JR       NZ,LOOP1b
           CALL     PRTHL       ; Print HL as 4digit hex.
           LD       A,0C4h      ; Move cursor left.
           LD       E,004h      ; 4 times.
LOOP1a:    CALL     DPCT
           DEC      E
           JR       NZ,LOOP1a
LOOP1b:    INC      HL
           LD       A,H
           CP       D           ; Have we reached end of memory.
           JR       Z,LOOP3     ; Yes, exit.
           LD       A,(HL)      ; Read memory location under test, ie. 0.
           CPL                  ; Subtract, ie. FF - A, ie FF - 0 = FF.
           LD       (HL),A      ; Write it back, ie. FF.
           SUB      (HL)        ; Subtract written memory value from A, ie. should be 0.
           JR       NZ,LOOP2    ; Not zero, we have an error.
           LD       A,(HL)      ; Reread memory location, ie. FF
           CPL                  ; Subtract FF - FF
           LD       (HL),A      ; Write 0
           SUB      (HL)        ; Subtract 0
           JR       Z,LOOP1     ; Loop if the same, ie. 0
LOOP2:     LD       A,16h
           CALL     PRNT        ; Print A
           CALL     PRTHX       ; Print HL as 4 digit hex.
           CALL     PRNTS       ; Print space.
           XOR      A
           LD       (HL),A
           LD       A,(HL)      ; Get into A the failing bits.
           CALL     PRTHX       ; Print A as 2 digit hex.
           CALL     PRNTS       ; Print space.
           LD       A,0FFh      ; Repeat but first load FF into memory
           LD       (HL),A
           LD       A,(HL)
           CALL     PRTHX       ; Print A as 2 digit hex.
           NOP
           JR       LOOP4

LOOP3:     CALL     PRTHL
           LD       DE,OKCHECK
           CALL     MSG          ; Print check message in DE
           LD       A,B          ; Print loop count.
           CALL     PRTHX
           LD       DE,OKMSG
           CALL     MSG          ; Print ok message in DE
           CALL     NL
           CALL     GRPHIND
           DEC      B
           JR       NZ,LOOP
           LD       DE,DONEMSG
           CALL     MSG          ; Print check message in DE
           JP       GETL1

LOOP4:     LD       B,09h
           CALL     PRNTS        ; Print space.
           XOR      A            ; Zero A
           SCF                   ; Set Carry
LOOP5:     PUSH     AF           ; Store A and Flags
           LD       (HL),A       ; Store 0 to bad location.
           LD       A,(HL)       ; Read back
           CALL     PRTHX        ; Print A as 2 digit hex.
           CALL     PRNTS        ; Print space
           POP      AF           ; Get back A (ie. 0 + C)
           RLA                   ; Rotate left A. Bit LSB becomes Carry (ie. 1 first instance), Carry becomes MSB
           DJNZ     LOOP5        ; Loop if not zero, ie. print out all bit locations written and read to memory to locate bad bit.
           XOR      A            ; Zero A, clears flags.
           LD       A,80h
           LD       B,08h
LOOP6:     PUSH     AF           ; Repeat above but AND memory location with original A (ie. 80) 
           LD       C,A          ; Basically walk through all the bits to find which one is stuck.
           LD       (HL),A
           LD       A,(HL)
           AND      C
           NOP
           JR       Z,LOOP8      ; If zero then print out the bit number
           NOP
           NOP
           LD       A,C
           CPL
           LD       (HL),A
           LD       A,(HL)
           AND      C
           JR       NZ,LOOP8     ; As above, if the compliment doesnt yield zero, print out the bit number.
LOOP7:     POP      AF
           RRCA
           NOP
           DJNZ     LOOP6
           JP       GETL1

LOOP8:     CALL     LETNL        ; New line.
           LD       DE,BITMSG    ; BIT message
           CALL     MSG          ; Print message in DE
           LD       A,B
           DEC      A
           CALL     PRTHX        ; Print A as 2 digit hex, ie. BIT number.
           CALL     LETNL        ; New line
           LD       DE,BANKMSG   ; BANK message
           CALL     MSG          ; Print message in DE
           LD       A,H
           CP       50h          ; 'P'
           JR       NC,LOOP9     ; Work out bank number, 1, 2 or 3.
           LD       A,01h
           JR       LOOP11

LOOP9:     CP       90h
           JR       NC,LOOP10
           LD       A,02h
           JR       LOOP11

LOOP10:    LD       A,03h
LOOP11:    CALL     PRTHX        ; Print A as 2 digit hex, ie. BANK number.
           JR       LOOP7


           ;
           ; LOAD COMMAND
           ;
LOAD:      CALL     ?RDI
           JP       C,?ER
LOA0:      CALL     NL
           LD       DE,MSG_LOADFROM
           CALL     MSG
           LD       HL,(DTADR)
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_LOADEXEC
           CALL     MSG
           LD       HL,(EXADR)
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_LOADSIZE
           CALL     MSG
           LD       HL,(SIZE)
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_LOADFILE
           CALL     MSGX
           LD       DE,NAME
           CALL     MSGX
           CALL     NL
           CALL     ?RDD
           JP       C,?ER
           LD       HL,(EXADR)
           LD       A,H
           CP       12h
           JP       C,GETL1
           JP       (HL)


           ; SAVE COMMAND

SAVE:      LD       HL,TESTBUF
           LD       DE,IBUFE
           LD       BC,128
           LDIR
           LD       DE,TITLE_SAVE
           CALL     MSG
           CALL     LETNL
           CALL     LETNL
           LD       DE,MSG_SAVEFROM
           CALL     MSG
           LD       HL,(DTADR)
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_SAVEEXEC
           CALL     MSG
           LD       HL,(EXADR)
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_SAVESIZE
           CALL     MSG
           LD       HL,(SIZE)
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_SAVEFILE
           CALL     MSGX
           LD       DE,NAME
           CALL     MSGX
           CALL     NL
           LD       A,01H                                                    ; ATTRIBUTE: OBJECT CODE
           LD       (ATRB),A
           ;
           LD       DE,MSG_WHDR
           CALL     MSGX
           CALL     NL
           CALL     QWRI
           JP       C,QER                                                    ; WRITE ERROR
           ;
           LD       DE,MSG_WDATA
           CALL     MSGX
           CALL     NL
           ;
           CALL     QWRD                                                     ; DATA
           JP       C,QER
           CALL     NL
           LD       DE,MSGOK                                                 ; OK MESSAGE
           CALL     MSGX                                                     ; CALL MSGX
           JP       GETL1           

           ;
           ; ERROR (LOADING)
           ;
QER:       CP       02h
           JP       Z,GETL1
           LD       DE,MSG_ERRWRITE
           CALL     MSG
           JP       GETL1
           ;
           ; ERROR (LOADING)
           ;
?ER:       CP       02h
           JP       Z,GETL1
           LD       DE,MSG_ERRCHKSUM
           CALL     MSG
           JP       GETL1
           ;
           ; READ INFORMATION
           ;
           ; EXIT ACC = 0 : OK CF=0
           ;          = 1 : ER CF=1
           ;          = 2 : BREAK CF=1
           ;
?RDI:      DI
           PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       D,0D2h
           LD       E,0CCh
           LD       BC,80h
           LD       HL,IBUFE
RD1:       CALL     MOTOR
           JP       C,RTP6
           CALL     TMARK
           JP       C,RTP6
;   CALL     PRTHL
           CALL     RTAPE
           POP      HL
           POP      BC
           POP      DE
           ;CALL     MSTOP
           PUSH     AF
           LD       A,(TIMFG)
           CP       0F0h
           JR       NZ,RD2
           EI
RD2:       POP      AF
           RET

           ;
           ; READ DATA
           ;
?RDD:      DI
           PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       D,0D2h
           LD       E,53h
           LD       BC,(SIZE)
           LD       HL,(DTADR)
           LD       A,B
           OR       C
           JP       Z,RDD1
           JR       RD1
RDD1:      POP      HL
           POP      BC
           POP      DE
           ;CALL     MSTOP
           PUSH     AF
           LD       A,(TIMFG)
           CP       0F0h
           JR       NZ,RDD2
           EI
RDD2:      POP      AF
           RET

           ;
           ; READ TAPE
           ;
RTAPE:     ;PUSH     BC
           ;PUSH     DE
           ;LD       DE,MSG_READTAPE
           ;CALL     MSG
           ;CALL     NL
           ;POP      DE
           ;POP      BC
           PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       H,2
RTP1:      LD       BC,KEYPB
           LD       DE,CSTR
RTP2:      CALL     EDGE
           JP       C,RTP6
           CALL     DLY3
           LD       A,(DE)
           AND      20h
           JP       Z,RTP2
           LD       D,H
           LD       HL,0
           LD       (SUMDT),HL
           POP      HL
           POP      BC
           PUSH     BC
           PUSH     HL
RTP3:      CALL     RBYTE
           JP       C,RTP6
           LD       (HL),A
           INC      HL
           DEC      BC
           LD       A,B
           OR       C
           JP       NZ,RTP3
           LD       HL,(SUMDT)
           CALL     RBYTE                 ; Checksum MSB
           JP       C,RTP6
           LD       D,A
           CALL     RBYTE                 ; Checksum LSB
           JP       C,RTP6
           LD       E,A
           CP       L
           JP       NZ,RTP5
           LD       A,D
           CP       H
           JP       NZ,RTP5
RTP0:      XOR      A
           ;
           PUSH     HL
           PUSH     DE
           PUSH     DE
           LD       DE,MSG_CHKSUM_MZ1
           CALL     MSGX
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_CHKSUM_TP1
           CALL     MSGX
           POP      DE
           EX       DE,HL
           CALL     PRTHL
           CALL     NL
           POP      DE
           POP      HL
           ;
RTP4:      
RET2:      POP      HL
           POP      BC
           POP      DE
           CALL     MSTOP
           PUSH     AF
           LD       A,(TIMFG)
           CP       0F0h
           JR       NZ,RTP8
           EI
RTP8:      POP      AF
           RET

RTP5:      PUSH     HL
           PUSH     DE
           PUSH     DE
           LD       DE,MSG_CHKSUM_MZ2
           CALL     MSGX
           CALL     PRTHL
           CALL     NL
           LD       DE,MSG_CHKSUM_TP2
           CALL     MSGX
           POP      DE
           EX       DE,HL
           CALL     PRTHL
           CALL     NL
           POP      DE
           POP      HL
           ;
           LD       D,1
           DEC      D
           JR       Z,RTP7
           LD       H,D
           CALL     GAPCK
           JP       RTP1
RTP7:      LD       A,1
           JR       RTP9
RTP6:      LD       A,2
RTP9:      SCF
           JR       RTP4


           ;
           ; EDGE
           ;  BC = KEYPB
           ;  DE = CSTR
           ; EXIT CF = 0 : EDGE
           ;         = 1 : BREAK
           ;
EDGE:      LD       A,0F0h
           LD       (KEYPA),A
           NOP
EDG1:      LD       A,(BC)
           AND      81h             ; SHIFT & BREAK
           JP       NZ,EDG0
           SCF
           RET
EDG0:      LD       A,(DE)
           AND      20h
           JP       NZ,EDG1
EDG2:      LD       A,(BC)
           AND      81h
           JP       NZ,EDG3
           SCF
           RET
EDG3:      LD       A,(DE)
           AND      20h
           JP       Z,EDG2
           RET


           ;
           ; 1 BYTE READ
           ;
           ; EXIT  SUMDT=STORE
           ; CF = 1 : BREAK
           ;    = 0 : DATA=ACC
           ;
RBYTE:     PUSH     BC
           PUSH     DE
           PUSH     HL
           LD       HL,0800h
           LD       BC,KEYPB
           LD       DE,CSTR
RBY1:      CALL     EDGE
           JP       C,RBY3
           CALL     DLY3
           LD       A,(DE)
           AND      20h
           JP       Z,RBY2
           PUSH     HL
           LD       HL,(SUMDT)
           INC      HL
           LD       (SUMDT),HL
           POP      HL
           SCF
RBY2:      LD       A,L
           RLA
           LD       L,A
           DEC      H
           JP       NZ,RBY1
           CALL     EDGE
           LD       A,L
RBY3:      POP      HL
           POP      DE
           POP      BC
           RET

           ;
           ; TAPE MARK DETECT
           ;
           ;    E=@L@     : INFORMATION
           ;     =@S@     : DATA
           ; EXIT CF = 0  : OK
           ;         = 1  : BREAK
           ;
TMARK:     CALL     GAPCK
           PUSH     BC
           PUSH     DE
           PUSH     HL
           PUSH     BC
           PUSH     DE
           LD       DE,MSG_TAPEMARK
           CALL     MSG
           CALL     NL
           POP      DE
           POP      BC
           LD       HL,2828h
           LD       A,E
           CP       0CCh
           JP       Z,TM0
           LD       HL,1414h
TM0:       LD       (TMCNT),HL
           LD       BC,KEYPB
           LD       DE,CSTR
TM1:       LD       HL,(TMCNT)
TM2:       CALL     EDGE
           JP       C,TM4
           CALL     DLY3
           LD       A,(DE)
           AND      20h
           JP       Z,TM1
           DEC      H
           JP       NZ,TM2
;  CALL     PRTHL
TM3:       CALL     EDGE
           JP       C,TM4
           CALL     DLY3
           LD       A,(DE)
           AND      20h
           JP       NZ,TM1
           DEC      L
           JP       NZ,TM3
           CALL     EDGE
RET3:
TM4:       POP      HL
           POP      DE
           POP      BC
           RET

TM4A:      CALL     NL
           CALL     PRTHL       ; Print HL as 4digit hex.
           LD       A,0C4h      ; Move cursor left.
TM4B:      CALL     DPCT
           CALL     DPCT
           CALL     DPCT
           CALL     DPCT
           CALL     NL
           JP       GETL1

           ;
           ; MOTOR ON
           ;
           ;    D=@W@   : WRITE
           ;     =@R@   : READ
           ; EXIT CF=0  : OK
           ;        =1  : BREAK
MOTOR:     PUSH     BC
           PUSH     DE
           PUSH     HL
           PUSH     BC
           PUSH     DE
           LD       DE,MSG_MOTORTG
           CALL     MSG
           CALL     NL
           POP      DE
           POP      BC
           LD       B,10
MOT1:      LD       A,(CSTR)
           AND      10h
           JR       Z,MOT4
MOT2:      LD       B,0A6h
MOT3:      CALL     DLY12
           DJNZ     MOT3
           XOR      A
MOT7:      JR       RET3
MOT4:      LD       A,06h
           LD       HL,CSTPT
           LD       (HL),A
           INC      A
           LD       (HL),A
           DJNZ     MOT1
           CALL     NL
           LD       A,D
           CP       0D7h
           JR       Z,MOT8
           LD       DE,MSG1
           JR       MOT9
MOT8:      LD       DE,MSG3
           CALL     MSGX
           LD       DE,MSG2
MOT9:      CALL     MSGX
MOT5:      LD       A,(CSTR)
           AND      10h
           JR       NZ,MOT2
           CALL     ?BRK
           JR       NZ,MOT5
           SCF
           JR       MOT7

           ;
           ; MOTOR STOP
           ;
MSTOP:     PUSH     AF
           PUSH     BC
           PUSH     DE
           PUSH     BC
           PUSH     DE
           LD       DE,MSG_MOTORSTP
           CALL     MSG
           CALL     NL
           POP      DE
           POP      BC
           LD       B,10
MST1:      LD       A,(CSTR)
           AND      10H
           JR       Z,MST3
MST2:      LD       A,06h
           LD       (CSTPT),A
           INC      A
           LD       (CSTPT),A
           DJNZ     MST1
MST3:      JP       ?RSTR1

           ;
           ; CHECK SUM
           ;
           ;   BC = SIZE
           ;   HL = DATA ADR
           ; EXIT SUMDT=STORE
           ;      CSMDT=STORE
           ;
CKSUM:     PUSH     BC
           PUSH     DE
           PUSH     HL
           LD       DE,0
CKS1:      LD       A,B
           OR       C
           JR       NZ,CKS2
           EX       DE,HL
           LD       (SUMDT),HL
           LD       (CSMDT),HL
           POP      HL
           POP      DE
           POP      BC
           RET
CKS2:      LD       A,(HL)
           PUSH     BC
           LD       B,+8
CKS3:      RLCA
           JR       NC,CKS4
           INC      DE
CKS4:       DJNZ     CKS3
           POP      BC
           INC      HL
           DEC      BC
           JR       CKS1


           ;
           ; 107 uS DELAY
           ;
DLY1:      LD       A,14
DLY1A:     DEC      A
           JP       NZ,DLY1A
           RET

           ;
           ; 240 uS DELAY
           ;
DLY2:      LD       A,13
DLY2A:     DEC      A
           JP       NZ,DLY2A
           RET

           ;
           ; 240 uS x 3 DELAY
           ;
DLY3:      NEG
           NEG
           LD       A,42
           JP       DLY2A

           ;
           ; 12mS DELAY
DLY12:     PUSH     BC
           LD       B,35
DLY12A:    CALL     DLY3
           DJNZ     DLY12A
           POP      BC
           RET


           ;
           ; GAP * TAPEMARK
           ;
           ;  E = @L@   : LONG GAP
           ;    = @S@   : SHORT GAP
           ;
GAP:       PUSH     BC
           PUSH     DE
           PUSH     HL
           LD       A,E
           LD       BC,55F0h           ;Number of pulses for the Long Gap.
           LD       DE,2828h           ;40 + 40 LTM
           CP       0CCh
           JP       Z,GAP0
           LD       BC,2AF8h           ;Number of pulses for a Short Gap.
           LD       DE,1414h           ;20 + 20 LTM
GAP0:      PUSH     DE
           LD       DE,MSG_WGAPS
           CALL     MSG
           ;
GAP1:      CALL     SHORT              ;22000 short GAP pulses.
           LD       H,B
           LD       L,C
           LD       A,000h
           CP       L
           JR       NZ,GAP1D
           CALL     PRTHL              ; Print HL as 4digit hex.
           LD       A,0C4h             ; Move cursor left.
           LD       E,004h             ; 4 times.
GAP1B:     CALL     DPCT
           DEC      E
           JR       NZ,GAP1B
GAP1D:     DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GAP1
           LD       H,B
           LD       L,C
           CALL     PRTHL              ; Print HL as 4digit hex.
           LD       DE,MSG_SPC
           CALL     MSG
           CALL     LETNL
           POP      DE
           ;
           LD       BC,20000            ; 2 Second delay
GAP1C:     CALL     DLY1
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GAP1C
           ;
           PUSH     DE
GAP1A:     LD       DE,MSG_WGAPL
           CALL     MSGX
           POP      DE
GAP2:      PUSH     DE
           CALL     LONG               ;40 or 20 Long Pulses (LTM or STM)
           LD       H,00h
           LD       L,D
           CALL     PRTHL              ; Print HL as 4digit hex.
           LD       A,0C4h             ; Move cursor left.
           LD       E,004h             ; 4 times.
GAP2B:     CALL     DPCT
           DEC      E
           JR       NZ,GAP2B
           LD       BC,1000           ; .1 Second delay
GAP2D:     CALL     DLY1
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GAP2D
           POP      DE
           DEC      D
           JR       NZ,GAP2
           LD       H,000h
           LD       L,D
           CALL     PRTHL              ; Print HL as 4digit hex.
           PUSH     DE
           LD       DE,MSG_SPC
           CALL     MSG
           CALL     LETNL
           POP      DE
           ;
           LD       BC,20000           ; 2 Second delay
GAP2C:     CALL     DLY1
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GAP2C
           ;
GAP2A:     PUSH     DE
           LD       DE,MSG_WGAPS2
           CALL     MSGX
           POP      DE
GAP3:      PUSH     DE
           CALL     SHORT              ;40 or 20 Short Pulses (LTM or STM)
           LD       H,00h
           LD       L,E
           CALL     PRTHL              ; Print HL as 4digit hex.
           LD       A,0C4h             ; Move cursor left.
           LD       E,004h             ; 4 times.
GAP3B:     CALL     DPCT
           DEC      E
           JR       NZ,GAP3B
           LD       BC,1000            ; .1 Second delay
GAP3D:     CALL     DLY1
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GAP3D
           POP      DE
           DEC      E
           JR       NZ,GAP3
           LD       H,000h
           LD       L,E
           CALL     PRTHL              ; Print HL as 4digit hex.
           PUSH     DE
           LD       DE,MSG_SPC
           CALL     MSGX
           CALL     LETNL
           POP      DE
           ;
           LD       BC,20000           ; 2 Second delay
GAP3C:     CALL     DLY1
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,GAP3C
           ;
GAP3A:     PUSH     DE
           LD       DE,MSG_WGAPL2
           CALL     MSGX
           CALL     LETNL
           POP      DE
           CALL     LONG               ;1 Long Pulse
           POP      HL
           POP      DE
           POP      BC
           RET

           ;GAP Test - fixed 80 x short, 80 x long to see if hardware is receiving and counting correctly.
           ;
;GAP:       PUSH     BC
;           PUSH     DE
;GAP0:      LD       BC,050h          ;Number of pulses for the Long Gap.
;GAP1:      CALL     SHORT              
;GAP1A:     DEC      BC
;           LD       A,B
;           OR       C
;           JR       NZ,GAP1
;           LD       BC,0050h          ;Number of pulses for the Long Gap.
;GAP2:      CALL     LONG              
;GAP2A:     DEC      BC
;           LD       A,B
;           OR       C
;           JR       NZ,GAP2
;GAP3A:     JR       GAP3A
;GAP3:      POP      DE
;           POP      BC
;           RET


           ;
           ; GAP CHECK
           ;
GAPCK:     PUSH     BC
           PUSH     DE
           PUSH     HL
           LD       DE,MSG_GAPCK
           CALL     MSG
           CALL     NL
           LD       BC,KEYPB
           LD       DE,CSTR
GAPCK1:    LD       H,100
GAPCK2:    CALL     EDGE
           JR       C,GAPCK3
           CALL     DLY3
           LD       A,(DE)
           AND      20h
           JR       NZ,GAPCK1
           DEC      H
           JR       NZ,GAPCK2
GAPCK3:    JP       RET3

           ;
           ; 1 bit write
           ; Short Pulse
           ;
SHORT:     PUSH     AF
           LD       A,03h
           LD       (CSTPT),A
           CALL     DLY1
           CALL     DLY1
           LD       A,02h
           LD       (CSTPT),A
           CALL     DLY1
           CALL     DLY1
           POP      AF
           RET

           ;
           ; 1 bit write
           ; Long Pulse
           ;
LONG:      PUSH     AF
           LD       A,03h
           LD       (CSTPT),A
           CALL     DLY1
           CALL     DLY1
           CALL     DLY1
           CALL     DLY1
           LD       A,02h
           LD       (CSTPT),A
           CALL     DLY1
           CALL     DLY1
           CALL     DLY1
           CALL     DLY2
           POP      AF
           RET


           ;    WRITE INFORMATION

QWRI:      DI      
           PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       D,0D7H                                                   ; "W"
           LD       E,0CCH                                                   ; "L"
           LD       HL,IBUFE                                                 ; 10F0H
           LD       BC,80H                                                   ; WRITE BYTE SIZE
WRI1:      CALL     CKSUM                                                    ; CHECK SUM
           CALL     MOTOR                                                    ; MOTOR ON
           JR       C,WRI3
           LD       A,E
           CP       0CCH                                                     ; "L" - Long Gap/Tape Mark?
           JR       NZ,WRI2
           CALL     NL
           PUSH     DE
           LD       DE,MSGN7                                                 ; WRITING
           RST      18H                                                      ; CALL MSGX
           LD       DE,NAME                                                  ; FILE NAME
           RST      18H                                                      ; CALL MSGX
           CALL     NL
           POP      DE
WRI2:      CALL     GAP
           CALL     WTAPE
WRI3:      JP       RET2


           ;    WRITE DATA
           ;    EXIT CF=0 : OK
           ;           =1 : BREAK

QWRD:      DI      
           PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       D,0D7H                                                   ; "W"
           LD       E,53H                                                    ; "S"
L047D:     LD       BC,(SIZE)                                                ; WRITE DATA BYTE SIZE
           LD       HL,(DTADR)                                               ; WRITE DATA ADDRESS
           LD       A,B
           OR       C
           JP       Z,RET1
           JR       WRI1

           ;    TAPE WRITE
           ;    BC=BYTE SIZE
           ;    HL=DATA LOW ADDRESS
           ;    EXIT CF=0 : OK
           ;           =1 : BREAK

WTAPE:     PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       D,02H
           LD       A,0F0H                                                   ; 88H WOULD BE BETTER!!
           LD       (KEYPA),A                                                ; E000H
WTAP1:     LD       A,(HL)
           CALL     WBYTE                                                    ; 1 BYTE WRITE
           LD       A,(KEYPB)                                                ; E001H
           AND      81H                                                      ; SHIFT & BREAK
           JP       NZ,WTAP2
           LD       A,02H                                                    ; BREAK IN CODE
           SCF     
           JR       WTAP3

WTAP2:     INC      HL
           DEC      BC
           LD       A,B
           OR       C
           JP       NZ,WTAP1
           LD       HL,(SUMDT)                                               ; SUM DATA SET
           LD       A,H
           CALL     WBYTE                                                    ; Send Checksum
           LD       A,L
           CALL     WBYTE
WTAP3A:    PUSH     DE
           LD       DE,MSG_WGAPL2
           CALL     MSGX
           CALL     LETNL
           POP      DE
           CALL     LONG
           DEC      D
           JP       NZ,L04C2                                                 ; Another copy to be sent?
           OR       A
           JP       WTAP3

L04C2:     PUSH     DE
           LD       DE,MSG_SPCS
           CALL     MSGX
           POP      DE
           LD       B,0                                                      ; Send 256 short pulses.

L04C4:     CALL     SHORT
           LD       H,00h
           LD       L,B
           CALL     PRTHL              ; Print HL as 4digit hex.
           LD       A,0C4h             ; Move cursor left.
           LD       E,004h             ; 4 times.
SPCS2:     CALL     DPCT
           DEC      E
           JR       NZ,SPCS2
           DEC      B
           JP       NZ,L04C4
           LD       H,00h
           LD       L,B
           CALL     PRTHL              ; Print HL as 4digit hex.
           LD       BC,2500            ; .25 Second delay
SPCS3:     CALL     DLY1
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,SPCS3
           CALL     LETNL
           POP      HL                                                       ; Retrieve saved location and size
           POP      BC
           PUSH     BC
           PUSH     HL
           JP       WTAP1                                                    ; Repeat send.

WTAP3:
RET1:      POP      HL
           POP      BC
           POP      DE
           RET     

           DB       2FH
           DB       4EH

           ;    VERIFY (FROM $CMT)
           ;    EXIT ACC=0 : OK CF=0
           ;            =1 : ER CF=1
           ;            =2 : BREAK CF=1

QVRFY:     DI      
           PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       BC,(SIZE)
           LD       HL,(DTADR)
           LD       D,0D2H                                                   ; "R"
           LD       E,53H                                                    ; "S"
           LD       A,B
           OR       C
           JP       Z,RTP4                                                   ; END
           CALL     CKSUM
           CALL     MOTOR
           JP       C,RTP6                                                   ; BRK
           CALL     TMARK                                                    ; TAPE MARK DETECT
           JP       C,RTP6                                                   ; BRK
           CALL     TVRFY
           JP       RTP4

           ;    DATA VERIFY
           ;    BC=SIZE
           ;    HL=DATA LOW ADDRESS
           ;    CSMDT=CHECK SUM
           ;    EXIT ACC=0 : OK  CF=0
           ;            =1 : ER    =1
           ;            =2 : BREAK =1

TVRFY:     PUSH     DE
           PUSH     BC
           PUSH     HL
           LD       H,02H                                                    ; COMPARE TWICE
TVF1:      LD       BC,KEYPB
           LD       DE,CSTR
TVF2:      CALL     EDGE
           JP       C,RTP6                                                   ; BRK
           CALL     DLY3                                                     ; CALL DLY2*3
           LD       A,(DE)
           AND      20H
           JP       Z,TVF2
           LD       D,H
           POP      HL
           POP      BC
           PUSH     BC
           PUSH     HL
           ;    COMPARE TAPE DATA AND STORAGE
TVF3:      CALL     RBYTE
           JP       C,RTP6                                                   ; BRK
           CP       (HL)
           JP       NZ,RTP7                                                  ; ERROR, NOT EQUAL
           INC      HL                                                       ; STORAGE ADDRESS + 1
           DEC      BC                                                       ; SIZE - 1
           LD       A,B
           OR       C
           JR       NZ,TVF3
           ;    COMPARE CHECK SUM (1199H/CSMDT) AND TAPE
           LD       HL,(CSMDT)
           CALL     RBYTE
           CP       H
           JP       NZ,RTP7                                                  ; ERROR, NOT EQUAL
           CALL     RBYTE
           CP       L
           JP       NZ,RTP7                                                  ; ERROR, NOT EQUAL
           DEC      D                                                        ; NUMBER OF COMPARES (2) - 1
           JP       Z,RTP8                                                   ; OK, 2 COMPARES
           LD       H,D                                                      ; (-->05C7H), SAVE NUMBER OF COMPARES
           JR       TVF1                                                     ; NEXT COMPARE

           ;    1 BYTE WRITE

WBYTE:     PUSH     BC
           LD       B,8
           CALL     LONG
WBY1:      RLCA    
           CALL     C,LONG
           CALL     NC,SHORT
           DEC      B
           JP       NZ,WBY1
           POP      BC
           RET     

ARARA:     POP      HL
           JP       ABCD

DLY1S:     PUSH     AF
           PUSH     BC
           LD       C,10
L0324:     CALL     DLY12
           DEC      C
           JR       NZ,L0324
           POP      BC
           POP      AF
           RET

           ; Test the 8253 Timer, configure it as per the monitor and display the read back values.
TIMERTST:  CALL     NL
           LD       DE,MSG_TIMERTST
           CALL     MSG
           CALL     NL
           LD       DE,MSG_TIMERVAL
           CALL     MSG
           LD       A,01h
           LD       DE,8000h
           CALL     ?TMST
NDE:       JP       NDE
           JP       GETL1
?TMST:     DI      
           PUSH     BC
           PUSH     DE
           PUSH     HL
           LD       (AMPM),A
           LD       A,0F0H
           LD       (TIMFG),A
ABCD:      LD       HL,0A8C0H
           XOR      A
           SBC      HL,DE
           PUSH     HL
           INC      HL
           EX       DE,HL

           LD       HL,CONTF    ; Control Register
           LD       (HL),0B0H   ; 10110000 Control Counter 2 10, Write 2 bytes 11, 000 Interrupt on Terminal Count, 0 16 bit binary
           LD       (HL),074H   ; 01110100 Control Counter 1 01, Write 2 bytes 11, 010 Rate Generator, 0 16 bit binary
           LD       (HL),030H   ; 00110100 Control Counter 1 01, Write 2 bytes 11, 010 interrupt on Terminal Count, 0 16 bit binary

           LD       HL,CONT2    ; Counter 2
           LD       (HL),E
           LD       (HL),D

           LD       HL,CONT1    ; Counter 1
           LD       (HL),00AH
           LD       (HL),000H

           LD       HL,CONT0    ; Counter 0
           LD       (HL),00CH
           LD       (HL),0C0H

;           LD       HL,CONT2    ; Counter 2
;           LD       C,(HL)
;           LD       A,(HL)
;           CP       D
;           JP       NZ,L0323                
;           LD       A,C
;           CP       E
;           JP       Z,CDEF                
           ;

L0323:     PUSH     AF
           PUSH     BC
           PUSH     DE
           PUSH     HL
           ;
           LD       HL,CONTF    ; Control Register
           LD       (HL),080H
           LD       HL,CONT2    ; Counter 2
           LD       C,(HL)
           LD       A,(HL)
           CALL     PRTHX
           LD       A,C
           CALL     PRTHX
           ;
           CALL     PRNTS
           ;CALL     DLY1S
           ;
           LD       HL,CONTF    ; Control Register
           LD       (HL),040H
           LD       HL,CONT1    ; Counter 1
           LD       C,(HL)
           LD       A,(HL)
           CALL     PRTHX
           LD       A,C
           CALL     PRTHX
           ;
           CALL     PRNTS
           ;CALL     DLY1S
           ;
           LD       HL,CONTF    ; Control Register
           LD       (HL),000H
           LD       HL,CONT0    ; Counter 0
           LD       C,(HL)
           LD       A,(HL)
           CALL     PRTHX
           LD       A,C
           CALL     PRTHX
           ;
           ;CALL     DLY1S
           ;
           LD       A,0C4h      ; Move cursor left.
           LD       E,0Eh      ; 4 times.
L0330:     CALL     DPCT
           DEC      E
           JR       NZ,L0330
           ;
;           LD       C,20
;L0324:     CALL     DLY12
;           DEC      C
;           JR       NZ,L0324
           ;
           POP      HL
           POP      DE
           POP      BC
           POP      AF
           ;
           LD       HL,CONT2    ; Counter 2
           LD       C,(HL)
           LD       A,(HL)
           CP       D
           JP       NZ,L0323                
           LD       A,C
           CP       E
           JP       NZ,L0323                
           ;
           ;
           PUSH     AF
           PUSH     BC
           PUSH     DE
           PUSH     HL
           CALL     NL
           CALL     NL
           CALL     NL
           LD       DE,MSG_TIMERVAL2
           CALL     MSG
           POP      HL
           POP      DE
           POP      BC
           POP      AF

           ;
CDEF:      POP      DE
           LD       HL,CONT1
           LD       (HL),00CH
           LD       (HL),07BH
           INC      HL

L0336:     PUSH     AF
           PUSH     BC
           PUSH     DE
           PUSH     HL
           ;
           LD       HL,CONTF    ; Control Register
           LD       (HL),080H
           LD       HL,CONT2    ; Counter 2
           LD       C,(HL)
           LD       A,(HL)
           CALL     PRTHX
           LD       A,C
           CALL     PRTHX
           ;
           CALL     PRNTS
           CALL     DLY1S
           ;
           LD       HL,CONTF    ; Control Register
           LD       (HL),040H
           LD       HL,CONT1    ; Counter 1
           LD       C,(HL)
           LD       A,(HL)
           CALL     PRTHX
           LD       A,C
           CALL     PRTHX
           ;
           CALL     PRNTS
           CALL     DLY1S
           ;
           LD       HL,CONTF    ; Control Register
           LD       (HL),000H
           LD       HL,CONT0    ; Counter 0
           LD       C,(HL)
           LD       A,(HL)
           CALL     PRTHX
           LD       A,C
           CALL     PRTHX
           ;
           CALL     DLY1S
           ;
           LD       A,0C4h      ; Move cursor left.
           LD       E,0Eh      ; 4 times.
L0340:     CALL     DPCT
           DEC      E
           JR       NZ,L0340
           ;
           POP      HL
           POP      DE
           POP      BC
           POP      AF

           LD       HL,CONT2    ; Counter 2
           LD       C,(HL)
           LD       A,(HL)
           CP       D
           JR       NZ,L0336                
           LD       A,C
           CP       E
           JR       NZ,L0336                
           CALL     NL
           LD       DE,MSG_TIMERVAL3
           CALL     MSG
           POP      HL
           POP      DE
           POP      BC
           EI      
           RET     

?TMRD:     PUSH     HL
           LD       HL,CONTF
           LD       (HL),080H
           DEC      HL
           DI      
           LD       E,(HL)
           LD       D,(HL)
           EI      
           LD       A,E
           OR       D
           JR       Z,?TMR1                 
           XOR      A
           LD       HL,0A8C0H
           SBC      HL,DE
           JR       C,?TMR2                 
           EX       DE,HL
           LD       A,(AMPM)
           POP      HL
           RET     

?TMR1:     LD       DE,0A8C0H
?TMR1A:    LD       A,(AMPM)
           XOR      001H
           POP      HL
           RET     

?TMR2:     DI      
           LD       HL,CONT2
           LD       A,(HL)
           CPL      
           LD       E,A
           LD       A,(HL)
           CPL      
           LD       D,A
           EI      
           INC      DE
           JR       ?TMR1A     

TIMIN:     PUSH     AF
           PUSH     BC
           PUSH     DE
           PUSH     HL
           LD       HL,AMPM
           LD       A,(HL)
           XOR      001H
           LD       (HL),A
           LD       HL,CONTF
           LD       (HL),080H
           DEC      HL
           PUSH     HL
           LD       E,(HL)
           LD       D,(HL)
           LD       HL,0A8C0H
           ADD      HL,DE
           DEC      HL
           DEC      HL
           EX       DE,HL
           POP      HL
           LD       (HL),E
           LD       (HL),D
           POP      HL
           POP      DE
           POP      BC
           POP      AF
           EI      
           RET

           ; Method to clear memory either to 0 or a given pattern.
           ;
CLR8Z:     XOR      A
CLR8:      LD       BC,00800H
CLRMEM:    PUSH     DE
           LD       D,A
L09E8:     LD       (HL),D
           INC      HL
           DEC      BC
           LD       A,B
           OR       C
           JR       NZ,L09E8                
           POP      DE
           RET     

           ; Help/Synoposis of commands available.
           ;
HELP:      CALL     LETNL
           LD       DE,MSG_HELP1
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP2
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP3
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP4
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP5
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP6
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP7
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP8
           CALL     MSG
           CALL     LETNL
           LD       DE,MSG_HELP9
           CALL     MSG
           CALL     LETNL
           CALL     LETNL
           JP       GETL1

TMPADR:    DW       00000H
GPUCHAR:   DW       00000H
GPUATTR:   DW       00000H
GPUSTARTX: DW       00000H
GPUSTARTY: DW       00000H
GPUENDX:   DW       00000H
GPUENDY:   DW       00000H


MSG_HELP1: DB       "GRPH[1-2]= TEST GRAPHICS",   0Dh, 00h
MSG_HELP2: DB       "GPU[1-2] = TEST GPU",        0Dh, 00h
MSG_HELP3: DB       "PAL      = TEST PALETTE",    0Dh, 00h
MSG_HELP4: DB       "MEMTEST  = TEST MEMORY",     0Dh, 00h
MSG_HELP5: DB       "LOAD     = LOAD TAPE",       0Dh, 00h
MSG_HELP6: DB       "TIMER    = TIMER TEST",      0Dh, 00h
MSG_HELP7: DB       "SAVE     = WRITE TEST TAPE", 0Dh, 00h
MSG_HELP8: DB       "VGA[0-3] = SET VGA MODE",    0Dh, 00h
MSG_HELP9: DB       "QUIT     = QUIT TO MONITOR", 0Dh, 00h

TITLE:     DB       "SHARPMZ TESTER (C) P.SMART 2018-20", 0Dh, 00h
MSG_INITGR:DB       "INIT GRAPHICS", 0Dh
MSG_INITM: DB       "INIT MEMORY", 0Dh
TITLE_SAVE:DB       "WRITE TEST TAPE", 0Dh
            
MSGBADCMD: DB       "???", 0DH, 00H
MSG1:      DW       207Fh
MSG2:      DB       "PLAY", 0Dh, 00h
MSG3:      DW       207Fh                     ; PRESS RECORD
           DB       "RECORD.", 0Dh, 00h
MSGN7:     DB       "WRITING ", 0Dh, 00h
MSGOK:     DB       "OK", 0Dh, 00h
MSG_ERRCHKSUM:
           DB       "CHECKSUM ERROR", 0Dh
MSG_ERRWRITE:
           DB       "WRITE ERROR", 0Dh

MSG_READTAPE:
           DB       "READ TAPE", 0Dh, 00h
MSG_TAPEMARK:
           DB       "TAPEMARK", 0Dh, 00h
MSG_MOTORTG:
           DB       "MOTOR TOGGLE", 0Dh, 00h
MSG_MOTORSTP:
           DB       "MOTOR STOP", 0Dh, 00h
MSG_TPMARK:
           DB       "TAPE MARK START", 0Dh, 00h
MSG_GAPCK:
           DB       "GAP CHECK", 0Dh, 00h
MSG_LOADFILE:
           DB       "LOAD FILE          = ",0Dh, 00h
MSG_LOADFROM:
           DB       "LOAD ADDRESS       = ", 0Dh, 00h
MSG_LOADEXEC:
           DB       "EXEC ADDRESS       = ", 0Dh, 00h
MSG_LOADSIZE:
           DB       "LOAD SIZE          = ", 0Dh, 00h
MSG_SAVEFILE:
           DB       "SAVE FILE          = ",0Dh, 00h
MSG_SAVEFROM:
           DB       "SAVE ADDRESS       = ", 0Dh, 00h
MSG_SAVEEXEC:
           DB       "SAVE EXEC ADDRESS  = ", 0Dh, 00h
MSG_SAVESIZE:
           DB       "SAVE SIZE          = ", 0Dh, 00h
MSG_CHKSUM_MZ1:
           DB       "  MZ CHECKSUM (OK) = ", 0Dh, 00h
MSG_CHKSUM_TP1:
           DB       "TAPE CHECKSUM (OK) = ", 0Dh, 00h
MSG_CHKSUM_MZ2:
           DB       "  MZ CHECKSUM (ER) = ", 0Dh, 00h
MSG_CHKSUM_TP2:
           DB       "TAPE CHECKSUM (ER) = ", 0Dh, 00h
MSG_WHDR:  DB       "WRITE HEADER...", 0Dh
MSG_WDATA: DB       "WRITE DATA...", 0Dh
MSGGAP:    DB       "GAP WRITTEN", 0Dh, 00h
MSG_WGAPS: DB       "WRITE GAP: ", 0Dh, 00h
MSG_WGAPS2:DB       "WRITE TM SHORT: ", 0Dh, 00h
MSG_WGAPL: DB       "WRITE TM LONG: ", 0Dh, 00h
MSG_WGAPL2:DB       "WRITE 1 LONG BIT", 0Dh, 00h
MSG_SPCS:  DB       "WRITE 256 SHORT: ", 0Dh, 00h
MSG_SPC:   DB       ", WAIT.", 0Dh, 00h
MSGTAPE    DB       "HEADER WRITTEN", 0Dh, 00h
MSG_TIMERTST:
           DB      "8253 TIMER TEST", 0Dh, 00h
MSG_TIMERVAL:
           DB      "READ VALUE 1: ", 0Dh, 00h
MSG_TIMERVAL2:
           DB      "READ VALUE 2: ", 0Dh, 00h
MSG_TIMERVAL3:
           DB      "READ DONE.", 0Dh, 00h

OKCHECK:   DB      ", CHECK: ", 0Dh
OKMSG:     DB      " OK.", 0Dh
DONEMSG:   DB      11h
           DB      "RAM TEST COMPLETE.", 0Dh

BITMSG:    DB      " BIT:  ", 0Dh
BANKMSG:   DB      " BANK: ", 0Dh

GRPHPOS:   DB      00h, 00h

           ; Test tape image to save.
TESTBUF:                                                                 ; TAPE BUFFER (128 BYTES)
TATRB:     DB       02h                                                  ; Code Type, 01 = Machine Code.
TNAME:     DB       "TEST TAPE SAVE", 0Dh, 00h, 00h                      ; Title/Name (17 bytes).
TSIZE:     DW       TESTEND - TESTSTART                                  ; Size of program.
TDTADR:    DW       TESTSTART                                            ; Load address of program.
TEXADR:    DW       TESTSTART                                            ; Exec address of program.
TCOMNT:    DB       "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

TESTSTART: DB       01h
           DB       0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
           DB       16,17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31
           DB       32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
           DB       48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
           DB       64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79
           DB       80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95
           DB       96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111
           DB       112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127
           DB       128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143
           DB       144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159
           DB       160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175
           DB       176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191
           DB       192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207
           DB       208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223
           DB       224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239
           DB       240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 
TESTEND:

MEND:
