Files
Jorge Feitosa 6f03aa224a Microphone input, optional melonDS DS core and its touchpad stylus (0134, 0135)
From mihawk-99/PS5_RetroArch#53 and #52 (Jorge Feitosa), renumbered
(0131 to 0133 were taken), taken together: #52 fixes the read loop #53
turns on.

- src/microphone_ps5.cpp (0134): a native AudioIn microphone driver,
  the default one, for the first controller's user. It captures only
  while a core has its microphone on, sends silence under the DualSense
  mute, and keeps PCM only in a bounded queue in memory. RetroArch is
  configured with the microphone; the title links a host stub for
  libSceAudioIn's imports.
- 0135: a microphone read that gets no frames returns silence instead of
  looping forever (a paused core, an empty nonblocking device, a failed
  capture).
- tools/build-melondsds.sh: melonDS DS at pinned revisions (git objects
  by SHA), software renderer and a native-memory JIT, staged only with
  PS5_WITH_MELONDSDS=1; DeSmuME stays the DS default. The DualSense
  touchpad drives its stylus as it drives DeSmuME's.

Changed from the pull requests: the README and the 0134 entry describe
what happens, not an opt-in the code never had. RetroArch's microphone is
on by default, as upstream; melonDS DS listens only while its microphone
button is held (its default), and Settings > Audio > Microphone turns it
off for every core. tests/test_microphone_read.py applies the port's
edits to vendor/retroarch itself rather than reading build/ra-conf, which
a tree configured before 0135 would fail. The SwanStation and melonDS DS
title changes are merged into one licence-file rule.

Evidence: tests/test_microphone_ps5.py (the driver against a simulated
AudioIn: lifecycle, mute, input failure); tests/test_microphone_read.py
(it times out with upstream's loop); tests/test_touchpad_stylus.py
(melonDS DS's relative stylus); tools/build-melondsds.sh, core ABI PASS
(25 exports, kernel_web, sha256 b03d4c93...). A title built with both
optional cores: 61 notice parts, check-notices covers every shipped
executable, check-manifest PASS, 78 melonDS DS options in the catalog.
Gates (default build): format, unit (204), build (staged cores reused),
integration, evidence PASS. Console: with this series' deploy.
2026-10-17 21:25:33 -04:00

146 lines
4.9 KiB
Diff

diff --git a/src/ARMJIT_Global.cpp b/src/ARMJIT_Global.cpp
index e4aa42f9..35e7e6cf 100644
--- a/src/ARMJIT_Global.cpp
+++ b/src/ARMJIT_Global.cpp
@@ -1,5 +1,9 @@
#include "ARMJIT_Global.h"
#include "ARMJIT_Memory.h"
+#ifdef __PROSPERO__
+#include <ps5platform/exec.h>
+#include <new>
+#endif
#ifdef _WIN32
#include <windows.h>
@@ -25,7 +29,7 @@ std::mutex globalMutex;
#define APPLE_AARCH64
#endif
-#if !defined(APPLE_AARCH64) && !defined(__NetBSD__) && !defined(__OpenBSD__)
+#if !defined(APPLE_AARCH64) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__PROSPERO__)
static constexpr size_t NumCodeMemSlices = 4;
static constexpr size_t CodeMemoryAlignedSize = NumCodeMemSlices * CodeMemorySliceSize;
@@ -46,7 +50,7 @@ void* AllocateCodeMem()
{
std::lock_guard guard(globalMutex);
-#if !defined(APPLE_AARCH64) && !defined(__NetBSD__) && !defined(__OpenBSD__)
+#if !defined(APPLE_AARCH64) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__PROSPERO__)
if (AvailableCodeMemSlices)
{
int slice = __builtin_ctz(AvailableCodeMemSlices);
@@ -56,8 +60,13 @@ void* AllocateCodeMem()
}
#endif
- // allocate
-#ifdef _WIN32
+ // PS5: the platform owns executable memory; anonymous/heap memory cannot run.
+#ifdef __PROSPERO__
+ void* code = ps5_exec_allocate(CodeMemorySliceSize, reinterpret_cast<uintptr_t>(&AllocateCodeMem));
+ if (!code)
+ throw std::bad_alloc();
+ return code;
+#elif defined(_WIN32)
return VirtualAlloc(nullptr, CodeMemorySliceSize, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#elif defined(APPLE_AARCH64)
return mmap(NULL, CodeMemorySliceSize, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS | MAP_JIT,-1, 0);
@@ -73,7 +82,7 @@ void FreeCodeMem(void* codeMem)
{
std::lock_guard guard(globalMutex);
-#if !defined(APPLE_AARCH64) && !defined(__NetBSD__) && !defined(__OpenBSD__)
+#if !defined(APPLE_AARCH64) && !defined(__NetBSD__) && !defined(__OpenBSD__) && !defined(__PROSPERO__)
for (int i = 0; i < NumCodeMemSlices; i++)
{
if (codeMem == &GetAlignedCodeMemoryStart()[CodeMemorySliceSize * i])
@@ -85,7 +94,9 @@ void FreeCodeMem(void* codeMem)
}
#endif
-#ifdef _WIN32
+#ifdef __PROSPERO__
+ ps5_exec_release(codeMem);
+#elif defined(_WIN32)
VirtualFree(codeMem, CodeMemorySliceSize, MEM_RELEASE|MEM_DECOMMIT);
#else
munmap(codeMem, CodeMemorySliceSize);
@@ -102,7 +113,7 @@ void Init()
#ifdef _WIN32
DWORD dummy;
VirtualProtect(GetAlignedCodeMemoryStart(), CodeMemoryAlignedSize, PAGE_EXECUTE_READWRITE, &dummy);
- #elif defined(APPLE_AARCH64) || defined(__NetBSD__) || defined(__OpenBSD__)
+ #elif defined(APPLE_AARCH64) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__PROSPERO__)
// Apple aarch64 always uses dynamic allocation
#else
mprotect(GetAlignedCodeMemoryStart(), CodeMemoryAlignedSize, PROT_EXEC | PROT_READ | PROT_WRITE);
diff --git a/src/ARMJIT_Memory.cpp b/src/ARMJIT_Memory.cpp
index c64bad1f..25a46a74 100644
--- a/src/ARMJIT_Memory.cpp
+++ b/src/ARMJIT_Memory.cpp
@@ -36,6 +36,9 @@
#include "ARMJIT.h"
#include "ARMJIT_Memory.h"
+#ifdef __PROSPERO__
+#include <new>
+#endif
#include "ARMJIT_Internal.h"
#include "ARMJIT_Compiler.h"
@@ -743,7 +746,7 @@ u32 ARMJIT_Memory::PageShift = 0;
bool ARMJIT_Memory::IsFastMemSupported()
{
-#if defined(__APPLE__) || defined(__OpenBSD__)
+#if defined(__APPLE__) || defined(__OpenBSD__) || defined(__PROSPERO__)
return false;
#else
static bool initialised = false;
@@ -769,7 +772,9 @@ bool ARMJIT_Memory::IsFastMemSupported()
void ARMJIT_Memory::RegisterFaultHandler()
{
-#ifdef _WIN32
+#ifdef __PROSPERO__
+ // PS5 uses checked memory accesses; no title fault handler is installed.
+#elif defined(_WIN32)
ExceptionHandlerHandle = AddVectoredExceptionHandler(1, ExceptionHandler);
KernelBaseDll = LoadLibrary("KernelBase.dll");
@@ -798,7 +803,8 @@ void ARMJIT_Memory::RegisterFaultHandler()
void ARMJIT_Memory::UnregisterFaultHandler()
{
-#ifdef _WIN32
+#ifdef __PROSPERO__
+#elif defined(_WIN32)
if (ExceptionHandlerHandle)
{
RemoveVectoredExceptionHandler(ExceptionHandlerHandle);
@@ -887,6 +893,11 @@ ARMJIT_Memory::ARMJIT_Memory(melonDS::NDS& nds) : NDS(nds)
// old Windows version
MemoryBase = new u8[MemoryTotalSize];
}
+#elif defined(__PROSPERO__)
+ MemoryBase = static_cast<u8*>(aligned_alloc(16*1024, MemoryTotalSize));
+ if (!MemoryBase)
+ throw std::bad_alloc();
+ memset(MemoryBase, 0, MemoryTotalSize);
#else
MemoryBase = (u8*)mmap(nullptr, VirtmemAreaSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
@@ -971,6 +982,11 @@ ARMJIT_Memory::~ARMJIT_Memory() noexcept
{
delete[] MemoryBase;
}
+#elif defined(__PROSPERO__)
+ free(MemoryBase);
+ MemoryBase = nullptr;
+ FastMem9Start = nullptr;
+ FastMem7Start = nullptr;
#else
if (MemoryBase)
{