CART-0, Go & WASM-4

here the thing

here it's source

What is WASM-4?

WASM-4 is a so-called fantasy console. Basically a platform with artificial restrains inspired by old consoles, because restrains are fun. WASM-4 runs on webassembly, so you can use almost any language that compiles to wasm. I say almost, because the WASM-4 cartridge size and RAM is limited to 64kB. Since memory size is crucial, using standard Go compiler wouldn't get me all that far. But fear not, for those are the exact reasons TinyGo and Binaryen's wasm-opt exist. With these, Go becomes a viable option for WASM-4 development.

Why?

Because I wanted to try something different than Raylib, but I didn't feel like learning a whole new framework. WASM-4 does not provide much, just a few functions really, but they are enough for my needs.

I personally really like the visuals of WASM-4 games. WASM-4 has a (160x160)px display and at maximum 4 colors on the screen at the time. Furthermore, textures can hold at maximum 4 colors including transparency, so your transparent textures actually only hold up to 3 of the current colors. But the color selection is entirely up to you and you can switch the color pallet at runtime. I really like, keeping colors at minimum, but switching pallets with the scenery/mood, and WASM-4 is perfect for this.

What have I made with it?

But [E X P E R I E N C E] of course!

I mean, you can just click the top link and experience the [E X P E R I E N C E] for yourself, it's just a few minutes long. All I can say is that it's a walking simulator with puzzles, secrets, and a boss at the end. All miraculously fit into just 64kB! You should also read the source after you're done. After all, it's part of the [E X P E R I E N C E]!

What have I learned?

I'm sure I've learned a lot about myself, but that is not what you're interested in, now is it?

Go is nice. It works, and it's dynamic enough to handle most things you'd need it to handle. (probably, maybe not, IDK (I'm still in the automatic-text mode, should get back to semi-serious))

One thing that makes me not happy is that it's not (at least TinyGo is not) happy about cyclic references and stuff. Like, say I'm defining a data structure (like the level layout list) and it contains a function. I can define the function within it just fine, but only as far as neither it, nor any function it calls refers to the data structure I'm defining. Not so nice if I need the functions to modify the structure. You can, however, put such function to the structure once it's created.

What I can do then is to instead of defining a fixed sruct as a part of the bigger structure, I can just define a function which creates and returns the structure, while adding the missing function to it.

Go, fortunately, has powerful enough OOP to handle a type that can be both a literal and a function returning it just fine. If you want to see examples of what I just explained, I guess you'll have to read the code (hehehe, it's in 'overworld-data.go' BTW)

I've got some bugs in the default WASM-4 bindings however, so I had to add the following lines to it:

//go:linkname getCurrentStackPointer tinygo_getCurrentStackPointer
func getCurrentStackPointer() uintptr {
  return 0
}

Not sure what exactly it was problem with, nor if this is the best solution, but my project compiles and runs with it just fine. I should probably push it to upstream. I'll get to it I swear.

Wow, looks like I've made a b-log of a reasonable length for once! Well, let's not ruin it now...

Peace~