Double buffering on the Spectrum

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
Manic Miner
Posts: 350
Joined: Tue Apr 03, 2018 6:19 pm
Location: Argentina

Re: Double buffering on the Spectrum

Post by druellan » Wed Apr 18, 2018 11:35 am

Ast A. Moore wrote:
Tue Apr 17, 2018 5:59 pm
Curiously enough, in his blog post
Seems he was using a bright 1 black attribute as delimiter. That's clever:

I didn't fully appreciate that Sidewize / Crosswize run at 50fps.
Me either, but when I've learned about EmuZWin's real FPS indicator, I started to test games, and I loaded Sidewize because I can, and I got instantly blown again about how well it performs.


I now notice the flickering, EmuZWin seems not to be doing a great job emulating this.
0 x
Un buen día me puse a probar juegos de ZX Spectrum a ciegas en Youtube, terminó siendo:
📺 Retroarqueología en Youtube

Posts: 1
Joined: Thu Jun 13, 2019 10:52 pm

Re: Double buffering on the Spectrum

Post by robpearmain » Thu Jun 13, 2019 11:07 pm

Joefish wrote:
Tue Apr 17, 2018 4:15 pm

This one is more complicated - there is no background buffer; the scenery is redrawn from scratch each frame. There are a very limited number of scenic blocks, but it's actually quicker than a scroll+copy. Note also that the scenery now scrolls in 2-pixel steps.
The pre-shifted scenery blocks are loaded into the registers AF, BC, DE and HL then the scenery is drawn by a series of PUSHes, PUSHing the relevant pattern onto the screen at that point. It's wasteful as a scrolling pattern may be half-in and half-out of a character position. So the patterns for solid platforms might be:

AF = empty space
BC = start of platform
DE = continuous platform
HL = end of platform

But before this happens, the program must first re-write the list of PUSH instructions to match the level data. The PUSH list for each row of scenery blocks is re-used to draw all 16 pixel rows. It only has to POP four registers to fetch the scenery patterns for an entire pixel row, so it's quicker that using POP+PUSH to copy a row of data (just as many PUSHes, but fewer POPs).

The scroll can also draw things one-character over, so it only needs scenery pre-shifted to 4 positions (to cover each pattern moving across 8 pixels, not 16). The blacked-off borders either side of the screen are uneven; there's an extra character on one side to hide the scenery redraw moving about, as well as any sprite overlap.

It can have a different set of patterns on each row of the screen, and because of the character-position adjustment it can have either:
- one pattern that can be repeated to any length (e.g. platforms which need 3 pre-shifted patterns to start, repeat and end)
- or 3 separate patterns of a narrow upright object (e.g. pipes up to 10 pixels wide, which always just fit within one 16 pixel wide pre-shifted block)
- or one platform that must start and end within 24 pixels and one narrow upright object.

Finally, there's a faster parallax bit at the bottom of the screen drawn by just PUSHing a 16-bit wide pattern right across the screen. This is programmed to occur twice per game cycle. The result is that this part scrolls at 50fps, making everything seem a bit smoother.
This is great information, what about when a row changed graphics, how did this work (see image attached)

1 x

Posts: 4
Joined: Tue May 28, 2019 11:02 am

Re: Double buffering on the Spectrum

Post by catmeows » Fri Jun 14, 2019 12:21 am

robpearmain wrote:
Thu Jun 13, 2019 11:07 pm

This is great information, what about when a row changed graphics, how did this work (see image attached)

By loading values in the middle of line.

Code: Select all

	push bc			 ; 89d2 c5 $0bts
	push af			 ; 89d3 f5 $0bts
	push de			 ; 89d4 d5 $0bts
	push bc			 ; 89d5 c5 $0bts
	push hl			 ; 89d6 e5 $0bts
	push hl			 ; 89d7 e5 $0bts
	push hl			 ; 89d8 e5 $0bts
	ld ($8bf0), sp		 ; 89d9 ed 73 f0 8b $14ts
	ld sp, ix		 ; 89dd dd f9 $0ats
	pop bc			 ; 89df c1 $0ats
	pop de			 ; 89e0 d1 $0ats
	pop af			 ; 89e1 f1 $0ats
	ld sp, ($8bf0)		 ; 89e2 ed 7b f0 8b $14ts
	push af			 ; 89e6 f5 $0bts
	push de			 ; 89e7 d5 $0bts
	push de			 ; 89e8 d5 $0bts
	push de			 ; 89e9 d5 $0bts
	push de			 ; 89ea d5 $0bts
	push de			 ; 89eb d5 $0bts
	push de			 ; 89ec d5 $0bts
	jp $9ced		 ; 89ed c3 ed 9c $0at
0 x

Manic Miner
Posts: 463
Joined: Tue Nov 14, 2017 10:26 am

Re: Double buffering on the Spectrum

Post by Joefish » Fri Jun 14, 2019 10:27 am

Could it really do that?
OK, my 50Hz scrolling demo couldn't, but then there was no 'slack time' in it. I tried to keep mine running at a constant speed, whereas with all its sprites, Cobra varies a lot in execution time. Mine used the alternate registers for an alternate set of platforms, but could only swap them between rows, not columns. I just assumed Cobra did the same.
I did develop some code that used the alternate BC/DE/HL registers (or just as easily AF'/IX/IY) for an extra platform type within a row, but it takes longer to execute.
0 x

User avatar
Posts: 115
Joined: Sun Jun 17, 2018 1:54 pm

Re: Double buffering on the Spectrum

Post by g0blinish » Fri Jun 14, 2019 3:00 pm

maybe not related to topic, but I used another tricks for AY Mehademo 3
(sources inside,compile with sjasm)
0 x

Post Reply