Sharp MZ-80A Elementary Graphics Tricks and Tips

Waiting for VSync

This very short routine shows how to wait for the vertical sync on the MZ-80A. Once the VSync is active you can
begin modifying the screen.

LOOP: LD A,(0E002H)
RLA
JR C,LOOP

; Get VSync state
; Rotate into carry
; Jump to Loop if carry set

The MZ's VSync is stored at memory mapped I/O address E002. The most significant bit (bit 7) stores
the current state of the VSync. On the MZ this is set to a '1' for most of the screen draw. Once VSync
becomes active it's set to a '0'.

Horizontal Raster Split

This routine makes use of the VSync (at address E002) to wait until display begins. The display is set
to inverse-video (via address E015) until a number of lines later when it is reverted back to standard
video (via address E014). Pressing Space will exit the program.

LD HL,0D000H
LD DE,0D001H
LD BC,03E8H
LD (HL),01H
LDIR

; First we fill
; one page of screen
; memory with the
; letter 'A'

LD A,(0E200H)

; Ensure display rolled UP

LOOP: LD A,(0E002H)
RLA
JR C,LOOP

; Wait for VSync to
; be active
; (C = 0 means VSync active)

LD A,(0E015H)

; Inverse video ON

LD BC,02D0H
LOOP2: NOP
DEC BC
LD A,B
OR C
JR NZ,LOOP2

; Set up long
; delay counter to
; wait a number of lines

LD A,(0E014H)

; Inverse video OFF

LD A,0F4H
LD (0E000H),A
NOP
LD A,(0E001H)
AND 1
JR NZ,LOOP

; Test to see if
; Spacebar has been
; pressed. If not then
; jump back to LOOP

RET

VGATE : Switch display off during frame

The MZ has a useful feature of its display circuitry referred to in documentation as VGate. This is a toggle which allows the
display to be switched off completely but drawing to the screen can still occur. When the display is switched on again any changes
to the screen are shown. We can make use of VGate, however, to switch the display off anywhere during a single frame and back on
again in the same frame. This would allow, as shown in the below code, splitting of characters to only show portions of a character
at a time and would also help with smooth scrolls or gradual appearances of screens (scanline by scanline). VGate is accessed by
writing a '1' or a '0' to the least significant bit (bit 0) of memory mapped i/o address E002

LD A,(0E200H)

; Ensure display rolled UP

LD HL,0D000H
LD DE,0D001H
LD BC,03E8H
LD (HL),01H
LDIR

; First we fill
; one page of screen
; memory with the
; letter 'A'

LD HL,0E002H

; Store 8255 chip memory i/o address in HL

LOOP: LD A,(HL)
RLA
JR C,LOOP

; Wait for VSync to
; be active
; (C = 0 means VSync active)

LD BC,02D0H
LOOP2: NOP
DEC BC
LD A,B
OR C
JR NZ,LOOP2

; Set up long
; delay counter to
; wait a number of lines

RES 0,(HL)

; Switch display OFF

LD BC,0108H
LOOP3: NOP
DEC BC
LD A,B
OR C
JR NZ,LOOP3

; Set up delay
; counter to
; wait a few more lines

SET 0,(HL)

; Switch display back ON

LD A,0F4H
LD (0E000H),A
NOP
LD A,(0E001H)
AND 1
JR NZ,LOOP

; Test to see if
; Spacebar has been
; pressed. If not then
; jump back to LOOP

RET

Character Split

There is no facility on the MZ-80A to redefine the in-built character set, unlike the more popular 8-bit machines. The character set is
stored on a ROM chip and there is no pointer in RAM that can be changed to redirect character generation to any other block of
RAM. This is by design of the display hardware. However, given the right timings and having enough time left each frame, you can
split a character space in video RAM between a number of different characters. Below is a routine that will split the top half of the
'A' character with the bottom half of the 'B' character in the top-left corner of the screen (screen memory address D000 with screen
rolled fully up)

LD A,(0E200H)

; Ensure display rolled UP

LD A,0C6H
CALL 0DDCH

; Clear the screen

LD HL,0D000H

; Set HL to start of video RAM

LOOP: LD A,(0E002H)
RLA
JR C,LOOP

; Wait for
; VSync to occur

LD (HL),01H

; Place letter 'A' on top-left

LD BC,0109H
LOOP2: NOP
DEC BC
LD A,B
OR C
JR NZ,LOOP2

; Set up long
; delay counter to
; wait a number of lines

LD (HL),02H

; Place letter 'B' on top-left
; very soon after drawing 'A'

LD A,0F4H
LD (0E000H),A
NOP
LD A,(0E001H)
AND 1
JR NZ,LOOP

; Test to see if
; Spacebar has been
; pressed. If not then
; jump back to LOOP

RET

Double Buffer Horizontal Split

The MZ-80A has the unique ability to scroll its screen vertically in either direction
without losing any display characters. To do this it has 2000 bytes of video RAM set
aside for its display. Only 1000 bytes are shown at any one time (the screen is 40
characters wide by 25 character lines). The particular 1000 bytes shown on the screen
can be selected simply by reading one of the memory mapped I/O addresses between the
address range E200 to E2FF (the display shifts by 8 characters at a time). This 2000
bytes can be useful as a double-buffer for games.

With this knowledge we can fill one set of 1000 bytes with, for instance, the character
'A' and fill the other 1000 bytes with character 'B'. Halfway through each frame we can
suddenly change the pointer to VRAM and roll the screen down to the next 1000 bytes.
Finally we can roll the display all the way up again for the top of each frame. You will
see, with the below code, that this can happen at any line and it splices the letter 'A'
and letter 'B' horizontally down the middle.

This technique can, no doubt, be put to great effect in games to create smooth
pixel-by-pixel transitions between different 'playfields' which are stored in different
parts of VRAM. The switch of the VRAM pointer is very quick so many changes could
potentially happen per frame.

LD HL,0D000H
LD DE,0D001H
LD BC,03E8H
LD (HL),01H
LDIR

; First we fill
; one page of screen
; memory with the
; letter 'A'

LD HL,0D3E9H
LD DE,0D3EAH
LD BC,03E8H
LD (HL),02H
LDIR

; Now we fill
; the second page of screen
; memory with the
; letter 'B'

LOOP: LD A,(0E002H)
RLA
JR C,LOOP

; Wait for VSync to
; be active
; (C = 0 means VSync active)

LD A,(0E200H)

; Ensure display rolled UP

LD BC,02D0H
LOOP2: NOP
DEC BC
LD A,B
OR C
JR NZ,LOOP2

; Set up long
; delay counter to
; wait a number of lines

LD A,(0E27DH)

; Roll screen down to
; the top of 2nd 1000 bytes

LD A,0F4H
LD (0E000H),A
NOP
LD A,(0E001H)
AND 1
JR NZ,LOOP

; Test to see if
; Spacebar has been
; pressed. If not then
; jump back to LOOP