Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Show HN: Meg-4, the Open Source PICO-8 alternative (bztsrc.gitlab.io)
6 points by bzt on June 16, 2023 | hide | past | favorite | 12 comments
Hi fellow hackers,

I've created a GPL licensed alternative to the proprietary PICO-8. It also addresses most of its shortcomings:

- multilanguage support

- uses UTF-8 encoding (BMP only)

- sophisticated user input methods (direct codepoint, composition, Hiragana and Katakana etc.)

- provides a large and efficient API library for your scripts

- supports C, BASIC, Assembly and Lua scripts (more to come)

- supports wide variety of file formats (Amiga MOD, MIDI, Tiled TMX, PNG, etc.)

- capable of importing PICO-8 and TIC-80 cartridges

- runs in your browser: https://bztsrc.gitlab.io/meg4/

It might not look like much at first glance, but it surely shows its strengths when you start using it (for example automatic API help as you type in the code editor, or invoking the built-in debugger if your script crashes, things like that which makes development easy and fun).

Also check out its well-structured and comprehensive documentation:

https://bztsrc.gitlab.io/meg4/manual_en.html

Binaries are provided for emscripten (web), Windows, Linux (statically linked SDL and GLFW3+portaudio, dynamically linked deb package for Ubuntu and RaspiOS).

It is still in early in development, but almost feature complete. At this stage, expect minor bugs here and there, but should work most of the time. The interface is already translated to 25 languages, but the built-in help and the user manual is only available in English for now.

Let me know what you think!



Cool! Two questions:

1) Is there a table of contents for the manual? I’m on my phone and I only see next/previous buttons, and that’s very tedious.

2) What kind of assembly language does it use? Was it inspired by something (6502)?


> Is there a table of contents for the manual? I’m on my phone and I only see next/previous buttons, and that’s very tedious.

On desktop, should be on the left (like readthedocs). On mobile there should be a hamburger icon. I'll look into it (the MarkDown to HTML converter is my project too, https://gitlab.com/bztsrc/gendoc so you are right to blame me if this isn't working)

> What kind of assembly language does it use?

Here's the description: https://bztsrc.gitlab.io/meg4/manual_en.html#mnemonics (scroll down a bit for the full instruction table)

Most of it is standard (like "jmp", "jz", "jnz", "call", "ret" etc.), and for the rest I've used AT&T style type-in-suffix syntax, like "mulf" (float multiplication), "ldb" (load byte), "stw" (store word) etc. It's a RISC, about 60 instructions only, so it's pretty straightforward and easy to learn I believe.

> Was it inspired by something (6502)?

Not really. I invented the instruction set as I wrote the C compiler and the optimizer. My goal was to come up with a bytecode that plays nicely with the code generator and can be processed in the VM easily and efficiently.

Full disclosure, I've used 6502 (back in the C64 era, haven't touched it for a while). On the other hand I use x86 and AArch64 Assembly regularly and I also have a fair knowledge on VM bytecode (like Lua, Java, WASM) too, so these might have unintentionally affected some of my decisions. But I don't think any of these as direct inspiration.


Wow, I didn’t realize you wrote a C compiler just for this oroject! I assumed you were relying on an existing compiler. Very impressive!


> I assumed you were relying on an existing compiler.

Fair assumption, actually I was. Originally I wanted to port Bellard's TCC, but run into roadblocks: no real architecture abstraction layer as it generates machine code directly, so hard to port to a new CPU. Also it would be nearly impossible to add new languages like BASIC to that compiler.

> Very impressive!

Thank you very much, but I'm not so sure. C89 is a very simple language (the best ever in terms of provided expressivity and required compiler complexity IMHO).

TL;DR Problem only starts when you try to generate efficient code for an actual real hardware (which part I elegantly avoided entirely by designing the CPU myself), and when you start adding features from the later, increasingly more insane standards (C99, C11 etc.). K&R were geniuses, most of the restrictions they designed and were put in the basic ANSI C89 language makes it extremely easy to implement a C compiler.

And a little rant about integrating a 3rd party compiler, if you don't mind: it was much harder to integrate Lua. That's because Lua is a security nightmare, poorly documented and does not work the way as the doc says. For example:

- Lua might call abort() on your host application (seriously, not joking! And "lua_pcall" dares to throw an "isn't protected" error, resulting in calling that abort. I had to come up with an ugly continuity function and "lua_resume" workaround);

- lack of parameter verification, calling functions like "lua_getinfo" might segfault without any apparent reason;

- unless patched, execution of user provided strings as system commands is allowed;

- unless patched, provides full file system access outside of the sandboxed environment;

- ...and I still couldn't figure out how to get the faulting source line from an error event (which one might think to be obvious and trivial, but it really isn't).

So yeah, integrating Lua definitely took longer than implementing my own compiler :-)


That’s funny, I almost asked about TCC, but decided not to because I wasn’t sure it could be easily adapted to your custom VM :)

For Lua and file system access, is that only with the standard library? If not, that would be very surprising!


> For Lua and file system access, is that only with the standard library? If not, that would be very surprising!

If by standard library you mean Lua's io package in baselib, then the answer is yes. For example, "dofile" or "loadfile" functions will work no matter baselib is removed or not.

Here's a full list if you're interested: https://gitlab.com/bztsrc/meg4/-/blob/main/src/lua/hardened....

In a nutshell, I've removed package, coroutine, io, os modules from baselib and all functions calling fopen or fread/fwrite (like "loadfile") and replaced these with the MEG-4 API. This way you have the same functions in Lua as in C. All the rest left untouched; eg. table, string, utf8, math, etc. modules are still available as usual.


Okay, doc fixed, now you should be able to toggle the ToC on your phone.


Working now, thanks!


hell. yes!!! Thank you for this, this is awesome!


You're welcome! Spread the word if you like it ;-)

My hope is to build a nice and friendly community around it in time. Testing results, translations, contributions, PRs, more floppies are always appreciated!


Why not RISC-V?


As I wrote, I created a bytecode which fits the compiler's code generator the most. This keeps the entire code base small, the bytecode VM simple and compilation fast. This is a self-contained solution, the compiler as well as the execution environment is part of the emulator; therefore it has to be compatible with itself only, which opens up solutions for simplicity and effectiveness.

Using real world RISC-V instructions would have introduced a lot of complexity without any real benefit. It's not that you can run the MEG-4 scripts without the API library and emulation environment anyway, so at the end of the day the actual instruction encoding doesn't matter.

BTW, if I were to use an existing instruction encoding, I probably would have chosen WebAssembly instead, because it is a lot easier to generate and lot easier to process than a real CPU's instruction set. There are many wasm VM libraries with nice licensing and easy to integrate interface and virtually no dependencies like https://github.com/kanaka/wac for example. But again, implementing wasm's poorly engineered container format and one of its incompatible ABI would just add complexity and have no real benefit.

All that being said, one could implement a new bytecode format in MEG-4 easily if they really want to. It already supports multiple instruction sets (Lua being a working PoC).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: