Tearing while scrolling attributes

The place for codemasters or beginners to talk about programming any language for the Spectrum.
Post Reply
dfzx
Manic Miner
Posts: 682
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Tearing while scrolling attributes

Post by dfzx »

I've been messing about with a bit of code which scrolls a block of attributes across the screen. Or put another way, sets the attribute display memory to a pattern, rotates the pattern by one character column, then repeats. You get a block of data rolling horizontally across the display.

Thing is, as I watch this, there's a tearing sort of effect, even when it's locked to the raster with a HALT at the bottom of the loop. I slowed Fuse right down and caught a screen shot during the period while the pattern was stationary.

Image

You can see the torn attribute cells in the centre of the block.

I don't have real hardware, but I tend to trust Fuse. I tried another emulator (Speccy5.0) and that appears to do the same thing.

Which got me thinking: is this something real machines do? I always assumed the pixel data, followed by the attribute data, was sent to the display at the refresh, which is why it's flicker free when timed correctly. Now it occurs to me: is the attribute data treated differently?

If not, what's the explanation for this? Are the emulators wrong?
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
AndyC
Dynamite Dan
Posts: 1406
Joined: Mon Nov 13, 2017 5:12 am

Re: Tearing while scrolling attributes

Post by AndyC »

Nothing is "sent to the display at refresh". The ULA is reading the relevant bits of RAM interspersed with the CPU. This is why you get contention (the ULA has priority or the display would get messed up) and it's also how the various multi colour tricks work, by changing the contents of the attribute memory whilst the ULA is in the process of drawing the screen.
User avatar
Joefish
Rick Dangerous
Posts: 2058
Joined: Tue Nov 14, 2017 10:26 am

Re: Tearing while scrolling attributes

Post by Joefish »

A real Spectrum reads the pixel data from the screen memory line-by-line as it's drawing that line on the TV screen.
It also reads the attribute data in step with the pixel data, to colour those pixels.
That means it actually reads the same attribute data 8 times over; each time it draws a new pixel line, it fetches the attributes again.

So if the attributes have changed in the meantime, you get different colours mid-character-row where they shouldn't be possible.
If you get your timing right, you can exploit this, and this is how 'multicolour' graphics get all their extra colourful graphics.

And all the best emulators emulate this effect when drawing their displays.
dfzx
Manic Miner
Posts: 682
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Tearing while scrolling attributes

Post by dfzx »

Umm, OK, and thanks both, but I still don't understand why I'm seeing tearing of the character blocks.

The loop halts the processor, then at the interrupt it runs an empty ISR (which comes back in just a handful of cycles) then copies a couple of hundred bytes into the attribute memory area. Unless I've seriously messed up (always possible!) that will be done well inside the top border and before the raster starts updating the pixel/attribute part of the screen. Hence the attribute display memory should be stable as the raster generates the image and I wouldn't expect to see the tearing in the attributes.

And yet, there they are! But why?
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Tearing while scrolling attributes

Post by Ast A. Moore »

dfzx wrote: Tue May 19, 2020 5:53 pm that will be done well inside the top border and before the raster starts updating the pixel/attribute part of the screen
Simply issue a couple of OUT (254),A instructions before and after your loop to color the border. That’s a sure way to see where your code executes in relation to the screen refresh.
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.
AndyC
Dynamite Dan
Posts: 1406
Joined: Mon Nov 13, 2017 5:12 am

Re: Tearing while scrolling attributes

Post by AndyC »

Yup, fiddling the border colours is a classic 8-bit technique for figuring out when your code is running (and getting a ballpark feel for its speed)
dfzx
Manic Miner
Posts: 682
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Tearing while scrolling attributes

Post by dfzx »

Yes, I'd seen the border flickering thing elsewhere in these forums. I'd never tried it, but now have I see the point.

Somewhat embarrassingly, it turns out my simple copying code is much slower than I thought, which probably explains what I'm seeing. :)
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
Ast A. Moore
Rick Dangerous
Posts: 2641
Joined: Mon Nov 13, 2017 3:16 pm

Re: Tearing while scrolling attributes

Post by Ast A. Moore »

I find this trick indispensable in timing-critical applications. By “wrapping” routines (or parts thereof) around in different colors you get a good idea of when your code merits optimizing (and which part of the code). It also gives you a great visual aid for when you optimize your routines. By taking a screen snapshot—or even recording your screen to a movie—you can compare the time the different versions of your routine take to execute. Then you can decide whether your optimizations are worth the effort. Beats counting T states, especially for complex code with lots of conditional branching.
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.
AndyC
Dynamite Dan
Posts: 1406
Joined: Mon Nov 13, 2017 5:12 am

Re: Tearing while scrolling attributes

Post by AndyC »

It's amazing how often you can forget just how slow our beloved 8-bit machines really are. Code which doesn't really seem to do a lot that you assume will be super quick can often end up being noticeably slow.
User avatar
RMartins
Manic Miner
Posts: 776
Joined: Thu Nov 16, 2017 3:26 pm

Re: Tearing while scrolling attributes

Post by RMartins »

I would say, that your code is slow enough to process those lines, that the raster line catches up with the character you are changing the color at.

Two easy fixes:
1 - Move your graphics to the bottom of the screen, and you will have more time, before the raster line catches up with you.
2 - Wait a bit after the halt, to let the raster pass you by, before you start drawing, then it will be flicker free.

The harder, fix is to optimize your code.
User avatar
Lethargeek
Manic Miner
Posts: 743
Joined: Wed Dec 11, 2019 6:47 am

Re: Tearing while scrolling attributes

Post by Lethargeek »

I can't even imagine how a code for such a simple task could be so slow. Even a straightforward single ldir of 256 bytes + a few separate byte transfers to correct the right column will eat less than half of the top border time. And calling a simple subroutine (consisting of "get left; ldi x31; put right") 24 times should scroll the entire attribute area without any tearing (and likely still finishing ahead of the top border).
dfzx
Manic Miner
Posts: 682
Joined: Mon Nov 13, 2017 6:55 pm
Location: New Forest, UK
Contact:

Re: Tearing while scrolling attributes

Post by dfzx »

Lethargeek wrote: Wed May 20, 2020 2:32 am I can't even imagine how a code for such a simple task could be so slow.
4-way scrolling based on inputs and events means rebuilding the 32x24 display each frame. At least at the moment.

It looks like some sort of "scroll the attributes in one of the 4 directions, then fill in the appearing row/column" approach is going to be required.
Derek Fountain, author of the ZX Spectrum C Programmer's Getting Started Guide and various open source games, hardware and other projects, including an IF1 and ZX Microdrive emulator.
User avatar
Turtle_Quality
Manic Miner
Posts: 506
Joined: Fri Dec 07, 2018 10:19 pm

Re: Tearing while scrolling attributes

Post by Turtle_Quality »

If it's just the attributes moving, regardless of the direction, most of the work can be completed by one LDIR that should not take long.

Scrolling the graphics around is more complex and time consuming because of the screen layout and the 8 fold increase in data per character square.
Can you show the code ?
Definition of loop : see loop
User avatar
Lethargeek
Manic Miner
Posts: 743
Joined: Wed Dec 11, 2019 6:47 am

Re: Tearing while scrolling attributes

Post by Lethargeek »

dfzx wrote: Wed May 20, 2020 8:58 am 4-way scrolling based on inputs and events means rebuilding the 32x24 display each frame. At least at the moment.
still a very simple task if it's just attributes
dfzx wrote: Wed May 20, 2020 8:58 am It looks like some sort of "scroll the attributes in one of the 4 directions, then fill in the appearing row/column" approach is going to be required.
for horizontal scrolling it will be easier to wrap each row separately, like

Code: Select all

ld a,(de)
ldi	x31
ld (de),a
inc de
inc hl
(this scrolls a row left and goes to the next one)
Post Reply