"Quaracter"-display, how it actually works.

Any discussions related to the creation of new hardware or software for the ZX80 or ZX81
dr beep
Posts: 2341
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

"Quaracter"-display, how it actually works.

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.
User avatar
mrtinb
Posts: 1979
Joined: Fri Nov 06, 2015 5:44 pm
Location: Denmark
Contact:

Re: "Quaracter"-display, how it actually works.

Post by mrtinb »

Thank you for a great explanation.

Maybe you can also describe how to change the character each line. As I understand it would be much like pseudo-hires, but does not need a custom display routine.
Martin
https://zx.rtin.be
ZX81, Lambda 8300, Commodore 64, Mac G4 Cube
dr beep
Posts: 2341
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: "Quaracter"-display, how it actually works.

Post by dr beep »

mrtinb wrote: Tue Jun 18, 2024 2:59 pm Thank you for a great explanation.

Maybe you can also describe how to change the character each line. As I understand it would be much like pseudo-hires, but does not need a custom display routine.
it is the same display as here but you change each line so you are bound by same characters. Each line needs use of shadowregisters ad exact linecounting.
dr beep
Posts: 2341
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: "Quaracter"-display, how it actually works.

Post by dr beep »

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
dr beep
Posts: 2341
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: "Quaracter"-display, how it actually works.

Post by dr beep »

And with this trick you can add a few extra lines to your lowres screen
Don't forget to add the lines in your dfile.

Code: Select all

; the display file, Code the lines needed.
dfile

	jp	lowset		; back to LOWMEM to set registers
lowset	inc	b
	inc	b	; add 2 lines to your screen
	jp	hidisp+#8000	; and back to highdisplay
hidisp	halt
Spinnetti
Posts: 270
Joined: Sat Sep 12, 2020 11:29 pm

Re: "Quaracter"-display, how it actually works.

Post by Spinnetti »

Very cool. Well explained, but I think I understood 1/2 of what I read on the first pass :)
Zeddy: ZX80, ZX81/ZXpand, TS1000/ZXpand, TS1500/Zxpand+,Printer
Speccy: 48k, +, +2, +3, TS2068, "Bare Metal" Pi, Next KS2, IF1/Microdrives/Vdrive/Light Gun/VGA-Joy
QL: Minerva/QL-VGA/Custom PSU
C5: 24v, LiFE battery, Disc brakes
User avatar
siggi
Posts: 1029
Joined: Thu May 08, 2008 9:30 am
Location: Wetterau, Germany
Contact:

Re: "Quaracter"-display, how it actually works.

Post by siggi »

dr beep wrote: Sun Jun 23, 2024 4:45 pm
NOTE: this will NOT work with 32K RAM
That code will also not run on 48K and 64(56)K Zeddies, because in upper DFILE they support only single-byte opcodes (not eg. JP xxxx).
Maybe you will find a solution, also working for those Zeddies?

Siggi
My ZX81 web-server: online since 2007, running since dec. 2020 using ZeddyNet hardware
http://zx81.ddns.net/ZxTeaM
dr beep
Posts: 2341
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: "Quaracter"-display, how it actually works.

Post by dr beep »

siggi wrote: Thu Jun 27, 2024 10:59 am
dr beep wrote: Sun Jun 23, 2024 4:45 pm
NOTE: this will NOT work with 32K RAM
That code will also not run on 48K and 64(56)K Zeddies, because in upper DFILE they support only single-byte opcodes (not eg. JP xxxx).
Maybe you will find a solution, also working for those Zeddies?

Siggi
The solution is the same as my 1K hires games.
Make a full copy of your program 32K higher.

On the 1K games this is always done. When no extra RAM the game copies over itself.
dr beep
Posts: 2341
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: "Quaracter"-display, how it actually works.

Post by dr beep »

siggi wrote: Thu Jun 27, 2024 10:59 am
dr beep wrote: Sun Jun 23, 2024 4:45 pm
NOTE: this will NOT work with 32K RAM
That code will also not run on 48K and 64(56)K Zeddies, because in upper DFILE they support only single-byte opcodes (not eg. JP xxxx).
Maybe you will find a solution, also working for those Zeddies?

Siggi
Solution is
1) a full copy of the game 32K higher, like my 1K hires games standard does

2) Use HL' and do EXX JP (HL) and an extra EXX to return to right registers.
escher
Posts: 19
Joined: Thu May 12, 2011 7:31 pm

Re: "Quaracter"-display, how it actually works.

Post by escher »

The very last routine in Wilf Rigter's nice article you linked to in the first post is actually my own created for Z-Xtricator back in 1983/84 when I was doing 'O'-Levels.

I have previously posted on here the history of that game and the problems it caused the Software Farm when Sinclair released an unadvertised revision to the ZX81 Rom which changed one crucial address location that the code in the game used (not in the display routine though) - I may have done this in a private message to a long-standing member but he/she is can post the message here if they want, I would do so myself if I had a copy of the text from a few years back (around covid times I think??)

Anyway, the IMPORTANT thing about that "pseudo-hires" routine (which is actually more "pseudo-UDG" (User Defined Graphics)) was that it only used the same memory as the original ZX81 display file (Wilf doesn't mention that)

I was puzzled when the Software Farm told me my routine used far less RAM (I understood only years later after researching the history of hi-res on the ZX81) , and quite irked when they insisted I made a loading screen like their previous games which took over 6K and several minutes to load, far less than the actual game!
Post Reply