Double buffering on the Spectrum

The place for codemasters or beginners to talk about programming any language for the Spectrum.
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Double buffering on the Spectrum

Post by MonkZy »

I have been making efforts to try and understand the Spectrums screen memory and also the best ways to produce frames of display data. I am currently coding some standard demoscene routines my latest is a sinus-scroller.

My question is this : On fast paced games/demos do programmers avoid using a screen buffer and aim to update the display ahead of the scanline?

I have many other questions on this subject, I just wish to get a view on the pro's and con's of using a screen buffer as opposed to directly setting the screen from your code.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Double buffering on the Spectrum

Post by RMartins »

You can only double buffer ( I.e. use shadow screen) on 128k machines.
However having a double buffer means that you need to fill the entire buffer every frame before swapping, or you have to revert the buffer to "clean" state before starting the next frame draw. Take note that "clean" can have several meanings here.

Since the zx is severely under powered at 3.5mhz, copying or writing stuff to screen memory will take more time than available to blit a full screen.

So there are basicaly 3 options:
1 - animate just a smaller part of the screen
2 - use tricks with attributes, less memory to work on.
3 - just edit the areas that need animation.

Or you can use a mix of all these.

For 50Hz animation usualy racing the raster and outputting directly to screen memory is the only way to go.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

There’s no simple answer to your question. I’ve always been the staunch proponent of the idea that on simple and underpowered machines such as the Spectrum, one should avoid a “standard” or “library” approach as much as possible. Custom routines are the way to go.

That said, you must determine what you personally consider to be a high frame rate. For some, 12.5 fps is high enough; others strive for the magic 50 fps number. From personal experience, I can assure you that double-buffering at 50 fps is possible—to a degree. (I’m currently working on an update to Yankee that uses double-buffering for a small portion of the screen and still keeps the game running at 50 fps.) Naturally, you’re going to be severely limited in what you can do at this frame rate.

While not strictly necessary in every case, I nevertheless strongly recommend you look into using the floating bus trick instead of the usual sync-to-interrupt method, as well.

The gist of the idea behind double-buffering is simple—sometimes you need to arranged objects in a particular manner, and it’s easier to do it offscreen. When you’re done with object arrangement, you simply copy the buffer (or parts thereof) onto the actual screen.

Quite a few games don’t keep a steady pace, by the way, and the frame rate varies depending on how many parts of the virtual/actual screen need to be updated.

For simpler, XORed graphics (or even for masked sprites that move on a static background), you can draw directly to screen making sure the electron beam is out of the way.

One skill you definitely develop when working with direct-to-screen drawing is optimizing your routines for speed. I really enjoy it. This may not be your cup of tea, though.

Hope this helps. Sorry I couldn’t be more specific (see the first paragraph).
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Double buffering on the Spectrum

Post by Nomad »

That's a big part of the reason I was so blown away by Karl's program.

viewtopic.php?f=3&t=457&hilit=source
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Double buffering on the Spectrum

Post by MonkZy »

I was coding for the 48k Spectrum. I think I used the wrong term, double buffering, what I meant was using part of RAM to store display data and only make changes in that space , copying it to the screen after a HALT. I did read that the 128k machine makes buffering much easier but had read no further, sticking to 48k machine for now. I will read some more about screen buffer concepts.

My thinking was the buffer could use a simpler byte arrangement than the display. I wrote a routine to calculate an address and a bit position based on an X and Y coordinate and was comparing this to similar routines for the display memory. I am realising the savings are lost due to the need to copy the memory to the screen memory. Using my buffer I began aiming to achieve 25fps but with ultra smooth display. The other benefit of the buffer is it would allow me to have a complex text scroller at the top of the screen. My routines only work smoothly if I place them at the very bottom of the screen.

I will go back to avoiding a buffer for now. When I have a smooth sinusoidal text scroller (at the bottom of the screen :D ) I will post it. I have for now just some broken code that was an attempt to modify to use a buffer :oops:
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

MonkZy wrote: Sun Apr 15, 2018 3:04 pm I was coding for the 48k Spectrum. I think I used the wrong term, double buffering, what I meant was using part of RAM to store display data and only make changes in that space , copying it to the screen after a HALT.
Yes, that’s how I understood it, and that’s what’s generally implied as applied to the Spectrum.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
MonkZy
Manic Miner
Posts: 278
Joined: Thu Feb 08, 2018 1:01 pm

Re: Double buffering on the Spectrum

Post by MonkZy »

[mention]Ast A. Moore[/mention] Is the floating bus option available on the 48k machines? I have been using HALT to sync to the screen refresh, is this the best way on 48k machines?
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

MonkZy wrote: Sun Apr 15, 2018 3:28 pm @Ast A. Moore Is the floating bus option available on the 48k machines?
It’s available on all original Spectrums: 16K/48K, 128K, +2, and +2A/+3 (in 128K mode). Follow the link in my signature for the history of its recent discovery on the +2A/+3.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Double buffering on the Spectrum

Post by Nomad »

Why was it not understood so well until your research? I just assumed that the system was understood completely.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

Nomad wrote: Sun Apr 15, 2018 3:47 pm Why was it not understood so well until your research? I just assumed that the system was understood completely.
I think it was a combination of a few factors. Since Joffa Smith is no longer with us, we won’t know for sure, but I think it’s a safe bet to assume that his discovery was a fluke. His Cobra and Terra Cresta are the earliest examples of that trick I could find; both came out at the end of 1986. By that time, the Spectrum IP had already been acquired by Amstrad, and the +2A was released very soon afterward. The exact same technique didn’t work on these machines, and since there were plenty of other architectural changes, everybody just assumed that the floating bus was gone, so nobody bothered to research it further. Besides, the market was shifting rapidly toward 16-bit machines.

Fast forward to 2016, when Cesar—also by accident—discovered that “something was going on on the +2A/+3.” He is not a Spectrum developer, rather an emulator author. He posted his findings—a single test in BASIC—which provided little to no useful information to actual developers, and no one paid any attention to it.

Skip ahead agin to September 2017, when I stumbled upon his post. Mind you, I myself had avoided using the floating bus precisely for the same reason developers avoided it in the past—I’d thought it didn’t exist on the +2A/+3. However, Cesar’s post piqued my interest.

The rest is history. I pushed on with the investigation, first by cobbling together a series of simple visual tests that the non-programmer owners of these machines could run for me. Then Hikaru joined in with his own test (which was far more scientific than mine), and I, in turn, kept refining my test to be more purposeful. I was grateful to the volunteers for their willingness to spend time to help me out, but the final fine-tuning required my having direct access to an actual +2A, because I needed to run potentially a few dozen tests to find the perfect length for the padding instruction. Unfeasible, considering the lag between my posting a new version of the test and one of the volunteers finding time to run it and post the results. So I went ahead and bought a +2A and finished my test on it. This enabled me to incorporate this newly discovered feature into Yankee—which was my original goal all along—in a very short time.

In the process, we also helped Mark Woodmass to perfect SpecEmu, which became the first emulator to correctly support this feature. I even designed a specially modified version of my test for precisely that purpose.

So, to answer your question more succinctly—it was the combination of the poor timing of the original discovery (it happened too late) and subsequent lack of determination on the part of game developers. Had Joffa stumbled upon it a couple of years earlier, the trick would have been used widely enough by the time Amstrad acquired the Spectrum line that the quirk would have been preserved in the design of the +2A, or, if it hadn’t, people would have been more determined to find it.

In a sense, I just happened to provide the needed determination, albeit thirty years too late.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Nomad
Manic Miner
Posts: 600
Joined: Thu Dec 28, 2017 12:38 pm

Re: Double buffering on the Spectrum

Post by Nomad »

It is amazing that even years later stuff like this is coming out. It makes you wonder how many other techniques are just waiting to be rediscovered/discovered.

I guess that is why its important for there to be a true fpga implementation of a spectrum for stuff like this in the future. Otherwise you will have emulators that will not implement stuff that was possible on the original hardware just that nobody thought was possible or even knew existed.
Wall_Axe
Manic Miner
Posts: 492
Joined: Mon Nov 13, 2017 11:13 pm

Re: Double buffering on the Spectrum

Post by Wall_Axe »

does the floating bus trick basically allow you to know where the raster beam is at any time?

so if the static part of the game (e.g. a logo) is on the bottom of the screen..you wait until the beam is on the top of the logo before updating the game above?
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

Nomad wrote: Sun Apr 15, 2018 5:01 pm I guess that is why its important for there to be a true fpga implementation of a spectrum for stuff like this in the future. Otherwise you will have emulators that will not implement stuff that was possible on the original hardware just that nobody thought was possible or even knew existed.
You hit the nail on the head. It’s a vicious circle: emulator authors primarily focus on adding “features,” leaving the actual emulation at the “good enough” stage. Modern-day Spectrum developers then code for those emulators, rather than the actual Spectrum. Rinse and repeat. This applies to hardware emulators, too, by the way. In essence, they’re little more than Spectrum clones, except that most of them don’t even use the Z80.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

Wall_Axe wrote: Sun Apr 15, 2018 6:00 pm does the floating bus trick basically allow you to know where the raster beam is at any time?

so if the static part of the game (e.g. a logo) is on the bottom of the screen..you wait until the beam is on the top of the logo before updating the game above?
Well, yes and no. The trick takes advantage of the fact that you can fetch the value that the ULA is currently reading from contended memory. If that value happens to be the bitmap or attribute byte of the display file, you can then proceed to treat this information as you see fit.

Catching a bitmap byte is typically of little use—you risk running into too many false positives. An attribute byte is a whole different ballgame. You can fill an area of the screen with a unique attribute byte and wait for that byte to appear on the data bus.

So, technically, you’re not so much following the beam as the data that is being fetched by the ULA. That’s the good part. The downside is that the only piece of information available to you is the value that the ULA reads. Unless the value itself is unique, you can’t know for sure where the beam is exactly.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
Wall_Axe
Manic Miner
Posts: 492
Joined: Mon Nov 13, 2017 11:13 pm

Re: Double buffering on the Spectrum

Post by Wall_Axe »

so you put a color(attribute) near the bottom of the screen so you know where the beam is?

so my logo could have a line of magenta and no magenta used in the game?
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

Wall_Axe wrote: Sun Apr 15, 2018 7:07 pm so you put a color(attribute) near the bottom of the screen so you know where the beam is?

so my logo could have a line of magenta and no magenta used in the game?
Yes, except it’s the full attribute byte, not just a particular color. You can have, say, a non-bright magenta paper and black ink as your sync zone, but are free to use bright magenta paper and black ink anywhere else on the screen. Or use bright black on black (which is all but invisible). Or set Bit 7 (flashing) and use the same colors for paper and ink.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
fenderjaguar
Drutt
Posts: 23
Joined: Wed Mar 07, 2018 11:48 am

Re: Double buffering on the Spectrum

Post by fenderjaguar »

Even when I was a kid, I remember playing batman the movie and thinking how no sync on 50hz with all that tearing (at 12.5 or 25 fps, not sure which) was like eye cancer. Especially on the batwing level, I nearly had a seizure :lol:
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Double buffering on the Spectrum

Post by djnzx48 »

I read that floating bus thread a while ago and I'm still not entirely sure on how it works. Could someone give a quick rundown from the programmer's perspective on how it differs from the standard floating bus and how you would use it in a game?
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

djnzx48 wrote: Mon Apr 16, 2018 9:57 am I read that floating bus thread a while ago and I'm still not entirely sure on how it works. Could someone give a quick rundown from the programmer's perspective on how it differs from the standard floating bus and how you would use it in a game?
I think I did just that a couple of posts back. Also, what do you mean by “the standard floating bus”?

To reiterate (what I have already reiterated, I believe):

1. You create a wait loop that reads from a particular port, expecting a particular value (say, a screen attribute byte).
2. When the value read from the port matches the expected value, you exit the loop.

The time you exit the loop will roughly correspond to (plus some delay, naturally) the time the ULA was reading that value from the display fly, which will in turn correspond to the electron beam passing that area of the “physical” screen.

EDIT: I think I know what you mean by “the standard floating bus”—the floating bus on the 48K/128K/+2 as opposed to the +2A/+3. If there’s enough interest in the subject, I’ll do a separate writeup, something along the lines of “The Definitive Guide to Using the Floating Bus” with an actual example and make a separate post about it.
Last edited by Ast A. Moore on Mon Apr 16, 2018 10:24 am, edited 1 time in total.
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
djnzx48
Manic Miner
Posts: 729
Joined: Wed Dec 06, 2017 2:13 am
Location: New Zealand

Re: Double buffering on the Spectrum

Post by djnzx48 »

Sorry, I was meaning to ask how the +2A/+3 floating bus differs from on the Sinclair machines.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2640
Joined: Mon Nov 13, 2017 3:16 pm

Re: Double buffering on the Spectrum

Post by Ast A. Moore »

djnzx48 wrote: Mon Apr 16, 2018 10:21 am Sorry, I was meaning to ask how the +2A/+3 floating bus differs from on the Sinclair machines.
Yup. Got it. See my edit above . . . uh . . . the previous page, as of now. ;)
Every man should plant a tree, build a house, and write a ZX Spectrum game.

Author of A Yankee in Iraq, a 50 fps shoot-’em-up—the first game to utilize the floating bus on the +2A/+3,
and zasm Z80 Assembler syntax highlighter.
User avatar
Ersh
Manic Miner
Posts: 480
Joined: Mon Nov 13, 2017 1:06 pm

Re: Double buffering on the Spectrum

Post by Ersh »

Ast A. Moore wrote: Mon Apr 16, 2018 10:15 am... If there’s enough interest in the subject, I’ll do a separate writeup, something along the lines of “The Definitive Guide to Using the Floating Bus” with an actual example and make a separate post about it.
Please do. :)
User avatar
utz
Microbot
Posts: 113
Joined: Wed Nov 15, 2017 9:04 am
Contact:

Re: Double buffering on the Spectrum

Post by utz »

Ersh wrote: Mon Apr 16, 2018 10:50 am
Ast A. Moore wrote: Mon Apr 16, 2018 10:15 am... If there’s enough interest in the subject, I’ll do a separate writeup, something along the lines of “The Definitive Guide to Using the Floating Bus” with an actual example and make a separate post about it.
Please do. :)
Here's some more interest ;)
Wall_Axe
Manic Miner
Posts: 492
Joined: Mon Nov 13, 2017 11:13 pm

Re: Double buffering on the Spectrum

Post by Wall_Axe »

if you put the still stuff like score and logo in the top third of the screen
and simply used interrupt mode 2,
to use the time the raster takes to traverse the first third of the screen..
to draw the sprites on the bottom two thirds

how is that better/worse than...

putting the still stuff in the bottom third of the screen
waiting for floating bus to indicate raster is two thirds of the way down
drawing sprites in first two thirds of screen


it seems like you still get the same amount of time to draw stuff?

does the floating bus tell you when the raster is in the border? that would give more time to draw sprites
spectron
Drutt
Posts: 25
Joined: Thu Mar 29, 2018 3:27 pm

Re: Double buffering on the Spectrum

Post by spectron »

As already mentioned, there is no definitive answer.

Being pedantic I'd like to leave the double buffering term for the 128k ability to swap memory whereas I'd always call the term of writing off screen then copying to the visible screen as back buffering. But that's a moot point.

Most solid 3d stuff wrote to aback buffer (starstrike2 for example) and so did games like Elite. I used it to just draw the top 3d section for the conversion of Accolade's Gunboat and from memory used the stack to copy the data and also rearranged the off screen buffer to a more sensible layout with each line following the other in memory.

When doing the 100m and hurdles in Summer games, the code blitted the bottom sprites straight after the vblank then the top sprites later once the beam had gone down the screen. It did initially cause issues because the code was written in top memory but then the other coder combining all the events together assembled it into contended memory so everything started to flicker
Post Reply