heckmeck!

Nerd content and
cringe since 1999

Alexander Grupe
Losso/ATW

Santa wants you… to check out my little contribution to this year’s Teksti-TV advent calendar at Yle’s Teletext service from Finland. :) At least today, it should be on page 832.

Here’s the editor link. All the advent calendar Teletext pieces are also on Demozoo. Thanks to illarterate for curating the event, and merry relax-mas to all!

Programming fonts with “clever” ligatures? That’s an “Ugh!” for me.

On Hacker News, I saw a post titled “I tried Gleam for Advent of Code”. Luckily, “Gleam” turned out not to be some AI shit, but a new (-ish) programming language. Interesting! And a post about Advent of Code problems is a great hook to get a first impression and to learn how coding in Gleam looks and feels like.

It is a well-written blog post (thanks!), and I mean no disrepect to the author – but the typeface used for the code snippets made me struggle with the “looks” part already.

How is the code formatted? What operators does it use? What are common idioms? Let’s take a look at the very first block of example code:

“A-ha, so that’s an example about pipes and the echo command. Is that the complete code or a summary? What are those triangles? Can I click on them and expand more details?”

I did click on a triangle and was surprised that it didn’t open up anything (you know, like the <details> element), but instead half of the triangle was selected. “Wait a minute, is this one of those coding ligatures?” Sure enough, after altering the CSS on the page, I could see the actual code:

This is insane. How do you get to know a new programming language when the operators are replaced with arrows, squiggles, and geometric shapes that leave it up to you to guess what they might represent?

LigatureInterpretation

Ha, that’s easy! It’s an arrow of course: ->

Or is it? What if it’s an actual arrow, like U+2192 (→), maybe in a string literal?

Quick, how would you type this in?

This must be <==> as a ligature.

Could be <===> as well – that’s a wide bastard right there!

Obviously -~!

Or -~~? Definitely not -~-, though.

One of those!

To be fair: I can get behind this one, kind of.

It appears when you type ===, and it helps you discern at a glance if you used a clean, strict equality check or typed == instead.

Then again, things are getting out of hand quickly. Almost like that’s the theme here.

There are now so many lines that you want to add a clef and insert some notes. Oh, and is it !== or =!=?

Oh, nice, a postcard! No, wait… This is the concatenating assignment .= (and whatever it means in Haskell).

As a Perl veteran, if I were to encounter this abomination in the wild, I would concatenate someone’s face with my fist.

I’m joking. Use them 1337 ligatures if it makes you happy. But when I have to decode them in an informational article that should be about the exact letters and symbols? Miss me with that!

With regards to coding fonts, here’s my pettiest of pet peeves:

When the underlying text is:

Sprite size is 16x24 pixels. Class files start with 0xCAFEBABE.

Now we’re playing in a Wordpress-like level of cleverness! It’s kinda like the old “smart quotes” feature, together with an attitude straight from good old Clippy:

I see you’re typing 16x24! Surely you meant to use the multiplication sign ×, and are just too dumb to type it in properly with your greasy fingers. Don’t worry – we’ll fix it right in the typeface with a ligature hack!

We only need one custom rule for every combination: 0x0, 0x1, 1x0, 1x1, 1x2… Isn’t that elegant?

While we’re at it, let’s also use this for hexadecimal literals!

Wow, thanks Clippy, this is genius! Mind = blown! Pardon me, I meant:

But, um… What about binary numbers like 0b0101? And did you skip the uppercase hex prefix 0X intentionally?

Shut up, nerd!

Okay. Where was I? Right, I wanted to check out that programming language, not rant about glyphs. :)

PS: Shout-out to Matthew Butterick who made the case against this typographical madness six years ago.

Cleaning up, I found this little wish list (“Wunschzettel”) for Santa Claus I made 37 years ago. I’m not entirely sure if we got what we wished for in time for Christmas 1988, or some time later. Maybe we had to put up with the ole Plus/4 and our cassette tapes for some more months!

Eventually we did get an Amiga 500 from Karstadt, complete with an English copy of Zak McKracken. The monitor was a Philips CM8833, though, not a Commodore 1884 (?), or 1084, even… :)

Cool stuff to stumble upon, new and old.
Before: What’s Cool? · II · III · IV · V · VI · VII

  • Sizecoding and ramblings
    A collection of superogue’s sizecoding write-ups, a real treasure trove if you’re into these kind of things. I totally missed this crazy 3D pixel intro for the Amiga in 128 bytes of code, WTF! The amount of platforms covered is crazy, too: DOS, ZX Spectrum, Atari XE, Atari ST, MicroW8, TIC-80, Pico-8, Apple II – double WTF! :)
  • Reflections on My Tech Career Pt. 1
    This retrospective of a successful IT career is a great read, and I don’t only say that because there’s Amiga assembly code in it! No, Random ASCII is great blog overall, and I’ve been stumbling upon it often in the past. Each resource leak and subtle bug investigation is a treat! But it was only with this post that I realized Bruce Dawson is the author of CygnusEd, the text editor for the Amiga! It certainly adds up: Creating a lightning-fast, capable editor loved by coders and ASCII artist alike, and later taking that Amiga mentality of code quality, effective resource usage, and general power-user friendliness out into the world…
  • A very weird kids’ show made with DeluxePaint
    Well, it’s all in the title – click the link to enter “What did I just watch?” land. I don’t know any Dutch, so I don’t really understand what’s going on, but I wonder if this would change much if I spoke the language… Thanks to okkie who dropped the link on the demoscene discord!
  • Obfuscating Image Links
    I hate blob: links with a passion (no downloading resources directly from the networking tab for you, mister!), and I liked this post already for sharing that sentiment. At least you can still get something out of it, like this nice technical analysis, complete with a working PoC for building your own obfuscating custom tag. The burdens that insatiable AI scraping bots cause us…
  • Needy programs
    Speaking of relief by sharing the anger: If you, too, hate mandatory user accounts, being flooded with useless notifications, and just generally want to punch someone in the face when you are greeted with “Please wait while we update your installation” instead of the very program you want to use real quick – this post is for you. Breathe in, 3, 2, 1, exhale… Well, it’s probably naïve to do so, but I for one still dream of a world where I install a program once and just use it happily ever after.

PS: Days later, I realized this is not a dream, it’s exactly how I use Photoshop day to day. I’m using version 9.0 a. k. a. CS2, and this poor little program will never see an update, ever.

The only thing I sometimes miss is a contextual auto-fill operation, and under modern Windows installations, it falls into a weird always-on-top mode, and occasionally all the toolbars disappear. But apart from that, I’m happy with it. I especially enjoy the little AdobeUpdater.exe tantrum each time I launch it.

“Sure, Photoshop, I’ll go right ahead and re-install to fix your update problems!”

The “hot spot” determines where your mouse cursor is pointing, i. e. the exact pixel that is considered the active pixel. This isn’t necessarily the top left edge:

For a mouse pointer of 16×16 pixels, like the classic Amigas had, you could encode the hot spot as two bytes in the range of 0 to 15, with (0,0) being the upper left corner. The actual implementation takes a different route:

  • The coordinates are negative – they specify how many pixels you have to shift the pointer up and to the left, relative to the active pixel, so that the hot spot overlaps exactly with the active pixel position.
  • A hot spot in the upper left corner isn’t encoded as (0,0) as you might assume.

Why is that? Apparently, this is related to a bug in the MoveSprite library call.

******* graphics.library/MoveSprite *********************************
*
*   SYNOPSIS
*       MoveSprite(vp, sprite, x, y)
*                  A0  A1      D0 D1
*   BUGS
*       Sprites really appear one pixel to the left of the position
*       you specify. This bug affects the apparent display position
*       of the sprite on the screen, but does not affect the numeric
*       position relative to the viewport or view. This behaviour
*       only applies to SimpleSprites, not to ExtSprites.

This can be corrected by adding one to the hot spot’s x value:

PointerCalculation
// hotspot_x = -7
// hotspot_y = -8
Hot spot coordinates as relative offsets: Take the active pixel position and add (-7,-8)
// active_x = 10
// active_y =  9
Example: Active pixel at (10,9)
// sprite_x = active_x + hotspot_x = 10 + (-7) = 3
// sprite_y = active_y + hotspot_y =  9 + (-8) = 1

MoveSprite(vp,pointer,3,1);
MoveSprite bug in effect: one pixel to the left, at (2,1)
// sprite_x = active_x + hotspot_x = 10 + (-6) = 4
// sprite_y = active_y + hotspot_y =  9 + (-8) = 1

MoveSprite(vp,pointer,4,1);
Increasing hotspot_x by one: sprite position correct

But… That’s not what’s happening in devs/system-configuration, the 232 byte preferences file that contains the colors and the mouse pointer image!

Take the classic default mouse pointer:

Preferences from Workbench 1.2

The selection pixel is at the second column in the second row – so (1,1) in “normal” coordinates, counting from the top left starting with zero. What would you expect the encoded hot spot coordinates to be?

  • (-1,-1) if you just negate x and y,
  • (0,-1) if you take the “1 pixel to the left” MoveSprite bug into account,
  • but certainly not (-2,-1)!

And yet, that’s what is stored on disk:

; devs/system-configuration

00: 0800 0005 0000 0000 0001 86a0 0000 0000
10: 000c 3500 0000 0001 0007 a120 0000 0000
20: 0000 fc00 7c00 fe00 7c00 8600 7800 8c00  bitmap
30: 7c00 8600 6e00 9300 0700 6980 0380 04c0
40: 01c0 0260 0080 0140 0000 0080 0000 0000
50: 0000 0000 0000 0000 0000 0000 0000 0000
60: 0000 0000 feff 0d22 0000 0fca 0002 005a   x=-2   y=-1  colors     
70: 0fff 0002 0f80 0000 0081 002c 0000 0000                colors    
80: 6765 6e65 7269 6300 0000 0000 0000 0000
90: 0000 0000 0000 0000 0000 0000 0000 0000
a0: 0000 0000 0005 004b 0000 0000 0001 0002
b0: 0020 0042 0000 0000 0000 0000 0000 0000
c0: 0000 0000 0000 0000 0000 0000 0000 0000
d0: 0000 0000 0000 0000 0000 0000 0000 0000
e0: 0000 0000 0000 0000                    

Instead of adding 1 to the x coordinate, 1 is substracted! What?!

There’s more: Prior to Workbench release 1.2, the preferences tool did store this hot spot as (-1,-1)!

Preferences from Workbench 1.1
; devs/system-configuration

...
50: 0000 0000 0000 0000 0000 0000 0000 0000
60: 0000 0000 ffff 0d22 0000 0fca 0001 005a   x=-1   y=-1 
70: 0fff 0002 0f80 0000 0081 002c 0000 0007
...

At least the graphics/sprite rendering in the ROM hasn’t changed. If you take this pointer in the old file format, i. e. with (-1,-1) as the hot spot, and move it into the upper left corner, only the black border on the top will disappear (correct), but the black border on the left will remain visible (incorrect).

Hotspot (-1,-1) across Kickstart versions

Still, it’s a mess! And the AmigaOS source code reflects it, too. There are constants like SPRITEERROR=-1 used in various places, and code comments like “oh, we need to compensate for that old off-by-one bug”.

No wonder things got confusing. Maybe there’s an overcompensation for the MoveSprite bug somewhere? Or a sign flip? That could explain why preferences adds -1 to x instead of +1. Regardless of the exact origin story of the hot spot origin –

Does it matter? Umm, yes. Totally! :) It has some funny implications:

  • Hot spot coordinates “in the wild” have
    • 16 different values for y (0 to -15) and
    • 17 different values for x (0 to -16).
    Out of 37,481 preferences files I’ve scanned, 639 had a hot spot x value of 0 – those were probably created with the old preferences tool. That’s about 1.7% of all pointers, but these are only the pointers where the hot spot was on the left-most column. For all the other pointers, you would have to look at them to determine if the hot spot is off by one or not…
  • There are mouse pointers with a hot spot outside of the actual mouse pointer! You can edit system-configuration in a hex editor and create a mouse pointer that cannot be moved near the upper left corner, no matter how hard you shove that mouse:
    Pointer with (0x7F,0x7F) as hot spot
  • When you open a (0,0) pointer in the new preferences tool, you can cause it to glitch out a bit when changing the hot spot.
  • Same when you open a (-16,-15) pointer in the old editor.

Well, I’m out of fun facts to squeeze out of this, and I haven’t even used the “What’s the point?” pun yet. :) Anyway, enjoy your bootable Amiga disk with an unusable mouse pointer that will drive you mad – or your loved ones:

PS: I stumbled upon this when I was writing a pointer editor of my own. It has a similar bug to the original preferences editors! Of course I’ll leave that in…

previous next close