Quaracterdisplay, a new discovered graphical display on the ZX81

For those of you watching in black and white, the pink is next to the green...
Post Reply
Dr beep
Manic Miner
Posts: 391
Joined: Mon Oct 01, 2018 8:53 pm

Quaracterdisplay, a new discovered graphical display on the ZX81

Post by Dr beep »

The displaymethod of the ZX81 is widely described by Wilf Rigter
(https://8bit-museum.de/heimcomputer-2/s ... ay-system/).
The lowresdisplay focuses around this intruptroutine:

Code: Select all

0038               ;INT SERVICE ROUTINE
     DEC C         ;decrement the scan line counter in register C
     JP NZ 0045    ;go SCAN-LINE : repeats 8 times for each DFILE character row
     POP HL        ;point to the start of next DFILE row
     DEC B         ;decrement the ROW counter in register B
     RET Z         ;return to 028B
     SET 3,C       ;load scan line counter in register C with 08 scan lines

0041               ;WAIT-INT
     LD R,A        ;load value DD into register R
     EI            ;enable INT
     JP (HL)       ;execute the NOPs in DFILE

0045               ;SCAN-LINE
     POP DE        ;discard the return address
     RET Z         ;delay (never returns)
     JR 0041       ;got WAIT-INT
When a displayline ends in a HALT the computer waits for an intrupt and then makes a CALL
to #0038. The C-register holds a value from 8 to 1 for each part of the character that needs to be displayed.
In this way the same line is executed 8 times to make a display of a character by the hardware.
All the time the next pointer in the same character is displayed. The character doesn't alter.
During the 8 times the display is done the value of HL does not change, it changes to the next line
when C reaches 0 allowing the ROM to display the next line.
What if you could somehow alter the current displayline during the display?
The ROM would still point to the next pointer to display but the character could be changed.
This would create a new displayed character composed of multiple characters.

How to get this work?
When using pseudo-hires or true-hires the programmer makes a customized displayroutine
which is started by altering the IX-register. This method is using the default ROM-displayroutine,
but how do you get to the next line while displaying the current line?
The ZX81 does 1 check during the display. It checks if the next byte to display has
bit 6 set. Bit 6 is set in the HALT-opcode. Although during the development of the
ZX81 this bit was only used for detecting the HALT and executing it allows other opcodes with
bit 6 set to be executed too during the display.

After the first displayed line the pointer to the next line is held in DE, only when the line ends HL gets a new value.
We need to copy the value of DE into HL. The instructions to do this must also have bit 6 set or the character will
be displayed and not executed. LD H,D and LD L,E both have bit 6 set so we can copy DE into HL with these commands.
But how does this work during the display?

To have this working there is 1 rule:
When activating this method both DE and HL need to have the same value. This can be done in 2 ways but the
easiest is 1 line displayed with normal charachter display, like a top line with score, name of the game and lives
or just a single empty line. An examplescreen, the opcodes are written but must become the poked values #62 and #6B.

#76
A NORMAL LINE HALT ONLY IS ALSO OK #76
LINE1 NR 1 (LD H,D) (LD L,E) #76
LINE2 NR 2 (LD H,D) (LD L,E) #76
LINE3 NR 3 (LD H,D) (LD L,E) #76
LINE4 NR 4 (LD H,D) (LD L,E) #76

At the start of LINE1 both HL and DE will point to LINE1. At the end of the line HL is altered in DE but it still
is the same value. After the HALT, DE changes into LINE2. Since HL is not altered (yet) the ROM-display will again
diplay the characters of LINE1 but now the second line of the character, like the ROM does. This time just before
the HALT, HL changes into the value of LINE2 as held in DE. The ROM will now display the third line of a character but the
pointer to the character (=HL) has changed and so line 3 (and 4) from the next characterline will be displayed.
This continues into LINE3 and LINE4, but after the 8th line HL is altered by the ROM. DE already got the right value
during the display of line7 of the character so DE and HL match again for the next line.
You can start a line with the LD H,D and LD L,E but that will give 2 spaces at the start of a line.

Advantages and disadvantages of this method
Pro:
With the charactergenerator it is easy to create the characters to display.
You have a more flexible characterset on the ZX81.
The screen is 4x the old screen where pseudo-hires or hires is 8x the old screen.
You don't need a customized displayroutine.
It runs with ANY RAM-pack.

Con:
The display is character based so movement is also characterbased.
Like pseudo-hires the characterset in bound to the values in the ROM.

Is it possible to change the characterset each line?
Yes, it is possible however this needs exact calculation of the number of lines to display and is not as
simple as the 2 values to poke on the screen as the double lined display. It would also make the screen
the same size as a pseude-hires display.

I told a full charactermode was also possible.

This however needs some other setup.

The first line (before the first linefeed on dfile) needs some set up.

Code: Select all

; the display file, Code the lines needed.
dfile

	jp	lowset		; back to LOWMEM to set registers
lowset	ld	b,192
	ld	d,c		; set D to 1 to make each line a new character
	jp	hidisp+#8000	; and back to highdisplay
hidisp	halt
The screen is executed in upper memory. In uppermemory we can only execute opcodes with bit 6 set, so first we jump back to lowermemory.
Then we set the number of individual lines in the B-register. Here we will have 192 lines of this new displaymethod.
The screen is therefore in size equivalent to pseudohires.
Then we need a register with the value of 1. C holds the value of 1 here so we can copy C in D.
Next we do the normal display again.
NOTE: this will NOT work with 32K RAM

Now when an intrupts occur DEC C will become 0 and the next line is loaded in HL with the POP HL in the ROM.
Then C is set to 8 for 8 lines of display, but then the next part kicks in

Code: Select all

	ld	c,d		; undo setting of C to 8
	db	8		; your character(s)
	halt
	ld	c,d
	db	136
	halt
	ld	c,d
	db	8
	halt
	ld	c,d
	db	136
	halt
	ld	c,d
	db	8
	halt
	ld	c,d
	db	136
	halt
	ld	c,d
	db	8
	halt
	ld	c,d
	db	136
	halt

; fill full screen or end with these 2 bytes	
	ld	c,d
	jp	(hl)		; the trick to fill the screen without extra lines needed
We need to set C to 1 again to go to the next line, since POP DE is not used anymore we can set C to 1 with the LD C,D
Repeat this on every line and your character can alter 8 times during display

So with this new method the game MUSHROOMMAN is converted to the ZX81.

The Lambda 8300 is a ZX81 clone but not capable of pseudo- and hires display.
This method however also works on a Lambda so MUSHROOMMAN is now also ported to the Lambda.

After more than 40 years the Lambda has some kind of extende graphical mode.
Dr beep
Manic Miner
Posts: 391
Joined: Mon Oct 01, 2018 8:53 pm

Re: Quaracterdisplay, a new discovered graphical display on the ZX81

Post by Dr beep »

The last days I am thinking how to add this new displaymethod to my SP-2-ZX81 emulator.
The emultor is optimized for speed not for perfect emulation.

I think I can add this method but it will slow down the emulator.
I have won some speed in optimizing the display of the screen so I hope when I have this method working the speed will not drop too much.
Post Reply