Page 1 of 1

Tearing while scrolling attributes

Posted: Tue May 19, 2020 5:12 pm
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?

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 5:15 pm
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.

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 5:32 pm
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.

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 5:53 pm
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?

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 6:25 pm
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.

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 8:23 pm
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)

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 8:51 pm
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. :)

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 9:21 pm
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.

Re: Tearing while scrolling attributes

Posted: Tue May 19, 2020 11:11 pm
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.

Re: Tearing while scrolling attributes

Posted: Wed May 20, 2020 1:38 am
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.

Re: Tearing while scrolling attributes

Posted: Wed May 20, 2020 2:32 am
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).

Re: Tearing while scrolling attributes

Posted: Wed May 20, 2020 8:58 am
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.

Re: Tearing while scrolling attributes

Posted: Wed May 20, 2020 11:16 am
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 ?

Re: Tearing while scrolling attributes

Posted: Wed May 20, 2020 11:39 am
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)