mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
psx-beetle: build on macOS and send large replies whole
Three portability fixes for the psx-beetle oracle target, none of which changes behaviour on MinGW or Linux: - beetle_cdc_decode_volume redeclared PSX_CDC at block scope inside an extern "C" function. GCC accepts that; clang gives the declaration C linkage and rejects it against psx.h's C++ declaration. psx.h already declares PSX_CDC, so drop the redeclaration. - The debug server's client socket is non-blocking, and send_raw dropped the connection on the first EWOULDBLOCK. macOS starts a TCP send buffer at 128 KB, so a large reply (read_ram of the BIOS ROM or all of RAM) reached the client as a truncated JSON line. Wait for the socket to drain (select, 15 s budget, as debug_server.c's send_all_blocking does) and only drop the client on a real error. - .gitignore had "beetle-psx/", which matches a directory but not the symlink docs recommend when the Beetle checkout lives outside the tree. "beetle-psx" matches both. Also note the non-Windows make platforms in the target's comment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+1
-1
@@ -41,7 +41,7 @@ release-stage/
|
||||
*.zip
|
||||
|
||||
# Vendored upstream sources (cloned locally, not checked in)
|
||||
beetle-psx/
|
||||
beetle-psx
|
||||
|
||||
# Explicit-fallback SDL2 / dep zips (large, regenerable)
|
||||
sdl2-dev.zip
|
||||
|
||||
@@ -868,14 +868,17 @@ if(NOT MSVC)
|
||||
)
|
||||
endif()
|
||||
|
||||
# ---- psx-beetle target (Beetle PSX libretro standalone, MinGW) ----
|
||||
# ---- psx-beetle target (Beetle PSX libretro standalone; MinGW, Linux, macOS) ----
|
||||
#
|
||||
# Standalone binary that runs Beetle PSX (mednafen-psx libretro core) with
|
||||
# a debug server exposing the SAME wire-protocol commands as psx-runtime,
|
||||
# on a different port (4380). No recomp code linked.
|
||||
#
|
||||
# Requires beetle-psx built via:
|
||||
# Requires beetle-psx with the docs/beetle_*.patch hooks, built via:
|
||||
# cd beetle-psx && make platform=mingw_x86_64 STATIC_LINKING=1 HAVE_LIGHTREC=0
|
||||
# (platform=unix on Linux, platform=osx on macOS; there the archive is named
|
||||
# mednafen_psx_libretro.so/.dylib; copy it to libmednafen_psx.a). Recipes:
|
||||
# docs/beetle-linux.md, docs/beetle-macos.md.
|
||||
|
||||
set(BEETLE_LIB "${CMAKE_SOURCE_DIR}/../beetle-psx/libmednafen_psx.a")
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "host_time.h"
|
||||
|
||||
#ifndef DEFAULT_DEBUG_PORT
|
||||
#error DEFAULT_DEBUG_PORT must be defined by the beetle runtime target.
|
||||
#endif
|
||||
@@ -28,6 +30,7 @@
|
||||
# define sock_close closesocket
|
||||
#else
|
||||
# include <sys/socket.h>
|
||||
# include <sys/select.h>
|
||||
# include <netinet/in.h>
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
@@ -189,17 +192,50 @@ static int s_input_override = -1;
|
||||
static int s_input_frames = 0;
|
||||
|
||||
/* ---- Send helpers ---- */
|
||||
|
||||
/* The client socket is non-blocking. A reply larger than the free space in
|
||||
* the kernel send buffer (a 2 MB read_ram is ~4 MB of hex; macOS starts a
|
||||
* TCP send buffer at 128 KB) makes send() fail with EWOULDBLOCK
|
||||
* part-way through. Wait for the socket to drain and carry on, like
|
||||
* debug_server.c's send_all_blocking, instead of dropping the connection
|
||||
* and leaving the client a truncated JSON line. */
|
||||
#define SEND_TOTAL_BUDGET_MS 15000
|
||||
|
||||
static int send_would_block(void) {
|
||||
#ifdef _WIN32
|
||||
return WSAGetLastError() == WSAEWOULDBLOCK;
|
||||
#else
|
||||
return errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wait up to 100 ms for the client socket to become writable. */
|
||||
static int send_wait_writable(void) {
|
||||
fd_set wr;
|
||||
FD_ZERO(&wr);
|
||||
FD_SET(s_client, &wr);
|
||||
struct timeval tv = { 0, 100 * 1000 };
|
||||
return select((int)s_client + 1, NULL, &wr, NULL, &tv) >= 0;
|
||||
}
|
||||
|
||||
static void send_raw(const char *data, int n) {
|
||||
if (s_client == SOCK_INVALID) return;
|
||||
int off = 0;
|
||||
const uint64_t t_start = psx_host_mono_ms();
|
||||
while (off < n) {
|
||||
int k = send(s_client, data + off, n - off, 0);
|
||||
if (k <= 0) {
|
||||
sock_close(s_client);
|
||||
s_client = SOCK_INVALID;
|
||||
return;
|
||||
if (k > 0) {
|
||||
off += k;
|
||||
continue;
|
||||
}
|
||||
off += k;
|
||||
if (k < 0 && send_would_block() &&
|
||||
psx_host_mono_ms() - t_start < SEND_TOTAL_BUDGET_MS &&
|
||||
send_wait_writable()) {
|
||||
continue;
|
||||
}
|
||||
sock_close(s_client);
|
||||
s_client = SOCK_INVALID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1018,7 +1018,9 @@ extern "C" uint64_t beetle_spu_event_total(void) { return s_spu_event_seq; }
|
||||
* Returns 0 if the CDC isn't up. */
|
||||
extern "C" int beetle_cdc_decode_volume(unsigned out[4])
|
||||
{
|
||||
extern PS_CDC *PSX_CDC;
|
||||
/* PSX_CDC is declared by mednafen/psx/psx.h. A block-scope redeclaration
|
||||
* here would get C language linkage from the enclosing extern "C"
|
||||
* function, which clang rejects against psx.h's C++ declaration. */
|
||||
if (!PSX_CDC) return 0;
|
||||
uint8 m[2][2];
|
||||
PSX_CDC->PSXRecomp_GetDecodeVolume(m);
|
||||
|
||||
Reference in New Issue
Block a user