Holding Ground: The development of Ground Zero

Introduction:

Right after Outline 2026 (and the associated work on our Kablam! demo that we released under the Trepaan label there), I was excited to finally be able to focus on some smaller sizecoding projects again, so taking a quick peek at the demoparty schedule it turned out I didn't need to wait for long with the 68K Inside party happening the very next weekend \o/.

Design:

Since 68K Inside allows all kinds of platforms, as long as they are using a 68000 series CPU, I weighted the pro's and cons of each platform. What feature set will best my ideas, Will I take the 32-byte header penalty on ST and Amiga? Is this even a viable platform for sizecoding? etc.

I originally had an idea for a realtime chunkytype effect I wanted to try to sizecode for one of these platforms, But after some experimentation with trying to set up some kind of chunky to planar in as least amount of bytes possible, I finally gave up on my original idea and went back to an idea I originally had over a year ago to create something that had a few differently distinct 3D like elements that could be precalced and worked together to form a cohesive composition. Something like a ball rolling towards the viewer on a 3D perspective plane for example...

Visuals:

Since I already worked on several other intros with a similar setup, they were only focussing on displaying a single looping shape. This time around we are dealing with no less than 3 different shapes... The perspective sphere, the perspective floor and the sky, which each need their own per-pixel color calculations.

Selecting Colorscheme:

Normally the color palette is one of the things I decide on late in development, for this particular intro it was one of the very first things I knew I had to settle on is the color palette. Since generating good looking palettes on the Atari ST, I had some trouble finding a good palette that had different mini ramps of 4 in them as well at least a grass and sky color I could use. I eventually landed on this additive palette:

lea $ffff8240.w,a0 ; VID_COLOR0
palloop:
move.w d7,(a0)+
add.w #$1209,d7
bcc.s palloop

Four to the floor:

Now with the palette in place, I knew I wanted to seperate out the sky from the bottom half first, as well as limiting the number of frame calculation, to keep the amount of precalc in check and then later doing optional camera panning up and down to make things more interesting and suggest more movement and variation.

I got the basic setup in place, starting with the sky/ground division with both utilising a different bit of the palette.

; d2 = Screen X-pos
; d1 = Screen Y-pos
; d0 = calc skycolor (y>>4 + 4)
move.w d1,d0
lsr #4,d0
addq #4,d0
sub.w #68,d1
bmi storepixel

; calculate perspective floor
; z = (y+somevalue)
; d0 = x*4 / z
move.w d2,d0
sub.w #160,d0
muls.w #4,d0
divs.w d1,d0
; d3 = 512 / z
; d7 = frame
move.w #512,d3
divu d1,d3
sub.w d7,d3

; d0 = color = ((d3+frame) & d0) & 3 + 8
and.w d3,d0
and.w #3,d0
addq #8,d0

And here is the result in action:

Now let's get this intro rolling:

Once the sky and ground were in place, it was time to literally place the rolling sphere onto the ground. This was going to be the most complex shape to code. For a spherical distort we first need to have an inverse distance to the center of the screen (constant - (x*x+y*y)):

; D3 = x*x
move.w d2,d3
sub.w #160,d3
muls d3,d3
; d4 = y*y
move.w d1,d4
sub.w #106,d4
muls d4,d4

; d5 = 8192 - (x*x+y*y)
move #8192,d5
sub d3,d5
sub d4,d5

Then we do a check if the calculated distance is within our sphere, if so: We need to calculate the UV coordinates on the sphere. Here is the code for that (i've kept it unoptimised for educational reasons):

; U = X*512/Z
; V = Y*512/Z + frame
muls #512,d3
divs d1,d3
muls #512,d4
divs d1,d4
sub d7,d4
; d0 = calculated color (U^V & 3)
move d3,d0
eor d4,d0
and #3,d0

Now we can precalculate the final color for each of the frames, which we then can later pickup from memory and copy to the active screen.

Optimisation Hell:

When putting it all together and even doing some early optimisation, the total binary size was still around 300 bytes. So from here on out a lot had to happen to make it fit inside the 224 byte + header limit.

I started by removing some MIDI sounds i've added, but the rest was just keep hammering away on each aspect of the intro. Savings were made in reordering branches and registers, trying to reuse as much as possible and if at some point a register was free to use try to load it with a constant I could share between different calculations.

Furthermore the camera panning uses a 'cheap' 10-byte zigzag approach which I was able to work into the frame and offset calculations, which after many hours of rolling my head onto the keyboard resulted in the binary size ending up exactly at 256 byte TOS file.

Conclusion:

After everything was finally within the required size limited, I zipped everything up and sent it to the 68K Inside orgas just in time for testing (Thanks to the 68K Inside orgs for allowing me some slack in finishing my prod). The title was also a nod to the famous dutch demogroup from the 90s with the same name (Finland zuigt, daarom demo deze taal!).

The intro was received well at the party and won the 1st place in their 256 Byte Intro competition. You can check out the other entries from 68K Inside here

Return to blog overview