I promised to post WIP projects & experiments whilst I'm tinkering away on demo ideas. I've very much had my fill of Teletext for a while (and POP feels a bit overwhelming at the moment) so instead I've been looking at stable raster timing (i.e. being able to execute code at an exact known point relative to the raster beam) as there are quite a few classic demo effects that are derived from such techniques.

Anyway, attached is a raster scrolltext prototype. The background colour is changed 10 times per scanline (LDA + STA = 8c x 10 = 80c) to give a chunky 10x8 blocks that can be "drawn" independently of everything else on the screen. This is all done with interrupts turned off, using vsync & timer 1 tests, lots of cycle counting and NOP slide where / when necessary. I got it working without really understanding why some of the timings were such and, on looking for more info on cycle stretching, I came across the great thread from hexwab on RS: http://www.retrosoftware.co.uk/forum/viewtopic.php?f=73&t=1007.

I ended up borrowing hexweb's approach to vsync but am not using the timer 1 callback, just sitting waiting for the timer 1 interrupt flag to trigger. I don't think I fully understand cycle stretching, I mean I do conceptually but how this actually manifests in observed behaviour is still a bit confusing. Some thoughts / observations for discussion if anyone can help me better explain:

Testing the system VIA can only really happen at a resolution of 4us which I presume is a cycle stretched test (BIT &FE4D) followed by a cycle stretched read (LDA &FE44)? Hard for me to explain what I mean here, obviously I get values that are not just multiples of 4 from the timer 1 low order counter, but if I set different delay values on the timer I have to increment by at least 4us for the code to complete at a different raster position (as measured by the CRTC registers in b-em.) 4us = 8 character columns in the CRTC so quite a long time in horizontal screen units.

It is impossible for us to know in code whether the CPU is on an odd or even cycle because the timer is only 1 MHz. We can stablise the code so everything takes the same amount of total cycles but if a timer tests complete on an odd vs even cycle then the whole thing will be shifted by one CRTC character column. You can see this in the sample - the top left square should be red and the bottom right one blue - sometimes they are not square but if you reboot and run the code again a couple of times eventually they will be. I also saw this on hexwab's sample in the RS thread - if you run it enough times the red & yellow columns will be shifted by one character.

Final note, on my real Master the timer interrupt arrives 2 cycles earlier than in b-em although jsbeeb is correct. Don't even think about running this on BeebEm. I've only tested this on a Master so do let me know if you have any compatibility issues or strange behaviour.

So here's an example of what you can do if you know exactly where the raster is vs your code. I believe this is the first time the "Kefrens Bars" effect aka "Vertical Raster Bars" has been seen on the BBC.

This effect essentially turns your Beeb into an Atari 2600 - the framebuffer is only a single pixel high (160 pixels / 80 bytes across) but repeated on every scanline of the screen, so 256 times. To do this I'm creating a new CRTC cycle every scanline, effectively there are 256 frame buffers but they all point to the same piece of memory! If you plot additional pixels (avoiding the horizontal raster) then the effect becomes additive down the screen as the raster moves from top to bottom.

This works on my real Master but I know that my Sony CRT is very tolerant of reconfigured PAL signals - please could someone test on another CRT, preferably a CUB? The timing for this one is not actually as sensitive as the stabilised palette changes above.

And here's another example that is resetting the screen address every scanline to achieve a classic Twister effect. Each line of the Twister is precalcuated and then we just select which line to "draw" every scanline. It's a lot faster to set a pointer to some memory than it is to actually plot the pixels on the screen. The downside is that it uses a lot of memory because the CRTC works in character rows and uses 8 bytes per character, even through we're only displaying the first byte.

I need to play around with the maths to make it prettier / more varied but I think you get the idea!

And a copy per combination of pixel offsets.Reminds me of my first really-x demo bitd, it used four pixels per row, but at least I had a convenient place to put the graphics, which were also in four byte chunks I think it was RichTW that said that Zaxson on the beeb did the same thing.

kieranhj wrote:And here's another example that is resetting the screen address every scanline to achieve a classic Twister effect. Each line of the Twister is precalcuated and then we just select which line to "draw" every scanline. It's a lot faster to set a pointer to some memory than it is to actually plot the pixels on the screen. The downside is that it uses a lot of memory because the CRTC works in character rows and uses 8 bytes per character, even through we're only displaying the first byte.

Very nice! I did a textured version in Demo 128 - using a Master helps a bit on the memory front. The wobbly test card and zooming checkerboard also use variations on this code.

SarahWalker wrote:Very nice! I did a textured version in Demo 128 - using a Master helps a bit on the memory front. The wobbly test card and zooming checkerboard also use variations on this code.

Thanks Sarah. I did take another look at Demo 128 again just yesterday to check out those effects and have a peek at the crtc registers in the b-em debugger, so guessed I wasn't the first to try this! Simonm had the thought to switch in shadow ram midway through the frame thus giving a potential 40kb of pre-rendered framebuffers (plus anything you can steal from lower down of course) - did you try this?

I'm working my way through some of the classic demo fx for our next production. Trying to get the Beeb at least up to the baseline vs C64 scene, although without the VIC chip we'll never compete at the same level. The b-em cycle accuracy & debugger has been invaluable whilst getting the timing right BTW so thanks again for that.

I had thought I was using both main & shadow RAM for the wavy test card, but a quick look at the source shows otherwise - it's using all 32kb of the shadow bank, to store a 128x128x4 (4kb) picture, but doesn't display the main bank. Obviously I thought at the time that non-integer scaling would just look too ugly, though why I didn't just set the display height to 192 lines or something is beyond me!

Here's another prototype. Thought I would try a go at the parallax vertical bars from one of my favourite Amiga demos Total Triple Trouble and mess about with using shadow ram at the same time. This one uses 64 full width pre-rendered character rows in MODE 1 which requires the 5Kb of actual graphics (still only using one scanline per row) to be spread across 40Kb of main + shadow video memory. This version is selecting the shadow / main ram bank on a per-scanline basis as well as the framebuffer address.

It's cool that this works as it means we can cobble together something like 48Kb for pre-rendered gfx effects - suddenly some of those crazy CPC fx don't seem quite so out of reach.

Loving those Kefrens bars - I'm going to have to post my surprisingly closely-related efforts soon (...but don't worry, this time it's on the Archi!)

tricky wrote:You could pack a few more lines in by using the "mode 7" type addressing, for 1k on the master or 2k on the B.

Thanks for the comments guys. I haven't tried doing the MODE 7 addressing / linear frame buffer thing yet. The only instance I know is the plasma in puppeh's Some Nasty Effects demo. Is this just a case of setting the teletext bit in the ULA (&02) whilst the CRTC is still configured for a regular screen mode?