Blog

Apple Special Event

  • Live video doesn't work in Safari beta. Had to watch on iPad.
  • Steve Jobs tribute. Makes me a little uncomfortable. I don't think Steve would've liked being deified like this. Not sentimental, he wanted the work to speak for itself.
  • Apple Park. Very pretty as a modern cathedral, but still that open plan is going to be Hell for developers.
  • Apple "Town Squares". This is a very 20th Century kind of thing, a real-world gathering place, where you're supposed to learn from others. But now everyone just lives by their computer and talks online, watches online video. There's a lot of "we're restoring historic buildings" in this; the Medicis funding arts while politicking to get their Popes elected.
  • The stream isn't doing the usual dual-camera picture-in-picture of presentation and zoomed-in view of presenter, so often I only see a tiny bit of a presentation screen, then it flips out for context. Very jarring.
  • Apple Watch, exercise ad, lot of heart health study. Almost every watch app is getting redesigned again, because they can't figure out what it's for, beyond being a watch. "Now you can take a phone call, while you're surfing!" Streaming audio is their solution to killing the iPod… But how much is that going to impact your data cap?
  • AppleTV. A presentation screen on streaming video can't show HD vs. 4k HDR video, so they desaturated the "HD" image to make the images look different.
    • Aside: I've never much liked Spider-Man, but the new movie looks stupid, the costume looks like a plastic CGI figure (which it is, I guess), and the fight scene was so over-choreographed it looked like ballet, not a kid in a brawl with thugs.
    • Aside 2: I love thatgamecompany's games, Flower and Journey are amazing. Sky looks just as good. But I'm dubious to the extreme about social gaming in it; that's the weakest part in Journey, which has almost no interaction.
  • "For the first time, you were actually touching the button!" And then iOS 7 destroyed that UI by removing buttons and making everything a bland white void. Thanks IVE-1138.
  • Ha ha everyone who had "iPhone X" on their bingo card, it's "iPhone 8". There's a regular fat model, and a super-fat + model.
  • The camera is much better. I dislike the term "portrait mode", which doesn't mean portrait-vs-landscape, but bokeh.
  • Using AR (Augmented Reality) Kit to put virtual objects on the real world is still silly, you're still staring at your phone. It replaces a convenient on-screen camera control with having to spin around like a doofus, you can't just sit in your chair and play comfortably.
  • There are sane uses of AR to overlay physical things, like landmarks, or provide auto-translation. If Glassholes and naked Robert Scoble hadn't ruined Google Glass, it might be have a useful interface. But holding up your phone to do it is still silly.
  • Wireless charging is a nice thing. In a car is a strange use for it, since it'd just bounce around without something holding it in place, like a cable.
  • One More Thing: A separate model of iPhone X, with all the crazy rumor stuff. No home button, edge-to-edge screen.
  • FaceID: From now on, you need to wear a mask at all times or anyone can use your "true face" to unlock your phone. The pigs can just hold your phone up in front of you to dig thru it. Good thing there's animoji, so you can send a completely virtual face (panda, poop, robot, or alien) to replace that pesky human interaction.
    • Aside: I am wearing a Star Trek Mirror, Mirror tshirt. I'm the one with the goatee.
  • iPhone X (pronounced "Ten"), and Qi chargers (pronounced "Chi") provide all new ways for Apple devotees to "well, actually" everyone else.
  • Skate to where the oh not this quote again.

Probably makes sense for me to wait a couple months for the iPhone X and get the bleeding-edge device rather than a better what-I-already-have.

OK, get back to work.

TPortableNetworkGraphic

Trying to load a PNG image and display it on the canvas has been… not fun. Delphi only knew about BMP stored in some horrible Microsoft resource format, and so everything FreePascal adds on top is a pile of hacks or undocumented features. The WWW was not especially helpful.

Mostly I'm posting this so someone else might find it in a search.

uses Classes, SysUtils, Controls, Graphics, LCLType, types, contnrs;

{
type
    TSprite = class
    public
        color: integer;
        filename: array of utf8string;
        subrect: array of TRect;
        constructor Create(c: integer; f: utf8string; r: TRect);
    end;
}

var
    imageCache: TFPObjectHashTable;

function getImage(filename: utf8string): TPortableNetworkGraphic;
var
    img: TPortableNetworkGraphic;
begin
    img := imageCache.Items[filename] as TPortableNetworkGraphic;
    if img = nil then begin
        try
            img := TPortableNetworkGraphic.Create();
            img.loadFromFile(filename);
            imageCache.Items[filename] := img;
        except on e: Exception do begin
            LogError(Format('Image %s: %s', [filename, e.message]));
            raise;
        end;
        end; // try
    end;
    Result := img;
end;

procedure drawSprite(canvas: TCanvas; spr: TSprite; srect: TRect; tick: integer);
var
    img: TPortableNetworkGraphic;
    frame, nframes: integer;
begin
    if spr.color <> dawnUndefined then begin
        canvas.Brush.color := spr.color;
        canvas.FillRect(srect);
    end;

    nframes := length(spr.filename);
    if nframes > 0 then begin
        frame := tick mod nframes;
        img := getImage(spr.filename[frame]);
        canvas.CopyRect(srect, img.canvas, spr.subrect[frame]);
    end;
end;

Pascal Learning Curve

What I've learned so far:

  • I spent a while trying graphics libraries (or failing to even compile them) before deciding I don't understand the UI model enough yet, so I'll prototype with some high-level drawing and circle back around to OpenGL or SDL.
  • Build a do-nothing app in Lazarus, make a single form with a default FormCreate method, then quit out and write code starting from there in BBEdit.
    • Part of that is that I'm not going to use a ton of GUI components, and code building is the evil opposite of Interface Builder. In IB, you edit UI and connect it to method names scanned out of the source code, it doesn't touch your code.
    • The Lazarus editor is nightmarishly wrong and keeps inserting stuff in my code which makes me crazy. Maybe there's non-crazy-making settings, and probably it seems fine to masochistic Windows and Linux users, but I make enough problems in my life.
  • Naming conflicts are a giant problem, so my current naming scheme is: For class "foo", it goes in file FooUnit.pas, containing unit FooUnit and type TFoo = class…. I'm naming instance fields _bar and accessors bar() and setBar() as I do in most languages. I've mostly got the compiler to stop screaming at me every build. Not letting you name a unit, class, and field the same thing is infuriating.
  • Build with lazbuild -B --bm=Release whatever.lpi; I wrote a script to choose Debug or Release builds and launch the app if nothing went wrong, which is close enough to hitting Cmd-R.
  • Bookmark the docs for:
    • RunTime Library
    • Free Component Library - in particular unit 'contnrs' wants to buy some vowels but has dictionaries, lists, etc.
    • Lazarus Class Library
    • There's very little explanation, so often I have to go digging in source like /Developer/lazarus/lcl. I lost about 30 minutes today because they didn't document that TCanvas.FillRect uses Brush settings, TCanvas.Rectangle uses Pen settings, and I figured it out by reading the Carbon implementation. ? ☕️ ?
  • Almost always if there's a non-domain-specific type I need it already exists. Batteries are included but mostly they're named badly, or upside down, or hidden in sofa cushions, or the dog buried them and I need a metal detector, or my psycho ex stole them and is holding them hostage for a pity fuck.
  • The actual implementation code isn't much different from any other procedural language. For a guy who codes in Pascal for one year every 10 years, it's rolling along pretty fast. The near-equivalency of records and classes, and of functions, properties, and methods is convenient. Defining vars before using them, like in old-timey K&R C, is not convenient. Inline variable definition would be a gigantic quality of life improvement, which I doubt they'll do.

Hey Siri

Every morning I get up, plug in my phone & iPad, make coffee in a French press, and say to my watch, "Hey Siri set a timer for 4 minutes". At least 2, sometimes 3 other devices (finally on Sierra just in time for High-as-in-grass Sierra to come out) beep and try to catch that. Usually they all fail except the watch. If they do succeed, I now get timers going off in multiple places, because despite Continuity nothin communicates this state.

And Apple wants an Apple TV and Apple Home to join that mob of Siris.

☕️

Oracle Murders Solaris

For those unaware, Oracle laid off ~ all Solaris tech staff yesterday in a classic silent EOL of the product.

Simon Phipps

FUCK.

Solaris was a better server and development platform than anything else (OK, after HPUX and SunOS reached EOL), but getting management to spend money up front was always a massive battle. SUN did themselves no favors by going back and forth with SPARC and x86, and getting a freebie OpenSolaris running was a challenge.

But now the world runs servers on piece of shit free-as-in-freebase-heroin Linux, paying fedora-wearing dipshits at DeadRat for "support" consisting of "no, you go fuck yourself".

This future has been brought to you by lawyers and the lowest bidder.

I'm too bummed out to make a playlist for today, so here's a couple of Apple's:

Pascal

Trying out alternative languages to work around my performance and native binary problems, I've circled back around to the '70s and '80s: Pascal. I used classic Pascal on Atari 800 and TRS-80 back in the day, and did quite a bit with Kylix (Linux version of Delphi) before Borland killed that.

Pro

  • Fast Compiles. FreePascal compiles faster than anything I've used in ages. That was always a major Pascal selling point, and it still is. Optimized for programmer time.
  • Fast Runtime. As close to perfectly optimized machine code as you're going to get. Computer Language Shootout has competitive times with C++ for most benchmarks, and I think the worst-cases are variations in style.
  • Object-Oriented. FreePascal reimplements Delphi-style objects, which are pretty standard Simula-type OOP. I dislike having to tag methods as virtual, like some C++ or Swift peon, but it has everything I'd expect in a modern OOP system.
  • Reference Counting. No GC pausing, no manual memory management. Like Objective-C 1.0, you have to nil-out field references in your destructor, but otherwise you never need to worry about it.
  • Exceptions. Unlike Objective-C and Swift (which relies on Obj-C frameworks), you can throw exceptions and catch them and the program keeps working. Hooray! Flow control that isn't insane! There's no checked exceptions, which is sad, but it works.
  • Cross-Platform. Mac, Linux, Windows, Android, and iOS. Has SDL and OpenGL bindings, and some other options. I'll see how building out UI for each of those works, but it's not trapped on Mac like most other choices.
  • Native Binary. No source code included in the downloaded app. Dynamic language obfuscators are a minor obstacle at best, while machine language is hard enough to decompile. Sure, the other option is to put the program online and just have a thin client in the user's hands, but I'm old-fashioned, I believe in networkless programming and not paying Amazon for server time.
  • Easy Native Library Integration. Pretty much seems to be defining functions as external and calling.
  • Case-Insensitive. I'm usually neurotic about proper capitalization, but here it's a mercy: The classic Pascals were all-uppercase, Delphi CapitalizedEveryWord, but I prefer lazyCaps. FreePascal doesn't care.
  • Real Programs. There's working programmers using FreePascal to keep their (often very expensive) Delphi software running, and writing new code in it. That makes me confident it's not an unsupported toy, and there's current documentation and help.
  • BBEdit. Object Pascal syntax mode works fine.

Con

  • Bondage & Discipline. Not quite as BDSM as Java, Swift, Haskell, or classic ISO Pascal, which in practice have no safewords. You can use dynamic arrays, Variant and OOP types, and even dangerously cast anything to anything or screw around with pointers, but it's not beautiful anarchy like Python or JavaScript.
  • Pascal Syntax. Verbose begin/end pairs everywhere, long words of function, procedure, and such. Semicolon rules are insane (yes, they're terminators not separators; this is not how we use them in any other language, including English), I've taken to just always using begin/end blocks because I don't trust a misplaced semicolon not to terminate the wrong block.
  • Documentation. FPC's docs assume you already know Delphi. I found some decent docs at Borland's site and old Pascal textbooks, but I dunno how a normal person would learn this. Some of the libraries have moved in 3.0, and you're never going to figure this out unless you like digging thru the guts of a language.
  • Configuration. Put this in fpc.cfg somewhere, and export PPC_CONFIG_PATH to the path containing it:
    #WRITE Compiling with fpc.cfg
    -O3
    -Xs
    -MOBJFPC
    -Sh
    -Fu/usr/local/lib/fpc/$fpcversion/units/$fpctarget/rtl-console
    -Fu/usr/local/lib/fpc/$fpcversion/units/$fpctarget/regexpr
    

    The write is just a sanity check that I have it configured. Instead of the next two lines, I could put -dDEBUG or -dRELEASE on the fpc command-line, but I'm not currently using gdb (unfrozen caveman Mark debugs by writeln), so this is easier. -MOBJFPC forces modern FreePascal mode, not a compatibility mode. -Sh forces a default string type of ansistring instead of shortstring; but to be precise, I always specify utf8string. The -Fu lines add some paths where libraries have been moved.

    I want to have the local directive {$M+} (reflection support) always turned on, but I can't figure out any command-line option to do that.

  • Look Like a Crazy Person. But sometimes the crazy people are right.

Example

To (re)learn the language, I wrote a 4-function RPN calculator for Mac console: RealCalc

Presumably it compiles just fine on Windows or whatever, but you'll have to customize the fpc.cfg file. I'm a ways from dealing with that.