Sunday, 8 September 2024

Jelly Load with Artificial Sweetener

I should give a flashing images warning here. If you are affected by such things, give these post a miss.

We are still spending for more time on Jelly Load than any sensible person should, tweaking all the parameters to try to get it as fast and reliable as possible (those two things are normally in opposition with each other. Fast, cheap, reliable. Pick one)

I did look at adding a checksum to JellyLoad, but just couldn't get it to fit into the available space (the loader code has to run from the cassette buffer). It would have needed a bit more restructuring and rewriting, so I have given up on that for the moment.

There are some safety checks at the start, a sequence of patterns that for the header that have to match the expected sequence, then the load address needs to be valid.

That also checks you have the correct version of the loader. There needs to be three different builds for the three different VIC20 load addresses.

Memory
Load Address
Unexpanded VIC20
$1001
VIC20 + 3K
$0401
VIC20 + 8K or more
$1201

(Yay for standardization. Standards are great aren't they, there are just so many to choose from.....)

If/When I add this to the Penultimate Cartridge, I will need to tie it in to the RAM selection so you always have the right version for the RAM selected. (or I need to write a version of the loader which required 35K RAM to be selected and then fudges the VIC's memory detection so it switches to the appropriate mode)

Colour Bars

This is the test program we have been using recently. Credit to TFW8b for this one, it's quite a neat idea.

It is just a series of PRINTs, it is important that it is not just a loop.

If any of the program bytes are corrupted, skipped or repeated, it should immediately show on the screen.

One extra space caused by a rogue clock pulse will move everything else out of sync.

I don't know what's gone wrong here, but it's certainly not right.

Artificial Jelly Load

The current setup involves pointing a webcam at some LEDs. We have proved that can be done, and that it works.

I was wondering if I could bypass that step (and any potential problems that could introduce) and generate the video file programatically to give the best chance of success.

I did look at directly generating video from Python, and that seemed like it was getting complicated, so I decided to take an "easier" approach.

An "Easier" Approach

The plan was to create a folder of images, one for every combination of LEDs, and create an animated GIF or a video file from those.

I was thinking I needed to create images of all the possible patterns, and I could then create a folder of frames that were copies the appropriate images.

(side note, I am working on linux, so I will actually be creating symbolic links to the appropriate images, rather than copying them, but if it helps, just think of it as copying the files rather than creating shortcuts)

OK, so how many patterns are there? Well, it's 9 bits, so that is 2^9, or 512. Or put another way, each byte of the source file can be one of 2^8 or 256 values, and I need versions with the clock high and low, so 512 in total.

I could sit and colour in the appropriate bits of over 500 images, but I would rather not thank you very much.

So I need to generate these myself. Again, there are programmatic libraries for generating images, but I want the "easy" way.

I had worked out all I need to generate is a 3x3 pixel image. This can then be enlarged in the video player, and TFW8b was already applying a mask to the image to just leave between 0 and 9 clean white circles on a black background. (more recently this has become a transparent background)

I created a 3x3 test image and tried saving it in various file formats, to see how large the files were, and how easy it would be to generate a run of 512 of them automatically.

Most image files have headers that would need to be generated. The actual image data is usually compressed, either lossily like a JPG file, or lossless compression like a PNG file. Some file formats also contain palettes and even thumbnail previews of the larger image. All of this adds to the complication of generating these without getting bogged down into an image generation library.

I also looked into SVG vector images and the potential of creating a font, bit it seemed that standard raster images were the best option.

One file format that looked promising was .RAW files. Saving in that format produced a file that was only 9 bytes long, and it turned out that was one byte per pixel, either 00 or 01.

It also generated a six byte RAW.PAL file, presumably a palette file, with a 24 bit RGB value for the two index colours. 00 00 00 and FF FF FF, black and white respectively.

Great, that will do nicely.

I set about writing a simple bit of C code that generated all 512 of these 9 byte files.

512 files, check. Now I can use FFMPEG to render a video based on this folder full of images.

Well, no, it seems it does not support RAW files.

Damn. (should probably have checked that first)

Plan B.

I know it can work with PNG files, so I can use the imagemagick Convert program to convert all the RAW files to PNG.

Except that doesn't support RAW files either.

Damn. (should probably have checked that first)

Plan C.

I don't want to get into generating PNG files directly, so I just need to find a format that I can generate easily, and that can be easily converted to PNG.

OK, what file formats does Convert support?

I looked through various options doing the reverse process. Taking a 3x3 pixel PNG file and converting it to various supported formats that looked promising and seeing what size files they produced. All the ones I tried were too large / complex.

Then I found .MONO format and that looked interesting.

Not exactly sure what a "Raw bi-level bitmap" is, but it sounds like just what I need.

I converted the .PNG to .MONO and the resulting file was 3 bytes long. (.GRAY also looked interesting at 9 bytes, and would have worked, but I went with .MONO in the end)

I assumed that was a mistake, but when I loaded the .MONO file in GIMP, it was the correct pattern I had started with.

3 bytes? How?

Looking at the file in a hex editor it appears it is a line based bitmap.

05 02 05

The first (and last) line is 000 0101 in binary, and the last three digits match the pattern. The second is 0000 0010, again the last three match.

I wasn't sure of the bit ordering, so I created a test file to see if I had understood correctly.

07 00 01

Yes, I understood correctly, and it's starting with the leftmost pixel. So the line has a 1 if the leftmost pixel is black, 2 if the middle one, and 4 for the rightmost.

I modified my C program to generate 512 of these 3 byte .MONO files.

Perfect.

FFMPEG didn't accept them, but that's fine, I wasn't expecting it to.

I wrote a little bash script to convert all the .MONO files into .PNG files.

OK, look good so far. I think I will call these Jelly Moulds.

Now, I can feed those to FFMPEG and I generated a video.

That looks promising, so I set about writing a program to read in a PRG file and generate the appropriate series of frames.

The test program produced 3031 frames from a 1.5K PRG file (two frames per byte to allow the data to settle before toggling the clock).

I generated various MP4 files from that series of images, there are two parameters to set, both frame rates. The one that is normally used, the "r" parameter is the frame rate of the output video. 60 frames per second seems the optimal, and we have been able to feed these into and out of YouTube successfully.

The other is the "framerate" parameter, and this is the number of source images are used per second. So a frame rate of 1 would show one of these block patterns every second. A frame rate of 60 would show one pattern per video frame. This is the highest speed we could hope to achieve if the light sensors (and VIC20) were fast enough.In this case, 8 seems to work well, that works out 125mS per pattern, two per byte, so 4 bytes per second.

Mono files => PNG files => Symbolic links based on PRG file => MP4 files => OBS => YouTube => Light Sensors => VIC20 => PRG file loaded

I should really draw a flowchart.

Programatically generated Jelly Load. It's hypnotic. (N.B. I can neither confirm nor deny the presence of subliminal messages that may cause you to buy my stuff)

Look into the squares, look directly into the squares, the squares, the squares, not around the squares, don't look around the squares, look into the squares, you've loaded.....

Those videos are now off to TFW8b to experiment with. I think the squares version rather than the dots is favourite so far.

STOP PRESS

The latest tests include "Micro Jelly Load", a smaller and less obtrusive version. Hopefully will not be as distracting and disappear into the background like the flickering squares that used to indicate the adverts were about to start on ITV, or the white dots that indicate the end of a reel on old movies.

Side Quest

When I first tried to generate the MP4 file from the PNG images, it failed. 3 pixels wide was not appropriate as yuv420p video format requires an even line length.

I initially added a scale by 2 operation to the mono files in the convert operation. That produced 6x6 files, which worked, and generated videos, but on playback, the images were blurred as the video player performed some smoothing of the scaled images.

I think that would probably still look fine behind the mask, I thought it was best to scale the images to the size of the box in the final YouTube videos. I changed that to scale by 128, so 128x128 per square, 384x384 overall. That produces the cleaner square videos seen in the rest of the post.

Just watching those videos makes me think I have seen that before.

Ah, there we go. It seems someone else was experimenting with Jelly Load in the 80s.

They even tried the transparent version.


Advertisements

To load these programs, you will probably need a Penultimate +2 Cartridge

There is also my store with the full range of Minstrel and Mini PET accessories. Mini PET kits are all sold out now, but I do still have some Minstrel 3 kits left, which will last until I run out of Z80s.

I can ship worldwide, use the link at the top of the page to contact me with your location and what you want. Sorry I have to keep saying that. I am working on an alternative.

All the links can be found here:

Patreon

You can support me via Patreon, and get access to advance previews of posts like this and behind the scenes updates. These are often in more detail than I can fit in here, and some of these posts contain bits from several Patreon posts. This also includes access to my Patreon only Discord server for even more regular updates. If you want to see more posts like this, it would be great if you could give me a bit of support on Patreon, or via the PayPal link at the top of each blog post.