How to launch Makecode Arcade UF2s in Raspbian/RetroPie?

Hi,

Is there any way to (compile and)run the MakeCode Arcade games(uf2/png) offline and “natively” without the browser in Raspbian/RetroPie etc., preferably directly from the command line, like they seem to be launched on the various embedded devices, but without any special boot images?

Though any Raspberry/embedded device with Debian et. al. is my main target, it could also be generic for any Linux/Windows device. “Native” launch with game pad support is preferable to launching inside a browser, though a local minimal kiosk browser online solution, where game controllers already seem to work, might also be a solution(fullscreen without the arcade machine border graphics), although less preferable.

If anyone knows of any already existing solutions, or could point us to the shortest path to achieve something like this, it is greatly appreciated. I’m posting here and writing “us”, since this is a similar post to this, hoping to reach the right people here on this forum, and since something similar has also been discussed briefly a long time ago on Discord with one @mmoskal, but I couldn’t make sense of what he ment with “you already have native (binary) code generation for RPi”.

I have exhausted my Google/Bing search efforts, likewise stuck reading the scientific papers and talks/presentations about “MakeCode and CODAL” and web articles about “Using MakeCode Offline”, hoping for some hints/help here from the true experts/makers of MakeCode.

Thanks for an otherwise really great product with a growing community and endless possibilities!

Br,
Vegard

1 Like

The binaries generated for RPi should work without any special image, at least when you run them from text mode console (they may fight with the X server). Go to https://arcade.makecode.com/?compile=rawELF , click Download and select RPi. You should get a .elf file.

You’ll need a correct config file at /sd/arcade.cfg. To test with keyboard you can do something like this:

SCAN_CODES=/dev/input/event1
BTN_LEFT=28
BTN_RIGHT=1
BTN_UP=25
BTN_DOWN=15
BTN_A=106
BTN_B=103
BTN_RESET=2
BTN_EXIT=105
BTN_MENU=6

I think this is using arrows. The scan codes can be glanced from output of ‘evtest’ command.

Otherwise, you’ll have to set up ALSA sound (if you don’t set up sound, the games will crash).

We used to have a native SDL-based interpreter for MakeCode VM bytecode. That worked on Windows, macOS and Linux (all x86, but I see no reason it wouldn’t work on ARM). I don’t believe this works anymore though. One of these days I may try to revive it, but don’t hold your breadth.

3 Likes

Wow!

Thanks for your quick and thorough reply with a lot of actionable information, @mmoskal!

Just started programming a little my self, and even though I have no realistic hopes of solving this, it’s absolutely an interesting enough learning case I’m looking forward to engaging in.

Would the native SDL-based interpreter for MakeCode VM bytecode that you mention be something that could be published on GitHub for the open source community to tinker with?

It’s would no doubt be of interest for the retro gaming enthusiasts! :wink:

Br,
Vegard

It’s here https://github.com/microsoft/pxt-common-packages/tree/master/libs/core---vm and https://github.com/microsoft/pxt-arcade/tree/master/libs/hw---vm

1 Like

Thanks a lot again!

Sorry to bother you, but do I just run the file like ./name_of_game.elf?

Yes. Just run the binary.

Having spent most of the rainy part of today studying MakeCode and trying to get this to work, I’m still not quite there yet, and I am starting to grasp the enormous size of this project… :wink: -Impressive work, and fun and interesting to learn!

After experiencing that the arcade games didn’t compile in my Chromium browser on my RPi4(?), but on every other system, I at least and finally, with the help from Michal above, got the games’ .elf files to run natively. Here’s what I found and I’m still stuck at:

  • Using his link above with any of the 3 RPi(?) device choices or https://arcade.makecode.com/?hw=rpi&compile=rawELF resultet in working .elf executables, but where it was only possible to configure functioning keyboard buttons, but not gamepad buttons in /sd/arcade.cfg.
  • Using the beta link https://arcade.makecode.com/beta/?hw=rpi&compile=rawELF resulted in running .elf files, but without any working keyboard or gamepad keys.
  • Both regular and beta versions had to be run with sudo and when quitting with either the exit button or kill -INT they did not exit back to the command line. Everything froze and I had to kill -9 the running process and the calling bash process to remove the hanging game graphics from the screen. Played around with xinit, but this resulted in the opposite: This time I was able to quit the games with the exit button, but there was no picture, as Michal also hinted to above.

I’m pretty sure I got the /sd/arcade.cfg, right with the keyboard on event9 and gamepads on event5 and 13, respectively on my system. The game controllers work in evtest and on everything else.


Anyone who has had similar experiences and found solutions for gamepad bindings and graceful exits from the games on Raspbian?

And is it possible(with similar URLs or otherwise) to compile and download from a browser the above mentioned VM bytcode files to be used with the native SDL-based interpreter?

Hi again,

I found the permission issues(chown and chgrp to pi for game .elf file and /sd/arcade.cfg) that forced me to run games with sudo, and a way to execute the game .elf from the console so that the exit button worked(exec ./game.elf).

However, I still can’t figure out why my controllers, which successfully send evdev events on /dev/input/event5 and 13, over USB and Bluetooth, respectively, don’t work, but only similar keyboard events, both over USB and Bluetooth, seem to work fine.

Example of arcade.cfg for PS3 controller that does not work in the game, but with button codes successfully gotten from evtest:

SCAN_CODES=/dev/input/event13
BTN_LEFT=546
BTN_RIGHT=547
BTN_UP=544
BTN_DOWN=545
BTN_A=304
BTN_B=305
BTN_RESET=314
BTN_EXIT=315
BTN_MENU=316

Any help to solve this last piece of the puzzle will be greatly appreciated!

Br,
Vegard

Keep digging! We’d love to compile all your findings into a guide on how to use any pi as a arcade controller.

1 Like

There’s this test in the code:

    for (int i = 0; i < rd / (int)sizeof(struct input_event); i++) {
        if (ev[i].type == 1 && ev[i].code < sizeof(pressedScanCodes))
            pressedScanCodes[ev[i].code] = ev[i].value;
    }

The pressedScanCodes is currently 256 bytes big, so this is one problem. We can bump it to a thousand no problem. Is the type on events 1 (and value 0/1 for released/pressed) ?

1 Like

Thanks for your quick reply, Michal!

Yes, I believe the type on events is 1, with 0/1 for released/pressed.

Here’s the ouput of evtest for the pressing and releasing of the X/South button:

Event: time 1594655068.930813, type 4 (EV_MSC), code 4 (MSC_SCAN), value 9000f
Event: time 1594655068.930813, type 1 (EV_KEY), code 304 (BTN_SOUTH), value 1
Event: time 1594655068.930813, -------------- SYN_REPORT ------------
Event: time 1594655068.965941, type 4 (EV_MSC), code 4 (MSC_SCAN), value 9000f
Event: time 1594655068.965941, type 1 (EV_KEY), code 304 (BTN_SOUTH), value 0
Event: time 1594655068.965941, -------------- SYN_REPORT ------------

Hi @mmoskal,

I hope you’ve had a refreshing summer vacation!

From your appreciated support before the summer, natively compiled MakeCode Arcade games now run great on the Raspberry Pi with regards to using either the keyboard OR a gamepad as controller input.

However, there’s something not quite right with the execution and exiting of the natively compiled .elf files:

When exiting a natively compiled .elf arcade game, the system freezes with the last displayed screen image of the game, and does not exit gracefully and does not return to the calling process.

The only way to exit without rebooting the Pi, is to ssh into it and kill -9 the parent/calling bash process. The symptoms are the same regardless of whether executing in regular ways as pi or sudo, and with fork | exec ./anyarcadegame.elf.

One way to avoid the freeze, is to execute the game with exec ./anyarcadegame.elf. But this is a really bad workaround, since the calling/parent process is here replaced by the game, and on game exit(or rather end of execution) the calling/parent (bash) process is gone, and one has to log in again. When executing like this, the game also exits in the same way when remaining lives = 0 or if you win the game, in stead of resetting/restarting the game, as it should in these circumstances.

Could you please have a quick look at the exit code/conditions for either the (native) compiler process or the natively rpi compiled elf files? There seems to be something wrong or not fully in compliance with how most other executables handles exit.

Or maybe there are other ways to execute files in Linux/Raspbian that I don’t know of and that might work?

UPDATE:
Not sure if this helps, but ps afx (process tree) from the most recent execution shows:
PID TTY STAT TIME COMMAND
1157 tty1 S 0:00 \_ -bash
1746 tty1 Zl+ 0:05 \
_ [arcade-jumpy-pl]

On attempts to exiting the game with the assigned exit button or through the in-game menu exit option, process 1746 is killed, but 1157 remains with the last displayed game image displayed in a frozen state with the whole system and input peripherals frozen and unresponsive.

With it seems that the game process 1746 already is dead/a zombie process, event though the game is running fine until I attempt to exit, and thus cannot be killed without killing the parent process?

UPDATE2:
Following the execution of MakeCode arcade games using top, I observe that the game PID switches status Sl+ (interruptible sleep, foreground process group and multi-threaded) to Zl+ (Zombie, multi-threaded and foreground) only after pushing the A button until the introduction screens are finished and what seems to be when the actual gameplay or maybe the game.onUpdate() function/loop starts…

UPDATE3:
If I execute ./anyarcadegame.elf via ssh from TTY pts/0, I can play the game locally on tty1, but the shell command prompt and letters from key presses appear in the background of the game framebuffer. However, when exiting the game from tty, nothing hangs on either pts/0 or tty1 except the last displayed image from the game in the framebuffer, and the game process is terminated successfully on pts/0. On tty I’m now able to clear this framebuffer using the clear command, since neither the system nor keyboard hangs when executing from pts/0, like it always does when executing directly from tty1. -Really stuck here on getting anyarcadegames.elf files exiting gracefully and returning control to the parent shell process, like for any other executable files on my Pi systems(tested on RPi 3 and 4).

Br,
Vegard

It seems that the game exits, but it leaves keyboard in some sort of raw state, is that right?

The control.reset() on linux will try to start the game again. You can try calling control.panic() and see if that exits the game (this works by sending SIGTERM to the game process).

Another kink is that all games write their PID in /tmp/pxt-pid. When a game starts, it tries to kill any existing game.

@mmoskalwe should map a keyboard key to panic out of the game or add an custom entry in the menu. Sounds like we are very close!

@Vegz78 can we work with you to create a guide out of your adventures?

Thanks for your quick reply, @mmoskal!

Sorry for all the text above from all my updates while studying the issue, which made the description of the symptoms unclear.

  1. When running the game from the local console, tty1, in a bash shell, the game itself runs fine, with keyboard controls, reseting/restarting and everything, even though the game process turns zombie/defunct(first/main light weight process of 8 LWP, the other 7 seem normal).

  2. When exiting the same already running game in however way(in-game options or kill -9(kill -INT or -TERM does not work) command from ssh, or any keyboard shortcut) the game process dies and is reaped, but control/session is not handed back to the calling parent bash process at tty1, which:
    -still has framebuffer filled with the last frozen image of the game,
    -has no visible command prompt or response to remote commands to the console,
    -local keyboard is unresponsive

  3. The only way I’ve found to regain control of the tty1 console is to issue a reboot or kill the running bash/parent process(requiring new login), or rebooting using CTRL+ALT+DEL, which for some reason works for rebooting on my systems…

I’m unfortunately not able to determine whether the keyboard is in a sort of raw state, nor understand how to call control.panic(), and even less, as the game process actually already is exited/dead, but it’s the parent/calling bash process which seems to hang(frambuffer, keyboard etc.) and not regain control/session after the game process is gone…

@peli: I would be happy to create a guide together with you when it’s possible to exit the native MakeCode arcade games gracefully back to the calling process, like a (bash) shell, emulationstation etc. I assume having to reboot the system or ssh into the system, killing the calling/parent process and logging in again after every gameplay is of limited interest for the greater public. But I think you’re right, that you are very close to a great functioning native solution, as soon as it’s possible to exit the games in a normal/controlled fashion.

@mmoskal: I would also be happy to help you compile and testrun new native arcade games, like we did with the gamepad control issue. But I’ve for the moment exhausted my attempts to run the game in alternative ways in Raspbian to allow for exit back to the calling/parent shell process, and where to look in the compiler/source code to hunt down the error.

Br,
Vegard

Anyone who knows if there are similar web links as above with tags ?hw= and ?compile= for compiling natively and testing on a Linux PC instead of the Rpi, or maybe even a Windows PC?

I’ve got the native elf games working on a Raspberry Pi Zero with a GPi case. I’m using xboxdrv to map the controller to keyboard events and have a made a Python/Curses menu to select which game to play, which calls os.system() to run the game.

However, about 50% of the time I’m having the same problem with the screen freezing after a game has exited. Control does seem to pass back to the calling process because the Python menu works and you can select and run another game (although you can’t see what you’re doing), but the screen stays frozen until the new game starts.

I can’t seem to reproduce the problem consistently though. Sometimes it works, sometimes it doesn’t. Happens on all games at some point.

Looking at the posts above, I might just write something that kills the process in /tmp/pxt-pid once the game has finished? It’s not neat, but it should probably work.

Will be following this thread with interest!

I just submitted an issue about this on GitHub and will be happy to hear back from @mmoskal and/or @peli and try to help when/if they get the time to look at it:

Thanks for adding this to Github @Vegz78. Would be good to see a fix.

From what you’ve reported, it looks like my idea of killing the process in my menu software isn’t going to work. Strange that it only happens some of the time on my setup, and consistently on yours.