Elementary Tricks & Tips

The 8253 chip inside the MZ-80A. This is what we'll be controlling through software a lot of the time for our graphics effects

The 8253 chip inside the MZ-80A. This is what we’ll be controlling through software a lot of the time for our graphics effects

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)          ; Get VSync state
RLA                          ; Rotate into carry
JR C,LOOP                    ; Jump to Loop if carry set

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.

Inverse Split

Inverse Split


LD HL,0D000H                 ; First we fill
LD DE,0D001H                 ; one page of screen
LD BC,03E8H                  ; memory with the
LD (HL),01H                  ; letter 'A'
LDIR

LD A,(0E200H)                ; Ensure display rolled UP

LOOP: LD A,(0E002H)          ; Wait for VSync to
RLA                          ; be active
JR C,LOOP                    ; (C = 0 means VSync active)

LD A,(0E015H)                ; Inverse video ON

LD BC,02D0H                  ; Set up long
LOOP2: NOP                   ; delay counter to
DEC BC                       ; wait a number of lines
LD A,B
OR C
JR NZ,LOOP2

LD A,(0E014H)                ; Inverse video OFF

LD A,0F4H                    ; Test to see if
LD (0E000H),A                ; Spacebar has been
NOP                          ; pressed. If not then
LD A,(0E001H)                ; jump back to LOOP
AND 1
JR NZ,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

VGATE Split

VGATE Split


LD A,(0E200H)                ; Ensure display rolled UP

LD HL,0D000H                 ; First we fill
LD DE,0D001H                 ; one page of screen
LD BC,03E8H                  ; memory with the
LD (HL),01H                  ; letter 'A'
LDIR

LD HL,0E002H                 ; Store 8255 chip memory i/o address in HL

LOOP: LD A,(HL)              ; Wait for VSync to
RLA                          ; be active
JR C,LOOP                    ; (C = 0 means VSync active)

LD BC,02D0H                  ; Set up long
LOOP2: NOP                   ; delay counter to
DEC BC                       ; wait a number of lines
LD A,B
OR C
JR NZ,LOOP2

RES 0,(HL)                   ; Switch display OFF

LD BC,0108H                  ; Set up delay
LOOP3: NOP                   ; counter to
DEC BC                       ; wait a few more lines
LD A,B
OR C
JR NZ,LOOP3

SET 0,(HL)                   ; Switch display back ON

LD A,0F4H                    ; Test to see if
LD (0E000H),A                ; Spacebar has been
NOP                          ; pressed. If not then
LD A,(0E001H)                ; jump back to LOOP
AND 1
JR NZ,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)

Character Split

Character Split


LD A,(0E200H)                 ; Ensure display rolled UP

LD A,0C6H                     ; Clear the screen
CALL 0DDCH

LD HL,0D000H                  ; Set HL to start of video RAM

LOOP: LD A,(0E002H)           ; Wait for
RLA                           ; VSync to occur
JR C,LOOP

LD (HL),01H                   ; Place letter 'A' on top-left

LD BC,0109H                   ; Set up long
LOOP2: NOP                    ; delay counter to
DEC BC                        ; wait a number of lines
LD A,B
OR C
JR NZ,LOOP2

LD (HL),02H                   ; Place letter 'B' on top-left
                              ; very soon after drawing 'A'

LD A,0F4H                     ; Test to see if
LD (0E000H),A                 ; Spacebar has been
NOP                           ; pressed. If not then
LD A,(0E001H)                 ; jump back to LOOP
AND 1
JR NZ,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.

VRAM Split

VRAM Split


LD HL,0D000H                  ; First we fill
LD DE,0D001H                  ; one page of screen
LD BC,03E8H                   ; memory with the
LD (HL),01H                   ; letter 'A'
LDIR

LD HL,0D3E9H                  ; Now we fill
LD DE,0D3EAH                  ; the second page of screen
LD BC,03E8H                   ; memory with the
LD (HL),02H                   ; letter 'B'
LDIR

LOOP: LD A,(0E002H)           ; Wait for VSync to
RLA                           ; be active
JR C,LOOP                     ; (C = 0 means VSync active)

LD A,(0E200H)                 ; Ensure display rolled UP

LD BC,02D0H                   ; Set up long
LOOP2: NOP                    ; delay counter to
DEC BC                        ; wait a number of lines
LD A,B
OR C
JR NZ,LOOP2

LD A,(0E27DH)                 ; Roll screen down to
                              ; the top of 2nd 1000 bytes

LD A,0F4H                     ; Test to see if
LD (0E000H),A                 ; Spacebar has been
NOP                           ; pressed. If not then
LD A,(0E001H)                 ; jump back to LOOP
AND 1
JR NZ,LOOP

RET

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s