Introduction:
As I mentioned before in the writeup for Spare parts: I'm a big fan of the Forever party and its consistent focus on the 8-bit platforms as well as their 1K compos. Therefore I take pride in making a release for that particular party, and Dash was no different.
All in all development took about 3 months of intense work. Folding in 2 seperate releases along with typography, music and progression intro a single (uncompressed) 1K production.
Design:
As mentioned this intro took elements from different projects and brought them together into a single, hopefulyy cohesive, production. One of major drivers in the design was the fact that I always admired the Z-rotators on C64 and Amiga and wanted to do something along those lines myself some day. At the time I though this would probably need to be a 4K oldschool production, but we will find out that you can get them going in smaller sizes as well.
The size for this intro was budgeted at about 50% for the main visuals, 25% for typography and progression and 25% for the music. So let's look into the different elements that made up this intro.
Visuals - The floor:
The floor effect + raster background was the first thing to get done and was originally developed as a stand-alone 128 byte project. It works by generating 4 frames of looping animation at startup, which will then get pageflipped to the screen, with the raster-colors overlaying on top of this to give it that depth-shading.
To save on size the romplot is used to draw the precalculated pixels onto the different parts of the memory in the background with the screen-colors turned off. The perspective floor effect itself is quite straightforward. In graphics 7 mode (160x96 with 4 colors), we will scan all pixels across the screen and do the following color calculation for each pixel:
z=(y-48) ; skip directly to plot for any value Z<=0
X=(x-80) / z
Y=(127 / z) + frame (0..3)
color=X&Y
The division is done with a very much taylored-to-the-cause 8-bit division routine, where I preload the zval divisor and setup the accumulator with either x or 127. This way we can keep the division routine short enough (10 bytes + rts).
ldy #0
divloop:
sbc zval
bcc divdone
iny
bne divloop
divdone:
tya
rts
Then when the update starts, we will not do a memory copy (to save bytes), but rather cycle through the different display lists for each frame on each new update. Then for each scanline we will perform a color calculation for the BKCOL and different platfield colors to get that nice sky and depth shading on the floor.
Visuals - The Z-Rotator:
This effect i've been trying to approach in a couple of different ways before i finally settled on the method used in this intro.
With the first approach i stored a starting point, linelength and slope-delta for each of the segments for a quarter of the rotation. While this method worked fine, it still needed quite a bit of code to get it up and running.
So the second approach was to just store the relative deltas directly for each of the scanlines directly for doing a quarter turn in 8 frames. However the total amount of data needed for this was already nearing 1k, so that wasn't viable either.
Z-Rotator cube drawn using PlayerMissile sprites
In the end I ended up storing the deltas in 4-bit format, covering 2 scanlines each to match the Graphics 7 resolution of 160x96 pixels, which was a nice compromise between size and code-simplicity. There is a small piece of init code that takes the encoded data and extracts it as raw format elsewhere in RAM. From here it will be read back during the update.
The actual z-rotated cube is drawn on the same horizontal interrupt as the color rasters using 3 quad-scaled playermissile sprites. Two sprites are used for covering the edges with a third sprite overlapping in the center. Missile-Sprite colors are also set for all the sprites to get the depth gradient.
Visuals - Typography:
The typography in the intro was done by using and switching to hires textmode and using the ATASCII font to create custom logos.
I've always liked the way Wacek/Arise did this for his C64 stuff, but these logos would still be too large for the 1K sizebudget if I also want to include all the other stuff. So U had to come up with a stylished form of lettering that would require the minimum amount of characters. After lots of design-attempts I came up with a stylised font that is only 2 rows high. So I could get the total amount of logodata down to 32 bytes per logo.
Since the logo parts were running in text mode, I could only add an effect using the player-missile sprites only. So I settled for a nicely mirrored effect that wasn't too straining on the size budget using the nice gold-colors (that later in the intro will cycle into a little more purple-ish for variation).
Music:
Since this was going to be a 1K intro, one of the things that needed to happen eventually is doing the music. I wasn't particulary looking forward creating the tech and tooling to make this happen and spent about a good week on creating both the music, tooling and replay code for it.
The original music was made using raster tracker, where I made a small 16-row tune with some bass, drums and appergios using just 2 channels. Sadly raster tracker doesn't export to custom formats easily if you don't want to use the huge overhead of replayer, so I had to write my own tooling for this.
The main idea was to keep the music replayer within a reasonable size (for example 64 bytes) and find a way to get the most value out of the limited available data. I started by taking a raw register dump for the music, which I then fed into a tool that I wrote to detect the looping point and export the individual channels into seperate bytestreams with an apropriate resolution (i.e. apergios would have a finer resolution than for example a bassline.
The replayer then takes these streams and reshuffles bits and pieces of them to get different music variations from the same datastream. Then overall channel masking is applied depending on the part of the intro.
Bringing everything together and Intro Progression:
It was a good idea to develop this intro in different steps, having sizegoals in between. For example the perspective floor had its own sizegoal, then the floor + zcube rotator was created with a sizegoal of 512 bytes (as budgeted). Then after that the typography and music wered developed seperately with their own respective sizegoals.
So when it came to putting everything together I knew that the sum of its parts would at least end up somewhere within reach of the 1K size limit. However getting everything together I had some trouble combining the hires textmode screens with the rest of the Introduction
Then when everything was working together I spent a lot of time tweaking with the buildup and progression. I wasn't sure if I could stretch the intro to two rounds of logos and only revealing the cube rotator on the second round, so at first I only had a single loop of logos and floor + cube rotator and ending on another logo. But when I showed the result to Baze he suggested that a 2 round structure could very well work, so I went back and tried to make that work.
Doing a two round buildup ment that I needed to keep the first round with 'just' the floor and sky interesting enough from both a visual and music perspective, so I needed to add something else to the visuals without adding an entire new effect. I settled on trying to slowly change the colors on the horizon to give the idea of a sunset (and later sundown). This wasn't originally budgeted so I had to find more optimisations first before I could add that. Since the intro was already quite optimised due to the different development steps, this was not an easy task, but in the end I managed to get it in and surely enough it worked really well with stretching the buildup and surprise the audience later on in the intro.
Conclusion:
The good news is that I am pleased with the final result. This intro to me at least represents what I think a 1K oldschool intro should and could be like: A nice mix between different effects, typography with some progression and music to boot.
The bad news is that creating an intro like this from start to finish was a lot of hard work. When I developed Spare Parts in 2023 with F#FREADY it took us about 1.5 months of intense development with 2 people, this intro took 3 whole months of intense development to make happen with 1 person, so I don't even want to think about the development time that a 4K oldschool intro would need to do proper.
Overall I'm happy for the experience of making a 1K intro by myself. Hopefully I'll get to do an oldschool 4K intro some day, or at the very least I can start dreaming about attempting one.
For more information, you can check out the all the releases from Forever 2024 party here