Flickerfree screenupdates on the ZX81

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

Flickerfree screenupdates on the ZX81

Post by dr beep »

Spinnetti is coding a game and asked how to get a flickerfree display.

This made me think how to solve this.

On a ZX Spectrum you could do a HALT and then do the drawing before
a next intrupt would occur.

How can this be done on a ZX81?

At first I needed a small program that would give flickers when altering display.
For this test I simply erased a "A" and placed the "A" after some delay.
This was done with all "A"'s on the screen. The result: Flickering "A"'s
Test program is working.

Code: Select all

; Flicker free

	org 	#4009

eoscr	equ	vars


; in LOWRES more sysvar are used, but in this way the shortest code
; over sysvar to start machinecode. This saves 11 bytes of BASIC

; DO NOT CHANGE AFTER BASIC+3 (=DFILE)
basic   ld 	h,dfile/256			; highbyte of dfile
        jr 	init1

	db 	236				; BASIC over DFILE data
	db 	212,28				; GOTO USR 0
	db 	126,143,0,18			; short FP notation for #8009, no NEWLINE for BASIC

eline	dw 	last
chadd	dw 	last-1
        db 	0,0,0,0,0,0			; x
berg	db 	0				; x

mem	db 	0,0				; x OVERWRITTEN ON LOAD

init1	ld 	l, dfile mod 256		; low byte of dfile
	jr 	init2			
		
lastk	db 	255,255,255
margin  db 	55

nxtlin  dw 	basic				; BASIC-line over sysvar	

flagx   equ 	init2+2
init2	ld 	(basic+3),hl			; repair correct DFILE flagx will be set with 64, the correct value

	ld	h,eoscr/256
	db 	0,0				; x used by ZX81, not effective code after loading

	ld	l,eoscr mod 256
frames  db 	#37
	db	#e9				; set a end of screen marker
	jp 	init				; initroutine in screenmemory

	dw	0

cdflag  db 	64
; DO NOT CHANGE SYSVAR ABOVE UNLESS YOU KNOW WHAT YOU DO


init	ld	de,dfile+1

wrch	xor	a			; erase A
	ld	(de),a

	ld	b,20			; some delay
lp	djnz	lp
	
	ld	a,38
	ld	(de),a			; write A

sklf	inc	de			; do full screen
	ld	a,(de)
	cp	#76
	jr	z,sklf
	cp	#e9
	jr	nz,wrch
	
	jr	init

		
; the display file, Code the lines needed.
dfile 	db 	118

; each needed line has text and a Newline
	block 32,38
	db 	#76
	block 32,38
	db 	#76
	block 32,38
	db 	#76
	block 32,38
	db 	#76
	block 32,38
	db 	#76
	block 32,38
	db 	#76
	block 32,38
	db 	#76
	block 32,38
	db 	#76

		
; vars becomes EOSCR with JP (HL)
vars    db	128
last	equ $   	
end

Now I needed a way to test when a screenupdate will occur.
This is held in A'. I was suspecting that reading A' could cause
a screen updata not to occur, so I tested it.

Code: Select all

init	ld	de,dfile+1

wrch	ex	af,af'			; read screendelay
	ld	c,a			; save counter
	ex	af,af'			; back to main

	ld	a,253
	cp	c			; test enough time to update a character
	jr	c,sklf			; if not wait until intrupt is done

	xor	a
	ld	(de),a

	ld	b,20
lp	djnz	lp
	
	ld	a,38
	ld	(de),a
sklf	inc	de
	ld	a,(de)
	cp	#76
	jr	z,sklf
	cp	#e9
	jr	nz,wrch
	
	jr	init
Compiling this code gave me what I expected. The "A" are flickerfree but some
intrupts occur when I was reading A'. The full screen was no longer fixed but moved a bit.

I had to find a way to safely read A' without the change that an intrupt would occur.
This can be done by checking the last value that is pushed on the stack

Code: Select all

init	ld	de,dfile+1

wrch	ld	h,0			; stack 0 for A
	push	hl			
	pop	hl			; First free value on stack holds 0

ch2	dec	sp			; fake a register on the stack
	dec	sp
	pop	af			; get last register pushed on the stack
	or	a			; test if it is 0 from above
	jr 	z,ch2			; while 0, no intrupt has occurred

	ex	af,af'			; we are just behind an intrupt so it is
	ld	c,a			; now safe to read A'
	ex	af,af'

	ld	a,253
	cp	c
	jr	c,sklf

	xor	a
	ld	(de),a

	ld	b,20
lp	djnz	lp
	
	ld	a,38
	ld	(de),a
sklf	inc	de
	ld	a,(de)
	cp	#76
	jr	z,sklf
	cp	#e9
	jr	nz,wrch
	
	jr	init


This code will produce a flickerfree screen when updating characters.
You can use it for lowres and hires screens. When your updating of
a character is still flickering then you must decrease the 253 in a lower value.
This will give you more time for your update. Just remember that the more time
your routine needs the less changes can be done between screenupdates.

Only 18 bytes to make your game flickerfree.
It can be done in 16 with A and A' only

Code: Select all

wrch	xor	a			; stack 0 for A
	push	af			
	pop	af			; First free value on stack holds 0

ch2	dec	sp			; fake a register on the stack
	dec	sp
	pop	af			; get last register pushed on the stack
	or	a			; test if it is 0 from above
	jr 	z,ch2			; while 0, no intrupt has occurred

	ex	af,af'			; we are just behind an intrupt so it is
	cp	253
	jr	nc,sklf-1
	ex	af,af'

; erase and set
	
	db	62			; skip EX AF,AF' from above JR'
	ex	af,af'
sklf			
Last edited by dr beep on Sat Mar 25, 2023 6:35 pm, edited 2 times in total.
dr beep
Posts: 2060
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Flickerfree screenupdates on the ZX81

Post by dr beep »

All 3 versions compiled
FF-001.p
(341 Bytes) Downloaded 66 times
FF-002.p
(349 Bytes) Downloaded 84 times
FF-003.p
(359 Bytes) Downloaded 69 times
dr beep
Posts: 2060
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Flickerfree screenupdates on the ZX81

Post by dr beep »

First method has a small change in missing an intrupt when intrupt occurs between the DEC SP.

This version will always work

Code: Select all

wrch	ld	hl,#ffff			; -1
	add	hl,sp				; HL now SP-1

	xor	a
	ld	(hl),a				; signal clear stack

ch2	cp	(hl)
	jr 	z,ch2				; wait until intrupt is passed

	ex	af,af'				; save to read A'
	cp	253
	jr	nc,sklf-1
	ex	af,af'

; clear and display again

	db	62
	ex	af,af'

sklf	
Spinnetti
Posts: 253
Joined: Sat Sep 12, 2020 11:29 pm

Re: Flickerfree screenupdates on the ZX81

Post by Spinnetti »

Thanks for the great research. So, How do I apply this in context?
Last edited by Spinnetti on Sat Mar 25, 2023 8:52 pm, edited 1 time in total.
Zeddy: ZX80, ZX81/ZXpand, TS1000/ZXpand, TS1500/Zxpand+
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
dr beep
Posts: 2060
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Flickerfree screenupdates on the ZX81

Post by dr beep »

Spinnetti wrote: Sat Mar 25, 2023 8:47 pm Thanks for the great research!
Hope it can do what you need.
dr beep
Posts: 2060
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Flickerfree screenupdates on the ZX81

Post by dr beep »

Spinnetti wrote: Sat Mar 25, 2023 8:47 pm Thanks for the great research. So, How do I apply this in context?
See the final test.
You add the test before you erase and display a man. Itis mentioned where to do that.
If you need HL in your code just PUSH it and POP it after the test.

I added a PUSH and POP HL so no old registers are lost

Code: Select all

wrch	push hl
      ld	hl,#ffff			; -1
	add	hl,sp				; HL now SP-1

	xor	a
	ld	(hl),a				; signal clear stack

ch2	cp	(hl)
	jr 	z,ch2				; wait until intrupt is passed

	ex	af,af'				; safe to read A'
      ld h,a
	ex	af,af'

      ld a,h
      pop hl
      cp 253
      jr   nc,nodisp

; clear and display again

nodisp 
Spinnetti
Posts: 253
Joined: Sat Sep 12, 2020 11:29 pm

Re: Flickerfree screenupdates on the ZX81

Post by Spinnetti »

Thank you for the clarification. That helps.
Zeddy: ZX80, ZX81/ZXpand, TS1000/ZXpand, TS1500/Zxpand+
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
dr beep
Posts: 2060
Joined: Thu Jun 16, 2011 8:35 am
Location: Boxmeer

Re: Flickerfree screenupdates on the ZX81

Post by dr beep »

The code was still for the demo.

it should be this finally

Code: Select all

wait4int	push hl
      ld	hl,#ffff			; -1
	add	hl,sp				; HL now SP-1

	xor	a
	ld	(hl),a				; signal clear stack

ch2	cp	(hl)
	jr 	z,ch2				; wait until intrupt is passed, intrupt will change (HL)

	ex	af,af'				; safe to read A'
      ld h,a
	ex	af,af'

      ld a,h
      pop hl
      cp 253
      jr   nc,wait4int             ; wait for screenupdate first, not enough time to alter display 

; clear and display again
User avatar
SafePit
Posts: 43
Joined: Mon Feb 20, 2012 7:06 pm
Location: Boise, ID
Contact:

Re: Flickerfree screenupdates on the ZX81

Post by SafePit »

That's elegant. I'll give it a try in my animations. Do you still need a buffer for full displays?
Image
Image
Post Reply