• Updated 2023-07-12: Hello, Guest! Welcome back, and be sure to check out this follow-up post about our outage a week or so ago.

Stacksmith: Reverse Engineering HyperCard

uliwitness

Active member
Hi,

since someone in another thread mentioned it'd be interesting, just thought I'd mention that I'm working on a HyperCard clone names Stacksmith that runs on modern OSes. Some goal posts:

1. Fix some of the mistakes SuperCard and LiveCode made in extending HyperCard's design
2. Make it feel like a modern program
3. Import existing HyperCard stacks (I have a 'stackimport' command line tool that converts a HyperCard stack into XML + image files, which Stacksmith can read, as can any human with an image editor and text editor, but it's not been a priority to keep it working)
4. It will not run XCMDs or XFCNs (that would require MacOS 9 emulation and even then wouldn't be very useful for most XCMDs), though I will eventually add some sort of extension mechanism, and I will likely add some built-in commands for compatibility with common XCMDs like "palette", "addcolor" etc.
5. Expand upon HC with color support, internet support, arrays, multithreading, modern MacOS UI elements, closures, animation, but done "the HyperCard way" using metaphors non-programmers know, not by just adding Pascal or C syntax to HyperTalk.

A lot of this already sort of works (multithreading and closures aren't there yet, animation doesn't exceed what HyperCard did yet), but it's all still very much a work in progress and not really usable in practice.

I've also started rewriting the programming language a while ago, to fix a mistake I made in the core design that greatly slowed down development of new language features, so who knows when that new rewritten language will ship.

But anyway, some of the results of this can be seen in the file format description on HyperCard.org, which describes all I know about HyperCard's file format, as well as the AddColor resources that store color information.

So if any of you are curious, feel free to ask questions in this thread.
 

cheesestraws

Well-known member
Perhaps a silly question, but I couldn't see them on the website: what are the system requirements (wrt OS version etc)?
 

uliwitness

Active member
Since it's still in development, system requirements are currently "whatever the current OS is when I release a new build" :ROFLMAO:

So that's likely MacOS 10.14 on an Intel Mac or so at the moment. Chances are it will also run on an ARM Mac in Rosetta, but I don't have one yet, so that's not yet been tested.

Doesn't really seem worthwhile to worry about anything beyond making it run at all, before it is finished, I (or someone who cares about a particular OS) can always back-port features that require newer OSes later on.

I've also ported some of the scripting language to Windows, but that's far from a full HyperCard clone, and just something I wanted to play with.
 

cheesestraws

Well-known member
Yeah, that's fair, just wondering if you had an idea of what it was likely to compile on :).

I think I'm going to play with this this weekend. Looking forward to it...
 

360alaska

Well-known member
When was a kid, in school, we had Hyper studio, maybe you should have a look t that before going too wild?
 

Crutch

Well-known member
I quite liked SuperCard, which appears to have been updated to work thru OS X Mojave but now sadly appears to have finally been left to die by the publisher. (Hope I’m wrong.)
 

Scott Squires

Well-known member
Presumably they never ported SuperCard from Carbon to Cocoa, which is why it no longer works in Catalina. If they didn't do it by now I would be surprised if they ever do.
 

bdurbrow

Well-known member
Hmm… is the language going to have a proper class & inheritance mechanism? Also, the runtime engine is an interpreter, and not a JIT that targets only x86? In principle at least, if there’s no x86 dependencies, it should just compile for M1 processors by switching the build target to all architectures…

:unsure:
 

cheesestraws

Well-known member
Hmm… is the language going to have a proper class & inheritance mechanism

At risk of wandering off-topic here, I remain very much unconvinced that class-based inheritance is the correct way to go here. Smalltalk pulled off inheritance in a similarly dynamic system, and I very much do not want to Trashtalk Smalltalk (see what I did there) but it's much more a Real Development Tool than HyperCard is, and even in its more refined and beginner-friendly incarnations never managed to pull off the directness that HyperCard did.

There are plenty of other ways of being OO than class/inheritance based OO (some of which have very desirable theoretical characteristics indeed, though these are hardly relevant to a HyperCard successor—Kim Bruce's book on the subject is still a good read IMO, though...). Historically, I think it's quite telling that a lot of the systems that tried to learn from both Smalltalk and HyperCard, especially within Apple, ended up pursuing prototype-based inheritance instead. I'd argue this turned out to be a bad idea, but it wouldn't have been obviously a bad idea until it had been tried.

I'm not going to go into lots of detail here—the title of this thread isn't "cheesey pontificates endlessly about type systems", after all—but in my ideal HyperTalk-like language, I'd use a hybrid system: lightweight implicit interfaces for typing ("object passed here must have these properties") and prototypes for inheritance of behaviour (e.g., cards passing on event handlers to their backgrounds). And probably no subtyping relation at all, except implicitly.
 

uliwitness

Active member
@bdurbrow The scripting language's engine is a bytecode compiler + virtual machine, so yes, no JIT (yet?) and will just compile on other platforms. Given iPhone and Mac used different CPUs, I didn't really want to write TWO compilers at the beginning, the project is gigantic enough as-is.

Regarding M1, it should just compile, but I don't have one, so I didn't spend time on it yet, that's all.

Regarding inheritance, I'm thinking about ways to allow inheriting more behaviors, but I doubt it will use classes. HyperTalk seems to be more of a prototype-based language (particularly with user properties like SuperCard and LiveCode have them), so it'll probably be more like the existing "start using" mechanism, but for more objects than just stacks.
 

bdurbrow

Well-known member
The thing with HyperCard is that it only allowed you to use the object classes that it had built in: cards, buttons, etc. What I was thinking is something like this:

Code:
protocol MyGeometryStuff can
    area
end MyGeometryStuff

class MyBox is an object that can do MyGeometryStuff
    and has
        left
        top
        right
        bottom
    and can
        on area
            return (right-left) * (bottom-top)
        end area
end MyBox

class MySquare is an MyBox
    and has
        private somethingHidden
    and can
        on new horizontal, vertical, size
            set left to horizontal - size
            set right to horizontal + size
            set top to vertical - size
            set bottom to vertical + size
        end new
end MySquare

Put that somewhere accessible (typically, a card or stack level script), and use it like so:

Code:
on mouseDown
    put the value of card field "fromLeft" into horizontalValue
    put the value of card field "fromTop" into verticalValue
    put the value of card field "size" into sizeValue
    create new MySquare called aSquare with horizontal:horizontalValue, vertical:verticalValue, size:sizeValue
    
    if the area of aSquare is less than 5 then beep
end mouseDown
-- MySquare, having gone out of scope at this point, gets deallocated.
-- Put it into a persistent storage container like a card or stack variable to keep it around.

To restrict method parameters to a protocol, you might do something like so:
Code:
on myEvent someObject must handle MyGeometryStuff, someOtherParameter
    -- method body
end myEvent

Note that it's been decades since I actually wrote any HyperTalk, so I might have muddled something.
 

bdurbrow

Well-known member
The other thing about HyperCard that really bugged me is that it didn't have layers or snap-to guides. Everything was on a single bitmap either on the card or the background; and getting graphics like custom buttons and frames and stuff aligned was a pain. It would be nice if editing a stack could act a bit more like the earlier versions (pre-autolayout & SwiftUI) of Interface Builder.
 

uliwitness

Active member
@cheesestraws Hmm, interesting. As a scripter back then, I definitely saw the need to be able to pre-package behaviors and attach them to objects.

When I poked around in the original Myst a few weeks ago, I found that they used the button name for that. All buttons seemed to have been created using the "Link to..." GUI, and then they had a "go" handler in the card script that looked at the sender's name to decide what transition to use, sound to play etc.

So I'd definitely want to fill out that existing feature. My current thinking went along the line of a property that lets you select an existing button's script as "inherited" for your current button, which would allow for a nice picker UI where people can create a new button, choose a "class" from a "recents" popup, and then "Link to..." or whatever to have a built in GUI for their game engine.

I don't think there will be any typing per-se in Stacksmith. A good HyperTalk doesn't really do types (see how confusing AppleScript's "we have types but won't tell you about them" was), so some sort of behavior inheritance seems like the next best thing.
 

cheesestraws

Well-known member
So I'd definitely want to fill out that existing feature. My current thinking went along the line of a property that lets you select an existing button's script as "inherited" for your current button, which would allow for a nice picker UI where people can create a new button, choose a "class" from a "recents" popup, and then "Link to..." or whatever to have a built in GUI for their game engine.

Yes, that's kind of what I meant by prototype-based inheritance: grabbing a script from another object and going "like this, but...".

I don't think there will be any typing per-se in Stacksmith. A good HyperTalk doesn't really do types (see how confusing AppleScript's "we have types but won't tell you about them" was), so some sort of behavior inheritance seems like the next best thing.

Yes, absolutely: I'm using "types" here in perhaps a rather theoretical sense. They certainly wouldn't surface like that.

Sorry, didn't mean to derail the thread. Type discussions are only really relevant to HyperTalk-likes in very specific ways...
 

uliwitness

Active member
protocol MyGeometryStuff can
area
end MyGeometryStuff

Given that you don't declare objects in HyperTalk, but rather create them using a GUI at runtime (or using the "create" command), and then they end up as concrete things in your SmallTalk-like image, I'm kinda thinking classes should at the least work the same way.

So one approach I'm considering is having a GUI to create new "object templates" that define initial values for properties and a script. There would be script commands to create such "class objects" just like the "create" command, but it would make classes more concrete.

MetaCard (now LiveCode) does something vaguely similar, where certain parts of a stack are just objects on a card nobody will ever visit. Like, icons are just graphic objects in the current stack. Often people use bitmap graphic objects on a card in a second stack in the same stack file. On one hand I like the simplicity and flexibility of this, you can just use any graphic you can make with MetaCard and use it as an icon. On the other hand, it feels kind of janky to have a stack that is only there to hide icons and other resources from the user of a stack.

Hence why I haven't pulled the trigger on any one solution, because I might want to have icons and templates in a special section of the stack (like the resource fork was in HyperCard) with a special picker UI.
 
Top