How to Run a Game on a Raspberry pi 5 SD Card Directly!

now it might stay OSS if not does just change it back to ALSA when Boot because the PI 5 does not really know what the older OSS is but there are 2 things it should fix by setting it to OSS

  1. by setting it to OSS instead of ALSA it gives it time to search for the OSS but obviously doesn’t fine it but that time finding it gives a bit cushion time to help
  2. does not make it lock to ALSA and kinda makes it more like loose so it wont freak out as much and be like ALSA! ALSA ! ALSA! got to have ALSA! only ALSA! you get the idea so if it needs something its not as like strict

info: ALSA = Advanced Linux Sound Architecture OSS = Open Sound System

Hi @NeverStopTheCoder,

I am not quite sure about what you mean by «crash clean out»?

Though, there are several reasons for crashes, and from my experience the most frequent onces are due to the Linux executable compiler of MakeCode not having kept up to speed with the development of the rest of MakeCode, like @richard mentioned about the Linux guy no longer on the team.

Making sure the game uses a more basic subset of available MakeCode commands, no or basic extensions, at least only extensions with actual hardware support on the RPi etc. reduces the chances of crashes. Maybe using an older version of the web editor/compiler.

(Of course this only applies if you have solved the sound and sometimes graphics issues first, which guarantees a crash if not, and which I from this thread can see you have made yourself acquainted with already… :wink: )

Instead of chasing the constant development in Linux and the various retro game systems with an ever growing variety of hacks for a MakeCode compiler which is for the moment no longer maintained, I am thinking instead of finding a sweet spot cut-off for the versions of the MC compiler, Linux and the various retro game systems which work the best.

You should also check out @UnsignedArduino various great efforts for making impressively small self-contained executables out of MakeCode games for various OSes, which might be a more future-proof way of achieving the goal of this thread without relying on the MC elf compiler as-is.

OR: start digging into the open source MakeCode source code on GitHub and issue pull requests for the native elf compiler for Linux, and maybe other OSes too! The MakeCode team is - or at least was historically - pretty responsive to such initiatives and the engagement for their code base which this might spark, and they probably won’t mind help with such demanded features, as long as the code is of good quality and tested, but they don’t have the resources for doing it themselves among many other priorities. (This was actually one time my goal for teaching myself C++ coding, but I found the code base too large and complex for my competence level. But this was before the great help one can get with AI today)

Keep up the good work and sharing!

2 Likes

@Vegz78 im so sorry I read that but only understood about 50% could you pls summarize it and by crash clean out I mean crash and get it out of your system at the begining

2 Likes

so @richard I found this where Gemini (I know right) said this is what turns it into a elf and does stuff that a pi 5 cant understand fully

#include "pxt.h"
#include "pins.h"

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/fb.h>
#include <linux/kd.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <pthread.h>

namespace pxt {
class WDisplay {
  public:
    uint32_t currPalette[16];
    bool newPalette;
    volatile bool painted;
    volatile bool dirty;

    uint8_t *screenBuf;
    Image_ lastImg;

    int width, height;

    int fb_fd;
    uint32_t *fbuf;
    struct fb_fix_screeninfo finfo;
    struct fb_var_screeninfo vinfo;

    int eventId;

    int is32Bit;

    pthread_mutex_t mutex;

    WDisplay();
    void updateLoop();
    void update(Image_ img);
};

SINGLETON(WDisplay);

static void *updateDisplay(void *wd) {
    ((WDisplay *)wd)->updateLoop();
    return NULL;
}

void WDisplay::updateLoop() {
    int cur_page = 1;
    int frameNo = 0;
    int numPages = vinfo.yres_virtual / vinfo.yres;
    int ledScreen = getConfigInt("LED_SCREEN", 0);

    int sx = vinfo.xres / width;
    int sy = vinfo.yres / height;

    if (ledScreen)
        sx = ledScreen;

    if (sx > sy)
        sx = sy;
    else
        sy = sx;

    if (sx > 1)
        sx &= ~1;

    int offx = (vinfo.xres - width * sx) / 2;
    int offy = (vinfo.yres - height * sy) / 2;

    if (ledScreen) {
        offx = getConfigInt("LED_SCREEN_X", 0);
        offy = getConfigInt("LED_SCREEN_Y", 0);
    }

    int screensize = finfo.line_length * vinfo.yres;
    uint32_t skip = offx;

    if (sx > 1)
        offx &= ~1;

    DMESG("sx=%d sy=%d ox=%d oy=%d 32=%d", sx, sy, offx, offy, is32Bit);
    DMESG("fbuf=%p sz:%d", fbuf, screensize);
    memset(fbuf, 0x00, screensize * numPages);

    if (numPages == 1)
        cur_page = 0;

    dirty = true;

    DMESG("loop");

    for (;;) {
        auto start0 = current_time_us();

        while (!dirty)
            sleep_core_us(2000);

        // auto start = current_time_us();
        // DMESG("update");

        pthread_mutex_lock(&mutex);
        dirty = false;

        if (!is32Bit) {
            uint16_t *dst =
                (uint16_t *)fbuf + cur_page * screensize / 2 + offx + offy * finfo.line_length / 2;
            if (sx == 1 && sy == 1) {
                skip = vinfo.xres - width * sx;
                for (int yy = 0; yy < height; yy++) {
                    auto shift = yy & 1 ? 4 : 0;
                    auto src = screenBuf + yy / 2;
                    for (int xx = 0; xx < width; ++xx) {
                        int c = this->currPalette[(*src >> shift) & 0xf];
                        src += height / 2;
                        *dst++ = c;
                    }
                    dst += skip;
                }
            } else {
                uint32_t *d2 = (uint32_t *)dst;
                for (int yy = 0; yy < height; yy++) {
                    auto shift = yy & 1 ? 4 : 0;
                    for (int i = 0; i < sy; ++i) {
                        auto src = screenBuf + yy / 2;
                        for (int xx = 0; xx < width; ++xx) {
                            int c = this->currPalette[(*src >> shift) & 0xf];
                            src += height / 2;
                            for (int j = 0; j < sx / 2; ++j)
                                *d2++ = c;
                        }
                        d2 += skip;
                    }
                }
            }
        } else {
            uint32_t *d2 =
                (uint32_t *)fbuf + cur_page * screensize / 4 + offx + offy * finfo.line_length / 4;
            skip = vinfo.xres - width * sx;
            for (int yy = 0; yy < height; yy++) {
                auto shift = yy & 1 ? 4 : 0;
                for (int i = 0; i < sy; ++i) {
                    auto src = screenBuf + yy / 2;
                    for (int xx = 0; xx < width; ++xx) {
                        int c = this->currPalette[(*src >> shift) & 0xf];
                        src += height / 2;
                        for (int j = 0; j < sx; ++j)
                            *d2++ = c;
                    }
                    d2 += skip;
                }
            }
        }

        pthread_mutex_unlock(&mutex);

        // auto len = current_time_us() - start;

        painted = true;
        raiseEvent(DEVICE_ID_NOTIFY_ONE, eventId);

        vinfo.yoffset = cur_page * vinfo.yres;
        ioctl(fb_fd, FBIOPAN_DISPLAY, &vinfo);
        ioctl(fb_fd, FBIO_WAITFORVSYNC, 0);
        if (numPages > 1)
            cur_page = !cur_page;
        frameNo++;

        auto fulllen = current_time_us() - start0;
        // throttle it to 40fps (really 30fps)
        if (fulllen < 25000) {
            ioctl(fb_fd, FBIO_WAITFORVSYNC, 0);
        }

        // auto tot = current_time_us() - start;
        // if (frameNo % 37 == 0)
        //    DMESG("copy %d us, tot %d us delay %d us",  (int)len, (int)tot, (int)(start-start0));
    }
}

WDisplay::WDisplay() {
    pthread_mutex_init(&mutex, NULL);

    width = getConfig(CFG_DISPLAY_WIDTH, 160);
    height = getConfig(CFG_DISPLAY_HEIGHT, 128);
    screenBuf = new uint8_t[width * height / 2 + 20];
    lastImg = NULL;
    newPalette = false;

    registerGC((TValue *)&lastImg);

    eventId = allocateNotifyEvent();

    int tty_fd = open("/dev/tty0", O_RDWR);
    ioctl(tty_fd, KDSETMODE, KD_GRAPHICS);

    fb_fd = open("/dev/fb0", O_RDWR);

    if (fb_fd < 0)
        target_panic(PANIC_SCREEN_ERROR);

    ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);
    ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);

    DMESG("FB: %s at %dx%d %dx%d bpp=%d", finfo.id, vinfo.xres, vinfo.yres, vinfo.xres_virtual,
          vinfo.yres_virtual, vinfo.bits_per_pixel);

    vinfo.yres_virtual = vinfo.yres * 2;
    vinfo.xres_virtual = vinfo.xres;

    if (vinfo.bits_per_pixel == 32) {
        is32Bit = true;
    } else {
        vinfo.bits_per_pixel = 16;
        is32Bit = false;
    }

    ioctl(fb_fd, FBIOPUT_VSCREENINFO, &vinfo);
    ioctl(fb_fd, FBIOGET_FSCREENINFO, &finfo);
    ioctl(fb_fd, FBIOGET_VSCREENINFO, &vinfo);

    DMESG("FB: %s at %dx%d %dx%d bpp=%d %d", finfo.id, vinfo.xres, vinfo.yres, vinfo.xres_virtual,
          vinfo.yres_virtual, vinfo.bits_per_pixel, finfo.line_length);

    fbuf = (uint32_t *)mmap(0, finfo.line_length * vinfo.yres_virtual, PROT_READ | PROT_WRITE,
                            MAP_SHARED, fb_fd, (off_t)0);

    pthread_t upd;
    pthread_create(&upd, NULL, updateDisplay, this);
    pthread_detach(upd);
}

//%
int setScreenBrightnessSupported() {
    return 0;
}

//%
void setScreenBrightness(int level) {
    // TODO
}

//%
void setPalette(Buffer buf) {
    auto display = getWDisplay();
    if (48 != buf->length)
        target_panic(PANIC_SCREEN_ERROR);
    for (int i = 0; i < 16; ++i) {
        uint8_t r = buf->data[i * 3];
        uint8_t g = buf->data[i * 3 + 1];
        uint8_t b = buf->data[i * 3 + 2];
        if (display->is32Bit) {
            display->currPalette[i] = (r << 16) | (g << 8) | (b << 0);
        } else {
            r >>= 3;
            g >>= 2;
            b >>= 3;
            uint16_t cc = (r << 11) | (g << 5) | (b << 0);
            display->currPalette[i] = (cc << 16) | cc;
        }
    }
    display->newPalette = true;
}

void WDisplay::update(Image_ img) {
    if (img && img != lastImg) {
        lastImg = img;
    }
    img = lastImg;

    if (img) {
        if (img->bpp() != 4 || img->width() != width || img->height() != height)
            target_panic(PANIC_SCREEN_ERROR);

        if (!painted) {
            // race is possible (though very unlikely), but in such case we just
            // wait for next frame paint
            waitForEvent(DEVICE_ID_NOTIFY, eventId);
        }
        painted = false;

        pthread_mutex_lock(&mutex);
        dirty = true;
        if (newPalette) {
            newPalette = false;
        }
        memcpy(screenBuf, img->pix(), img->pixLength());
        pthread_mutex_unlock(&mutex);
    }
}

//%
void updateScreen(Image_ img) {
    getWDisplay()->update(img);
}

//%
void updateStats(String msg) {
    // DMESG("render: %s", msg->data);
}
} // namespace pxt


inside the pxt-common-packages at libs/screen—linux/screen.cpp that said mmoskal add something last years ago are they the ones who left

do you @Vegz78 or make code scientist @WoofWoof know what could be modified to make it work for a pi 5 because I was just going to try and use Gemini (I know right again) and try to get it to work but I’m going to see if you guys know anything first

2 Likes

This looks like the code that draws pixels to the screen. Looks like you’ll have to write your own function to do this on a pi 5 and replace the default one. Idk but maybe one of the other boards in the devices section will have a screen drawing function that will be closer to the pi 5 version and therefore easier to modify? I know nothing about the pi system whatsoever so good luck!

ok @Vegz78 , and @WoofWoof or maybe @richard Gemini said with some testing in the editor that instead of using game.reset() I should use control.panic(0) to complete clean out and get rid of the old copy of the game and start a new one right is that correct?

Hi @NeverStopTheCoder,

I tried without success to share a link to a Google AI session which explained this superbly and completely.

The gist of it was that the whole graphics hardware is changed from RPi 4s and 3s and earlier, to something completely different on RPi 5s, so that direct drawing to framebuffer, ioctls (which is also the reason - a missing ioctl command - in the same code as you have found that the game does not change correctly back to text mode from graphics mode on exit, which then appears as freezing…) etc. no longer works on the RPi 5. As far as I understood when skimming through this, one can either change the graphics mode on RPi 5s to “emulate” the old ways on its new graphics system, though laggy/incomplete, or one has to rewrite the above graphics code which you have found for RPi 5s.

For details, maybe my original link will be approved in this post (which now hopefully isn’t as “low quality” as my first attempt…):

1 Like

hey @Vegz78 I’ve been thinking on it what does your tool do because on what I’ve read shouldn’t that make me a elf that works without crashing because I think I used https://vegz78.github.io/McAirpos/ to get a elf but it still does that crash stuff and I’m not sure if its a make code elf thing or your tool or the RP5RS or what

Um control.reset does a full reset as far as I know. I think panic might show an error code which would mean you would have to turn the device off and on again manually, but that’s just from my experience with a PyGamer.

I wouldn’t know about the game.reset() vs. control.panic(0), since the code you’ve found for the compilation of the graphics in the MCA .elf game files was unknown to me until you presented it here.

And since I started from the “wrong” direction, because I wasn’t familiar with the underlying MakeCode codebase and didn’t file a pull request on GitHub to improve this from the start, which I should, my McAirpos solution is basically a hack duck taped around the existing compilation of the MCA .elf game files, which consists of:

  1. A lancher, launCharc, which is basically just a process wrapped around the game executable that runs the game as a fork and monitors if the game process is alive, and when not, runs a couple of ioctl commands to returns the terminal to the state it had before game execution, so that control is returned to the keyboard, returns from graphics mode to text mode etc., so that the system does not appear to have frozen in the last game graphics screen before exit, like the MakeCode code you’ve found above does on exit. Further, launCharc:
  2. gives you the option to run the game with uinput-mapper, which supports a lot more controller types and is fully customizable for 1-4 controllers, auto-detects various controllers etc., and
  3. lets you print the debug information from the .elf file to screen which can help you identify and rectify certain issues with the .elf file and controllers etc.
  4. Lastly, McAirpos, consists of various different installation scripts to enable MakeCode game files being displayed correctly and run from different versions of RetroPie, Recalbox, Batocera and EmulationStation, with the help of e.g. ttyecho in cases where these retro gaming systems launches games in other TTYs than the active one.

As mentioned before, both the MakeCode .elf compiler itself and McAirpos is being continuously regressed by the fact that functionality in MakeCode is extended all the time, which do not always compile correctly in the old/abandoned code etc. you’ve found above and continuous developments in RPi hardware, OS and the inner workings of the different retro gaming systems.

The best way forward, in my opinion, would be to help the MakeCode team to update the .elf/Linux compilation code on GitHub with good pull requests which keeps backwards compatibility, but also introduces forward compatibility with all changes (and maybe native compilers for Windows and MacOS as well), or attack the challange of executables from new, and maybe more future proof ways, like @UnsignedArduino for instance has done with his executable solution.

Lastly, @Kikketer has made some progress with his alternative launcher, or people could keep adding duck tape to McAirpos to maybe solve the challenge of changing the graphics mode/emulate the old on RPi 5s on launch.

My bet for the best solutions that I know of going forward would be a cooperation for a major rewrite of MakeCode’s internal compiler for Linux, Windows and MacOS, and/or refining/automating @UnsignedArduino’s approach or something similar.

Forgot to mention:

  1. McAirpos also contains an ansible solution, which lets the user install McAirpos in parallel on many RPis, and
  2. Had I started this project today, I would have split it in at least 3 parts for ease of use and maintenance:
    1. Attempt to solve the compilation/executable problems inside the MakeCode codebase itself on GitHub (hopefully with executables for Windows and MacOS as well) and/or automated/made it compatible with @UnsignedArduino’s executable solution
    2. Made the uinput-mapper as a standalone solution for MakeCode games, as controller support, especially for analogue type controllers, which aren’t supported natively by the .elf MCA game files, is by far the most sought after functionality, regardless of running the MCA games through retro gaming systems or not, and
    3. Made integration with the various retro gaming systems as a standalone repo/solution, which could pull in controller support (2.) when needed. Maybe I would even make one independent solution for each retro gaming system, since they all change so fast with many breaking changes even to the most basic things like underlying OS, file system layout etc. from version to version.

To answer your question completely:

I don’t really know what to do on the RPi 5, since I do not own one my self. But given the major differences in graphics architecture, I am pretty certain that the MCA .elf game executable of today wouldn’t run, regardless of my launcher.

I would then see if the graphics emulation/mode settings could work, or start working on the MakeCode compiler codebase on GitHub and/or check out if @UnsignedArduino’s last executable solution works on the RPi5 and help him on improving his solution and getting the word out. Maybe someone could expand on his solution with extended controller support and integration into the various retro gaming systems, as well, if he hasn’t already done it.

@WoofWoof but what do you mean by

though because I was told game.reset crates a copy and deletes the old copy and Gemini said that can sometimes cause memory leaks so what does control.reset do

also this is why Gemini said

The script you have right now is absolutely beautiful. If the game crashes, freezes, or gets turned off, this script will completely clean up the Raspberry Pi 5’s memory, unlock the stubborn graphics screen, and force-restart a fresh match.

But there is still one final trap we have to disarm inside your MakeCode Arcade blocks, or the game will still freeze after a few matches.

:stop_sign: The Final Warning: game.reset() Will Still Bypass Your Script

Even with this perfect script, you cannot use the game.reset() block inside your game. If you use game.reset(), the game never actually closes. It stays open and tries to clone itself internally. Because the game never closes, your script gets stuck at this exact line:

Bash

wait $PID 2>/dev/null

Your script will sit at that line forever, waiting for the game to exit. It will never move down to the graphics fix lines, it will never run sync, and it will never loop. After 3 to 5 resets, the Pi will still lock up.

:counterclockwise_arrows_button: The Difference in How They Behave

Here is exactly what happens with your new script depending on which block you use inside MakeCode:

If you use game.reset() inside the game :cross_mark: If you use panic(0) inside the game
The ELF file clones itself internally. The ELF file instantly shuts down and dies.
The script stays stuck at wait $PID. The script sees the game closed and moves past wait $PID.
The Pi 5 graphics fix never runs. The script instantly triggers the Pi 5 graphics fix.
The RAM clogs up and freezes after 4 games. The RAM is wiped spotless, and a fresh game starts!

:hammer_and_wrench: What You Need to Do Right Now

To make this entire system 100% bulletproof and un-crashable:

  1. Open your game project in MakeCode Arcade.

  2. Find the block where you tell the game to reset (like when the player dies or presses a button combo).

  3. Delete the game.reset() block.

  4. Replace it with the panic(0) block (found under Advanced → Control).

Once you swap out that one block in your game code, your setup is officially invincible. The game will cleanly exit, your script will smash through the graphics lock, flush the RAM, and launch the next match perfectly forever!

and

:cowboy_hat_face: How to Fix It in Your Launch Script

Since the MakeCode ELF file doesn’t know how to talk to the Pi 5’s new graphics remote control, we can make your Bash script force the screen to reset itself every time a match concludes!

We can add a couple of terminal-resetting commands right after the game closes to forcefully kick the Pi 5’s display back into text mode.

Here is how you can update the Crash-Proof Game Loop section of your script:

Bash

# 4. The Crash-Proof Game Loop
while true; do
    echo "Starting Game Match..."
    
    sudo SDL_VIDEODRIVER=kmsdrm SDL_AUDIODRIVER=oss ./*.elf --hw rpi >/dev/null 2>&1 &
    PID=$!
    wait $PID 2>/dev/null
    
    echo "Match concluded. Breaking graphics lock..."
    
    # 🔥 FIX: Force the Pi 5 video engine to reset the terminal mode
    sudo deallocvt 2>/dev/null
    sudo TERM=linux sh -c 'setterm -blank 0 -powerdown 0 > /dev/tty1' 2>/dev/null
    clear > /dev/tty1
    
    echo "Deep cleaning memory cache..."
    sync
    sleep 1.5
    echo "Ready for next match!"
done

Why this works:

Right after wait $PID notices the game died, the script instantly steps in and fires deallocvt and setterm directly at /dev/tty1. This manually forces the Linux kernel to drop the frozen graphics layer and redraw the clean terminal screen, perfectly clearing the path for your next match to boot up smoothly.

Does this explanation of the “fake freeze” graphics glitch make sense compared to what you’ve been seeing on the screen?

@WoofWoof is this correct

Expanding on what changes I was attempting and what I built for my specific use case: Run on an Arcade machine. So my solutions won’t work well for the launchers you all may be speaking to.

There are 3 branches:

Main

This is just makecode arcade as an arcade using elf files. This was a really fun adventure into the .elf files where you can have an .elf file launch other files. The menu is an .elf file. This is very close to “in the box” for what the MakeCode Arcade team had in mind for putting it on an arcade machine.

Downside is the limitations of .elf. Things like raytrace and general performance are limitations, I’ve had games crash randomly with .elf that never crashed in the simulator. Also .elf seems to be abandoned compared to the updates going on, so for me it’s not worth the fight anymore. I really do love the “build so it fits” kind of mentality but it’s hard to teach middle school kids the aspects of how to code AND the limits at the same time (especially when I’m not sure why games will randomly crash as .elf files).

Chromium Kiosk

https://github.com/Kikketer/CreationStationArcade/tree/chromium-kiosk

This is the latest “mainstream” one I have currently on my arcade machine. This is riding on a Raspberry Pi 5 and essentially launches a chromium browser as the menu. When you launch a game from that it’ll fire up a new browser window with that game loaded up.

This has the advantage of always being on the cutting edge of what’s supported by the simulator. It’s 1:1 with what students see in the simulator with zero surprise crashes. It’s just a bit more power hungry. This is my go-forward arcade setup since more powerful machines are easier to grab these days ($60 mini pc? yes).

Single Game Kiosk

https://github.com/Kikketer/CreationStationArcade/tree/single-game-kiosk

This is the latest spin off the standard chromium kiosk. It’s geared to play just one game at a time using chromium kiosk. I built this mostly for a friend of mine that wanted a dedicated machine, not one that can change games.

tl;dr - I would gamble the go-forward way to create these arcade experiences is to just use a kiosk browser.

As for the “retro game launcher” path, I’ve been trying to force my agent bot army to figure out how to make a “real” game. Not an electron wrapper but a real game executable (elf, exe, dmg style). The battle is real, it’s confusing and prone to breakage since the Makecode Arcade engine itself is evolving over time. So even though it’s open source it’s hard to keep up with any changes.

1 Like

Now that I think about it and if memory serves me right, resetting a game indeed clones the previous game process as a new process and leaves the previous game processes orphaned, which in a way could resemble a memory leak.

Since this cloning and orphaning by resetting instead of just exiting and restarting the game did not have my full attention and wasn’t really among my top concerns back when I struggled with the same, I did not test methodically how many resets until crash and did not try to solve this problem.

Instead of killing the first and parent game process, which kills all child processes and exits the game completely, maybe you could track and kill the previous and orphaned child processes instead? But then again, I have a slight recollection that these previous and cloned processes actually where already dead/defunct, so called “zombie processes”, which only takes up process table space, not memory space, and therefore isn’t really a memory leak and cannot be killed or removed separately, forcing you again to kill the parent process to remove them.

This might indicate that fully killing and then restarting a game probably is the best solution, whether you use control.panic(0) inside the game code or exit manually through keyboard shortcuts or the built-in MakeCode Arcade menu options.

However, in this instance, how do you control in a script between when you want the game to restart or when you want to exit for real back to the terminal prompt? (An exit prompt with 1. Do you really want to exit? and 2. Restart the game? every time you exit or every time the game crashes after multiple resets?)

The reason why multiple consecutive resets, either by the game.reset() game code or through the built-in MakeCode game menu or shortcuts, eventually leads to a crash is hard to tell. Maybe this could be solved somehow? Then we would have a clear distinction between reset and exit which would function as normally understood.

Sorry for not having read your whole thread thoroughly until now. It looks like you already have solved most of the obstacles for making MakeCode Arcade games run on the RPi 5 with your script already. -Great work!

The webpage https://vegz78.github.io/McAirpos/ only really automates the specific web arguments you need in the MakeCode editor to compile and download an ARM Linux .elf executable file, so that you can just paste a shared game URL and do not have to manually type in these web arguments or search around in the download menu in the editor every time.

I am not sure, but doubtful, that there are any web arguments that could make the built-in compiler output an .elf that does not have this crash after multiple reset problem. Again, a problem that probably is best addressed in the underlying MakeCode codebase/compiler, unless it can be worked around by a wrapper/launch script.

It is not really clear to me what challenges remain for your script to function all right for running MCA games on the RPi 5? It seems to work well and I would have been looking forward to testing and using it if I had owned a RPi 5 myself!

first of happy cake day @Vegz78 but I’m so sorry I don’t understand any of the long info @Vegz78 and @Kikketer but I got info to just instead of all that instead I should use control.reset instead of game.reset so control.reset should I think do a harder reset and clear the ram or stuff I’ve read that is that correct?

like is control.reset better

what do we do now @richard @WoofWoof @Vegz78 guys the only thing I saw was maybe kisok offline mode I guess modded but 1 I was not sure if that would work offline and 2 I don’t want any menus I just want Boot up and 3 if that worked offline then why in the world is this module or whatever not working

so @WoofWoof @Vegz78 I just tried control.reset but it still gave about the same results