Skip to content

Media Engine LLE: add homebrew-focused ME support#21554

Open
frangarcj wants to merge 6 commits intohrydgard:masterfrom
frangarcj:pr/media-engine-lle-homebrew-main
Open

Media Engine LLE: add homebrew-focused ME support#21554
frangarcj wants to merge 6 commits intohrydgard:masterfrom
frangarcj:pr/media-engine-lle-homebrew-main

Conversation

@frangarcj
Copy link
Copy Markdown

@frangarcj frangarcj commented Apr 14, 2026

This adds homebrew-focused Media Engine LLE support to PPSSPP.

The goal of this branch is to make ME bare-metal homebrews usable without disturbing the main CPU JIT or the existing execution model. The implementation keeps the ME isolated in its own state and scheduler path, adds the missing ME-side hardware behavior needed by real homebrew, and wires it into interpreter, IR, and native execution paths.

Main pieces included in this PR:

  • Add isolated Media Engine CPU state and execution flow.
  • Implement ME boot/reset handling, shared RAM access, and key ME MMIO behavior.
  • Add SC->ME and ME->SC soft interrupts.
  • Add ME exception/ERET handling, CP0 Count/Compare timer behavior, and interrupt delivery.
  • Add ME scheduling, spinwait detection, and per-core timing/accounting fixes.
  • Add ME IR execution and native ARM64 execution support without patching EMUHACK opcodes into RAM.
  • Add an initial x64 native ME backend following the same non-patching model.
  • Add DMACplus support needed by ME homebrew.
  • Add ME GE list feeding support.
  • Add ME views to the ImGui debugger.

A few implementation details were important for keeping this upstreamable:

  • The main CPU JIT remains the only owner of normal JIT state. The ME uses separate IR/native resources.
  • ME-native code does not patch PSP RAM with EMUHACK opcodes.
  • ME-sensitive hardware accesses fall back conservatively where needed.
  • The ME null-return case is handled as a local ME stop instead of a global runtime error.

About autotests / CI:

PPSSPP CI currently runs python test.py -g --graphics=software, which only covers the tests_good list in test.py. The existing pspautotests/tests/me/me test is a legacy interactive sample rather than a self-terminating stdout autotest, and it is also explicitly ignored today. Because of that, this PR does not add ME coverage to the standard pspautotests CI path yet. I plan to handle that as a separate pspautotests/update-submodule follow-up once there is a proper ME autotest suitable for the headless harness.

Testing performed on this branch:

  • Full rebuild on macOS ARM64.
  • Quick ME homebrew matrix on me-core=0, me-core=2, and me-core=3:
    • me-soft-interrupt
    • me-minimal-handler
    • me-spinlock
    • psp-me-bench-custom
    • me-dmacplus-drawing-transfer
    • me-feed-graphics-engine

All of the above passed on the ARM64 host used for development.

Note on x64:

The initial x64 native ME backend is included in this branch and compiles cleanly, but I have not yet runtime-validated it on a real x64 host. The ARM64 path and the interpreter/IR paths have been validated with the test matrix above.

image

Add MIPSDebugInterface for the Media Engine (debugMe) alongside the
existing debugr4k for the main CPU. The CPU menu now has a 'Media
Engine' section with separate windows:
  - ME Debugger (disassembly view)
  - ME GPR regs
  - ME FPR regs

These can be opened alongside the main CPU windows simultaneously.
DrawGPRs/DrawFPRs/DrawVFPU accept optional title/openFlag parameters.
ImDisasmWindow::Draw accepts optional title/openFlag for reuse.
@hrydgard
Copy link
Copy Markdown
Owner

This is very cool, thanks for doing this!

I'm targeting getting this in after 1.20.4, which is kind of a smaller bugfix/UI release.

Will take a little while to review as well.

There are some CI errors but they should be fairly easily resolved, I think. Let me know if you have any issues.

J_CC(CC_Z, bail, true) passed a FixupBranch as the second arg,
but the x64 emitter only accepts (CCFlags, bool) or (CCFlags, const u8*, bool).
Use a second FixupBranch bail2 and resolve both at the bail target.
Add a 'Media Engine Core' dropdown in Settings > Developer Tools with
options: Disabled / Interpreter / IR Interpreter / Native JIT (recommended).

The Dynarec/JIT option (value 1) is hidden since it's not a valid ME
backend. Native JIT is hidden on unsupported architectures.

Default changed from IR Interpreter to Native JIT.
@hrydgard
Copy link
Copy Markdown
Owner

By the way, it's great that you're relying on the IR JIT infra. The old non-IR JITs are going away in the future, likely for 1.21.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants