heckmeck!

Nerd content and
cringe since 1999

Alexander Grupe
Losso/ATW

After the challenge is before the post-challenge… It’s snowing again, and I’m so immensely looking forward to the law-mandated Winterdienst that I decided to took a look at my Vintage Computing Christmas Challenge snowflake again. Maybe I get an optimization idea for the VC³ post-challenge?

Staring at the old code, I noticed a pattern in the coordinates:

        dc.b    9*8,0*8
        dc.b    4*8,1*8
        dc.b    5*8,2*8
        dc.b    1*8,7*8
        dc.b    2*8,8*8
        dc.b    6*8,5*8
        dc.b    7*8,5*8

There are “chains” of coordinate pairs (if we flip some values here and there – they get swapped in the drawing process anyway). The second value is the first value of the next element:

  • (4,1) (1,7) (7,5) (5,6)
  • (5,2) (2,8)

If we rearrange the order a bit and insert seemingly redundant extra pairs (like 5,6 and 6,5)…

        dc.b    4*8,1*8
        dc.b        1*8,7*8
        dc.b            7*8,5*8
        dc.b                5*8,6*8
        dc.b                    6*8,5*8
        dc.b                        5*8,2*8
        dc.b                            2*8,8*8
        dc.b                                8*8,0*8
        dc.b                                    0*8,9*8

…we can get rid of almost half the bytes! Instead of reading two bytes each time and advance the coordinate pointer by two bytes, we can read two bytes and advance the pointer by one only.

        dc.b    4*8,1*8
        dc.b        1*8,7*8
        dc.b            7*8,5*8
        dc.b                5*8,6*8
        dc.b                    6*8,5*8
        dc.b                        5*8,2*8
        dc.b                            2*8,8*8
        dc.b                                8*8,0*8
        dc.b                                    0*8,9*8
Data schemeCoordinates ÷ 8Plot and mirror at
Old9,0, 4,1, 5,2, ...(9,0)
(4,1)
(5,2)
New4, 1, 7, 5, 6, ...(4,1)
(1,7)
(7,5)
(5,6)

Cool, plenty of bytes saved! Together with two other small improvements:

  • Avoid a useless register save (move.w d4,d7, 2 bytes)
  • Shuffle registers around so the value we pass for the alert height ends up in the right register automatically (move.l d4,d1, 2 bytes)

…my entry is down from 84 bytes to *checks notes* 78 bytes.

        move.l  368(a2),a6
        lea     .buf(pc),a0
        clr.l   -(a0)
        lea     .coords-1(pc),a1
        moveq   #64,d1
.loop   subq.b  #8,d1
        move.b  d1,d0
        bge.b   .star
        move.b  (a1),d0
        move.b  -(a1),d1
        blt.b   .done
.star   move.w  d0,d7
        add.l   (a2),d7
        move.l  #$562a0001,-(a0)
        add.b   d1,(a0)
        move.w  d7,-(a0)
        neg.w   d0
        blt.b   .star
        neg.w   d1
        blt.b   .star
        exg     d0,d1
        neg.l   d6
        blt.b   .star
        clr.w   d0
        neg.l   d5
        blt.b   .star
        bra.b   .loop
.done   jmp     -90(a6) ; 4eee ffa6
        dc.b    4*8
        dc.b       1*8
        dc.b          7*8
        dc.b             5*8
        dc.b                6*8
        dc.b                   5*8
        dc.b                      2*8
        dc.b                         8*8
        dc.b                            0*8
        dc.b                               9*8
.coords
        dx.b    8000    ; reserve extra space via header
.buf

Unfortunately, some neat optimizations don’t work anymore. The alert-message size exceeded the default stack size of 4k and caused crashes under Kickstart 2.0 and above. No more abusing the stack for our data! On the flip side, the code is more compatible than ever:

  • Uses a dedicated and properly allocated memory area for output
    • This is done with the dx.b directive which reserves a memory region in the file header, but adds nothing to the file size
    • Cost: four bytes for the lea .buf(pc),a0 instruction
  • Does not rely on zero-initialized memory
    • As we learned in 2024, that extra memory reserved in the file header is not cleared under Kickstart 1.x
    • Cost: two bytes for clr.l -(a0) (but we already had that)
  • Cleanly exits to the system
    • The stack pointer a7 is not corrupted
    • After the DisplayAlert call, register d0 contains the value 1 – that doesn’t even cause a “snowflake.exe failed returncode x” message on exit!
    • Cost: free

Bonus: The exit condition when a coordinate value is below zero has changed. We read backwards into the jmp -90(a6) instruction (4eee ffa6 in binary), and the below-zero condition now already occurs with the value a6, not ff. We use that for the alert height value, so it’s smaller now (166 instead of 255). I think it looks better this way, showing more of the AmigaDOS window below:

From the “things that are also cool in the browser” department: Using the passthrough feature of your VR headset to paint in the snow – in the headset’s browser, without any app, thanks to WebXR!

Have I seen that on TikTok? Maybe…

And like many cool things you can do in the browser nowadays, this has been around for years. Catching up takes time…

Built (ha! built) with Passtracing by fabio914, based on Three.js and three-mesh-ui. I only had to expand the maximum zoom a bit, for some reason it stopped at two meters. :)

Besides another superficial glimpse at the magic of Three.js (one day 3D maths and I will become friends…), I learned that my trusty old Meta Quest 2 does not like direct sunlight at all – even more so in a sea of infrared-reflecting snow. Good thing it worked in the end, resp. dawn. I really enjoy using that thing! With its extremely coarse, black-and-white only passthrough visuals, you could say it’s already giving retro vibes compared to its modern headset friends.

Shameless plug: The character I chose for this snowy adventure, Squinty…

…is from my first boxed Amiga game, zerosphere. You can grab a copy in various editions over at poly.play, among hundreds of other awesome titles.

Some nice Amiga games, and zerosphere

Over on the /de Subreddit, German game developer Volker Wertich is doing an AmA (in German) and mentioned some early games he worked on, including Kingsoft’s 1987 Boulder Dash adaption Emerald Mine. Oh, the memories! I quickly fired it up in WinUAE to listen to the iconic title song that has been burned into my memory since I was nine years old. Nostalgia took over and I played through the first level, reminiscing about the subsequent highscore screen that totally blew me away as a kid – all those colors, the cool font with that 3D effect, the parallax scrolling!

WinUAE (with Ultra extreme debug overscan enabled)

I noticed some subtle flickering on the left edge of the screen. What’s up with that? Surely they are using a Copper list for the background colors, why would it flicker? If there’s one thing the Copper can do well, it’s changing colors at exact, stable screen positions.

You may have guessed it: Turns out they’re not using the Copper at all! Instead, the background color is changed in a tight CPU loop that reads out the current screen position and changes the background color on the fly. That’s where the flickering comes from!

; disassembled from $15b6a on

.setup
        move.l  #$dff006,a4     ; VHPOSR
        move.l  #$dff004,a5     ; VPOSR
        move.l  #$dff180,a6     ; COLOR00
        ...
.loop
        move.l  (a5),d0         ; VPOSR VHPOSR
        ...                     ; mangle up d0
        move.w  d0,(a6)         ; set background (COLOR00)
        cmp.b   (a4),d5         ; compare screen position
        bne.b   .loop
        ...

Then again, it does something the Copper cannot do: Reading the screen position and turning it into color bars without requiring any extra memory, all while supporting a vertical scroll effect. Quite clever, actually, and a cool feat for 1987!

I just found it funny that I was busy using the Copper instead of the CPU (see the post before), and then I randomly stumble upon this ancient piece of code that uses the CPU instead of the Copper. :)

I had painted myself into a corner with my first no-cpu endeavor:

  • I took an idea I wanted to do for a long time – a quirky cover of the beautiful Amiga demo Cortez by Melon
  • So let’s use that vague idea and start filming and rotoscoping right away
  • Study Blueberry’s framework, get familiar with Dart and then decide: Nah, I’ll write my own Copper compiler!
  • Write an animation tool and a simulator while I’m at it
  • Oh, and of course we need Rocket integration for sync!
  • Endlessly fiddle with what was supposed to be only the opening screen
  • Damn, that no-cpu stuff is hard! And my chipmem is full already?!
  • The Gerp deadline is coming in hard as well…

Since I couldn’t really release a no-cpu thing elsewhere in the near future, it was time for some painful healthy cuts. Ouch!

In the end I managed to produce a half-assed version just minutes before the deadline. My demoscene friends later told me they had a good laugh at the party when it ran, so that’s a win. (Haha, “ran”!)

Watch it on the prod page

Too bad the title doesn’t make any sense in the trimmed-down version. But I know better than to promise a final, improved version. That would require planning and full-assing – not always my forte. :)

PS: By a weird cosmic coincidence, a video of “Cortez” was shown on the big screen all the way through Dream210 when I was already working on this. Funny.

Wait, what? I had the idea for the post title when I was still half asleep: I vaguely remembered how we used to watch an ancient, hilariously paranoid anti-marijuana movie for the lulz during our forming years at university (which was especially fun to do while pursuing the, um, recreational activity).

And, like any other oldschool geek that was there when the world wide web took off, I still find it amusing that the HTTP header name will forever be named Referer: because someone misspelt it once. So, the title is supposed to be a combination of those two things, because I was browsing through my referer logs yesterday. Funny, eh?

Upon waking up I realized that I’m a hundred years old and it’s probably only funny to me. At least I’ve now also learned that “Reefer Madness” has been turned into a stage musical, a musical movie, and a play, and several other musicals. Groovy! Anyway…

The real madness is the feedback I received for the Amiga Pointer Archive! Everyone and their pet seemed to have something positive to say about it. Is this still the internet I know?

Jokes aside, the nice comments and posts really made me happy. Especially the manic, perfectionist little voice on my left shoulder: “Ha! I knew spending another evening with the all-merged-into-one mouse pointer was worth it, and applying a realistic ordered med-res dither in the original Workbench colors as well! Who’s complaining now that this project is getting out of hand?”

I got boinged, and they liked the über-pointer!

Another thing I’ve learned: There’s an immensely popular Spanish link aggregator website called menéame, and they are producing three times the referer links than the amount I saw when I was on the Hacker News front page. Estoy impresionado y agradecido!

Edit: Bonus gratefulness: The Amigans over at amigans.net actually use the “share” feature for sharing custom pointers! Cheers! And yes, it is indeed intriguing that there was no Boing ball pointer in the files I collected so far – let’s see what the next pointer database update brings!

previous next close