Skip to content

Releases: soniciso1/LuaMD

Release list

LuaMD v1.0

Choose a tag to compare

@soniciso1 soniciso1 released this 21 Aug 06:16

Mega Drive / Genesis emulator running as native x86_64 shellcode on PS5,
delivered through Luac0re. No kernel
exploit — everything runs in userland inside the ps2emu sandbox of
Star Wars Racer Revenge.

Sibling to LuaGB, whose PS5 runtime
this reuses.

Credits

  • Clownacyclownmdemu,
    the emulation core, plus the clown68000 and clownz80 interpreters (AGPLv3).
  • GezineLuac0re, the JIT exploit
    and Lua delivery framework this runs on. No Luac0re, no project.
  • egycnq — the savedata write method, which
    is what makes cartridge saves persist, and EmuC0re,
    whose PS5 runtime structure this follows.

Install

Download md.lua below. You need Luac0re already working, with its loader
listening on port 9026.

1. Put your ROMs in the savedata

ROMs are read from a roms/ folder inside the game's savedata container —
the same container Luac0re lives in — and nowhere else.

/savedata0/
    lua/        <- Luac0re (already there, leave it alone)
    roms/       <- CREATE THIS. your .bin / .md / .gen / .smd files
    saves/      <- CREATE THIS, empty. cartridge SRAM lands here
    VMC0.card   <- leave alone
    VMC1.card   <- leave alone
    sce_sys/    <- leave alone

Use any PS5 save manager that can mount and write a savedata image: mount the
save, create roms/ and saves/, copy your ROMs in, then unmount to commit.

Do this with the game closed. Mounting the savedata image while the game is
running desynchronises the game's own mount — directories read back empty and
writes fail.

Alternatively the payload serves FTP on port 1337 while it waits on the ROM
screen and writes straight into the container, so after the initial Luac0re
setup no save manager is needed. With roms/ empty it waits indefinitely; with
ROMs already there it waits a few seconds and moves on.

Watch the space. The container is around 42 MB and the two PS2 virtual
memory cards take 16.5 MB before you start, leaving roughly 24 MB. A Mega Drive
cartridge is 512 KB to 4 MB.

2. Launch the game

Start Star Wars Racer Revenge, then OPTIONS → HALL OF FAME to arm the
Luac0re loader.

3. Send the payload

python md_launcher.py <PS5_IP>

Or send md.lua to port 9026 by any means you already use.

Controls

DualSense Mega Drive
Square A
Cross B
Circle C
Triangle X
L2 / R2 Y / Z
Options Start
L3 Mode
D-Pad D-Pad
L1 back to the ROM picker (saves first)
R1 (hold 1 second) quit

Six-button support is free — games that only understand three never poll for
the rest. R1 requires a deliberate full second held: quitting ends the Luac0re
session and means relaunching the game.

A web controller is also served at http://<PS5_IP>:9030 — touch, keyboard and
Gamepad API. The input source locks to whichever device you press first.

Saving

Cartridge SRAM is written into saves/<rom>.srm inside the savedata container,
so a backup of the save captures your games too. Press L1 to return to the
picker — that commits it. Yanking power will not.

Most cartridges have no battery at all; the load line says which.

Supported

.bin, .md, .gen raw dumps, and .smd (Super Magic Drive), which is
deinterleaved on load.

Not supported: Mega CD, 32X, Sega Pico, save states.

Known limits

  • One payload send per Luac0re session. The emulator takes over the display and
    stops ps2emu's graphics thread, so after it exits the loader cannot serve
    another payload — relaunch the game to send again.
  • Tested against NTSC cartridges. PAL region detection is implemented but has
    not been exercised on hardware.

Licence

AGPLv3, because clownmdemu is. Full source is in the repository, including
the one documented change to upstream (md/source/mega-cd-boot-rom.c — the
Mega CD BIOS array, 135 KB of the core's 190 KB, removed because a
cartridge-only build never maps those addresses and the payload has a hard
256 KB ceiling).