Merge remote-tracking branch 'origin/master' into dev

# Conflicts:
#	core/hw/aica/sgc_if.cpp
#	core/hw/naomi/naomi.cpp
#	core/hw/sh4/dyna/driver.cpp
This commit is contained in:
Flyinghead 2023-02-28 20:02:23 +01:00
commit 885a0508c0
25 changed files with 116 additions and 54 deletions

View File

@ -74,7 +74,7 @@ jobs:
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }} if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
- name: Setup Sentry CLI - name: Setup Sentry CLI
uses: mathieu-bour/setup-sentry-cli@1.2.0 uses: mathieu-bour/setup-sentry-cli@v1
env: env:
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }} SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
with: with:

View File

@ -157,7 +157,7 @@ jobs:
if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }} if: ${{ steps.aws-credentials.outputs.aws-account-id != '' }}
- name: Setup Sentry CLI - name: Setup Sentry CLI
uses: mathieu-bour/setup-sentry-cli@1.2.0 uses: mathieu-bour/setup-sentry-cli@v1
env: env:
SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }} SENTRY_TOKEN: ${{ secrets.SENTRY_TOKEN }}
with: with:

2
.gitmodules vendored
View File

@ -3,7 +3,7 @@
url = https://github.com/libsdl-org/SDL.git url = https://github.com/libsdl-org/SDL.git
[submodule "core/deps/libchdr"] [submodule "core/deps/libchdr"]
path = core/deps/libchdr path = core/deps/libchdr
url = https://github.com/rtissera/libchdr.git url = https://github.com/flyinghead/libchdr.git
[submodule "core/deps/luabridge"] [submodule "core/deps/luabridge"]
path = core/deps/luabridge path = core/deps/luabridge
url = https://github.com/vinniefalco/LuaBridge.git url = https://github.com/vinniefalco/LuaBridge.git

View File

@ -115,7 +115,11 @@ static GL3WglProc (*glx_get_proc_address)(const GLubyte *);
static int open_libgl(void) static int open_libgl(void)
{ {
#if defined(__OpenBSD__)
libgl = dlopen("libGL.so", RTLD_LAZY | RTLD_LOCAL);
#else
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
#endif
if (!libgl) if (!libgl)
return GL3W_ERROR_LIBRARY_OPEN; return GL3W_ERROR_LIBRARY_OPEN;

@ -1 +1 @@
Subproject commit 2781322c4a7f8315c5fd6499129ad4b718e35843 Subproject commit 8c319cf7be87186857972829e343b9082341d365

View File

@ -38,7 +38,9 @@ constexpr size_t CodeBufferSize = 32 * 1024;
static u8 *CodeBuffer; static u8 *CodeBuffer;
#else #else
alignas(4096) static u8 CodeBuffer[CodeBufferSize] alignas(4096) static u8 CodeBuffer[CodeBufferSize]
#if defined(__unix__) #if defined(__OpenBSD__)
__attribute__((section(".openbsd.mutable")));
#elif defined(__unix__)
__attribute__((section(".text"))); __attribute__((section(".text")));
#elif defined(__APPLE__) #elif defined(__APPLE__)
__attribute__((section("__TEXT,.text"))); __attribute__((section("__TEXT,.text")));

View File

@ -639,11 +639,11 @@ struct ChannelEx
//SA,PCMS //SA,PCMS
void UpdateSA() void UpdateSA()
{ {
u32 addr = (ccd->SA_hi<<16) | ccd->SA_low; u32 addr = (ccd->SA_hi << 16) | ccd->SA_low;
if (ccd->PCMS==0) if (ccd->PCMS == 0)
addr&=~1; //0: 16 bit addr &= ~1; //0: 16 bit
SA = &aica_ram[addr]; SA = &aica_ram[addr & ARAM_MASK];
} }
//LSA,LEA //LSA,LEA
void UpdateLoop() void UpdateLoop()
@ -896,6 +896,7 @@ void StepDecodeSample(ChannelEx* ch,u32 CA)
if (!last && PCMS<2) if (!last && PCMS<2)
return ; return ;
// TODO bound checking of sample addresses
s16* sptr16=(s16*)ch->SA; s16* sptr16=(s16*)ch->SA;
s8* sptr8=(s8*)sptr16; s8* sptr8=(s8*)sptr16;
u8* uptr8=(u8*)sptr16; u8* uptr8=(u8*)sptr16;

View File

@ -53,6 +53,8 @@ void (*EntryPoints[ARAM_SIZE_MAX / 4])();
#if defined(_WIN32) || defined(TARGET_IPHONE) || defined(TARGET_ARM_MAC) #if defined(_WIN32) || defined(TARGET_IPHONE) || defined(TARGET_ARM_MAC)
static u8 *ARM7_TCB; static u8 *ARM7_TCB;
#elif defined(__OpenBSD__)
alignas(4096) static u8 ARM7_TCB[ICacheSize] __attribute__((section(".openbsd.mutable")));
#elif defined(__unix__) || defined(__SWITCH__) #elif defined(__unix__) || defined(__SWITCH__)
alignas(4096) static u8 ARM7_TCB[ICacheSize] __attribute__((section(".text"))); alignas(4096) static u8 ARM7_TCB[ICacheSize] __attribute__((section(".text")));
#elif defined(__APPLE__) #elif defined(__APPLE__)

View File

@ -528,6 +528,7 @@ void naomi_reg_Reset(bool hard)
} }
if (settings.naomi.multiboard) if (settings.naomi.multiboard)
multiboard = new Multiboard(); multiboard = new Multiboard();
networkOutput.reset();
} }
else if (multiboard != nullptr) else if (multiboard != nullptr)
multiboard->reset(); multiboard->reset();

View File

@ -302,6 +302,8 @@ static void loadMameRom(const char *filename, LoadProgress *progress)
{ {
u8 *dst = (u8 *)CurrentCartridge->GetPtr(game->blobs[romid].offset, len); u8 *dst = (u8 *)CurrentCartridge->GetPtr(game->blobs[romid].offset, len);
u8 *src = (u8 *)CurrentCartridge->GetPtr(game->blobs[romid].src_offset, len); u8 *src = (u8 *)CurrentCartridge->GetPtr(game->blobs[romid].src_offset, len);
if (dst == nullptr || src == nullptr)
throw NaomiCartException("Invalid ROM");
memcpy(dst, src, game->blobs[romid].length); memcpy(dst, src, game->blobs[romid].length);
DEBUG_LOG(NAOMI, "Copied: %x bytes from %07x to %07x", game->blobs[romid].length, game->blobs[romid].src_offset, game->blobs[romid].offset); DEBUG_LOG(NAOMI, "Copied: %x bytes from %07x to %07x", game->blobs[romid].length, game->blobs[romid].src_offset, game->blobs[romid].offset);
} }
@ -331,6 +333,8 @@ static void loadMameRom(const char *filename, LoadProgress *progress)
case Normal: case Normal:
{ {
u8 *dst = (u8 *)CurrentCartridge->GetPtr(game->blobs[romid].offset, len); u8 *dst = (u8 *)CurrentCartridge->GetPtr(game->blobs[romid].offset, len);
if (dst == nullptr)
throw NaomiCartException(std::string("Invalid ROM: truncated ") + game->blobs[romid].filename);
u32 read = file->Read(dst, game->blobs[romid].length); u32 read = file->Read(dst, game->blobs[romid].length);
if (config::GGPOEnable) if (config::GGPOEnable)
md5.add(dst, game->blobs[romid].length); md5.add(dst, game->blobs[romid].length);
@ -346,6 +350,8 @@ static void loadMameRom(const char *filename, LoadProgress *progress)
u32 read = file->Read(buf, game->blobs[romid].length); u32 read = file->Read(buf, game->blobs[romid].length);
u16 *to = (u16 *)CurrentCartridge->GetPtr(game->blobs[romid].offset, len); u16 *to = (u16 *)CurrentCartridge->GetPtr(game->blobs[romid].offset, len);
if (to == nullptr)
throw NaomiCartException(std::string("Invalid ROM: truncated ") + game->blobs[romid].filename);
u16 *from = (u16 *)buf; u16 *from = (u16 *)buf;
for (int i = game->blobs[romid].length / 2; --i >= 0; to++) for (int i = game->blobs[romid].length / 2; --i >= 0; to++)
*to++ = *from++; *to++ = *from++;
@ -719,10 +725,14 @@ bool Cartridge::Write(u32 offset, u32 size, u32 data)
void* Cartridge::GetPtr(u32 offset, u32& size) void* Cartridge::GetPtr(u32 offset, u32& size)
{ {
offset &= 0x1FFFffff; offset &= 0x1fffffff;
verify(offset < RomSize); if (offset >= RomSize || offset + size > RomSize)
verify((offset + size) <= RomSize); {
WARN_LOG(NAOMI, "Invalid naomi cart: offset %x size %x rom size %x", offset, size, RomSize);
size = 0;
return nullptr;
}
return &RomPtr[offset]; return &RomPtr[offset];
} }
@ -754,7 +764,7 @@ void* NaomiCartridge::GetDmaPtr(u32& size)
{ {
INFO_LOG(NAOMI, "Error: DmaOffset >= RomSize"); INFO_LOG(NAOMI, "Error: DmaOffset >= RomSize");
size = 0; size = 0;
return NULL; return nullptr;
} }
size = std::min(size, RomSize - (DmaOffset & 0x1fffffff)); size = std::min(size, RomSize - (DmaOffset & 0x1fffffff));
return GetPtr(DmaOffset, size); return GetPtr(DmaOffset, size);

View File

@ -53,10 +53,12 @@ struct CommBoardStat
u16 dummy[7]; u16 dummy[7];
}; };
#if !defined(__OpenBSD__)
static inline u16 swap16(u16 w) static inline u16 swap16(u16 w)
{ {
return (w >> 8) | (w << 8); return (w >> 8) | (w << 8);
} }
#endif
static void vblankCallback(Event event, void *param) { static void vblankCallback(Event event, void *param) {
((NaomiM3Comm *)param)->vblank(); ((NaomiM3Comm *)param)->vblank();

View File

@ -46,7 +46,8 @@ void reset(bool hard)
rend_reset(); rend_reset();
tactx_Term(); tactx_Term();
elan::reset(hard); elan::reset(hard);
ta_parse_reset(); if (hard)
ta_parse_reset();
} }
void init() void init()

View File

@ -23,7 +23,9 @@
static u8 *SH4_TCB; static u8 *SH4_TCB;
#else #else
alignas(4096) static u8 SH4_TCB[CODE_SIZE + TEMP_CODE_SIZE] alignas(4096) static u8 SH4_TCB[CODE_SIZE + TEMP_CODE_SIZE]
#if defined(__unix__) || defined(__SWITCH__) #if defined(__OpenBSD__)
__attribute__((section(".openbsd.mutable")));
#elif defined(__unix__) || defined(__SWITCH__)
__attribute__((section(".text"))); __attribute__((section(".text")));
#elif defined(__APPLE__) #elif defined(__APPLE__)
__attribute__((section("__TEXT,.text"))); __attribute__((section("__TEXT,.text")));

View File

@ -8,15 +8,24 @@
#define __USE_GNU 1 #define __USE_GNU 1
#endif #endif
#if !defined(TARGET_NO_EXCEPTIONS) #if !defined(TARGET_NO_EXCEPTIONS) && !defined(__OpenBSD__)
#include <ucontext.h> #include <ucontext.h>
#endif #endif
#if defined(__OpenBSD__)
#include <signal.h>
#endif
#endif #endif
////// //////
#if defined(__OpenBSD__)
#define MCTX(p) (((ucontext_t *)(segfault_ctx)) p)
#else
#define MCTX(p) (((ucontext_t *)(segfault_ctx))->uc_mcontext p) #define MCTX(p) (((ucontext_t *)(segfault_ctx))->uc_mcontext p)
#endif
template <bool ToSegfault, typename Tctx, typename Tseg> template <bool ToSegfault, typename Tctx, typename Tseg>
static void bicopy(Tctx& ctx, Tseg& seg) static void bicopy(Tctx& ctx, Tseg& seg)
{ {
@ -82,6 +91,11 @@ static void context_segfault(host_context_t* hostctx, void* segfault_ctx)
#elif HOST_CPU == CPU_X64 #elif HOST_CPU == CPU_X64
#if defined(__FreeBSD__) || defined(__DragonFly__) #if defined(__FreeBSD__) || defined(__DragonFly__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.mc_rip)); bicopy<ToSegfault>(hostctx->pc, MCTX(.mc_rip));
#elif defined(__OpenBSD__)
bicopy<ToSegfault>(hostctx->pc, MCTX(->sc_rip));
bicopy<ToSegfault>(hostctx->rsp, MCTX(->sc_rsp));
bicopy<ToSegfault>(hostctx->r9, MCTX(->sc_r9));
bicopy<ToSegfault>(hostctx->rdi, MCTX(->sc_rdi));
#elif defined(__NetBSD__) #elif defined(__NetBSD__)
bicopy<ToSegfault>(hostctx->pc, MCTX(.__gregs[_REG_RIP])); bicopy<ToSegfault>(hostctx->pc, MCTX(.__gregs[_REG_RIP]));
bicopy<ToSegfault>(hostctx->rsp, MCTX(.__gregs[REG_RSP])); bicopy<ToSegfault>(hostctx->rsp, MCTX(.__gregs[REG_RSP]));

View File

@ -68,26 +68,24 @@ public:
} }
} }
void reset()
{
gameNameSent = false;
}
void output(const char *name, u32 value) void output(const char *name, u32 value)
{ {
if (!config::NetworkOutput) if (!config::NetworkOutput)
return; return;
if (!gameNameSent)
{
send("game = " + settings.content.gameId + "\n");
gameNameSent = true;
}
char s[9]; char s[9];
sprintf(s, "%x", value); sprintf(s, "%x", value);
std::string msg = std::string(name) + " = " + std::string(s) + "\n"; // mame uses \r std::string msg = std::string(name) + " = " + std::string(s) + "\n"; // mame uses \r
std::vector<sock_t> errorSockets; send(msg);
for (sock_t sock : clients)
if (::send(sock, msg.c_str(), msg.length(), 0) < 0)
{
int error = get_last_error();
if (error != L_EWOULDBLOCK && error != L_EAGAIN)
errorSockets.push_back(sock);
}
for (sock_t sock : errorSockets)
{
closesocket(sock);
clients.erase(std::find(clients.begin(), clients.end(), sock));
}
} }
private: private:
@ -107,8 +105,26 @@ private:
} }
} }
void send(const std::string& msg)
{
std::vector<sock_t> errorSockets;
for (sock_t sock : clients)
if (::send(sock, msg.c_str(), msg.length(), 0) < 0)
{
int error = get_last_error();
if (error != L_EWOULDBLOCK && error != L_EAGAIN)
errorSockets.push_back(sock);
}
for (sock_t sock : errorSockets)
{
closesocket(sock);
clients.erase(std::find(clients.begin(), clients.end(), sock));
}
}
sock_t server = INVALID_SOCKET; sock_t server = INVALID_SOCKET;
std::vector<sock_t> clients; std::vector<sock_t> clients;
bool gameNameSent = false;
}; };
extern NetworkOutput networkOutput; extern NetworkOutput networkOutput;

View File

@ -128,9 +128,14 @@ public:
NOTICE_LOG(AUDIO, "Oboe driver stopping"); NOTICE_LOG(AUDIO, "Oboe driver stopping");
if (stream != nullptr) if (stream != nullptr)
{ {
stream->stop(); // Don't let the AudioErrorCallback term/reinit while we are stopping
stream->close(); // This won't prevent shit to hit the fan if it's already in the process
// of doing so but this is a pretty rare event and happens on devices
// that have audio issues already.
auto localStream = stream;
stream.reset(); stream.reset();
localStream->stop();
localStream->close();
} }
} }

View File

@ -121,8 +121,10 @@ static bool reios_locate_bootfile(const char* bootfile)
// system settings // system settings
flash_syscfg_block syscfg{}; flash_syscfg_block syscfg{};
int rc = static_cast<DCFlashChip*>(flashrom)->ReadBlock(FLASH_PT_USER, FLASH_USER_SYSCFG, &syscfg); int rc = static_cast<DCFlashChip*>(flashrom)->ReadBlock(FLASH_PT_USER, FLASH_USER_SYSCFG, &syscfg);
verify(rc != 0); if (rc == 0)
memcpy(&data[16], &syscfg.time_lo, 8); WARN_LOG(REIOS, "Can't read system settings from flash");
else
memcpy(&data[16], &syscfg.time_lo, 8);
memcpy(GetMemPtr(0x8c000068, sizeof(data)), data, sizeof(data)); memcpy(GetMemPtr(0x8c000068, sizeof(data)), data, sizeof(data));

View File

@ -453,11 +453,11 @@ void BaseTextureCacheData::unprotectVRam()
bool BaseTextureCacheData::Delete() bool BaseTextureCacheData::Delete()
{ {
unprotectVRam();
if (custom_load_in_progress > 0) if (custom_load_in_progress > 0)
return false; return false;
unprotectVRam();
free(custom_image_data); free(custom_image_data);
custom_image_data = nullptr; custom_image_data = nullptr;
@ -625,6 +625,7 @@ void BaseTextureCacheData::Update()
else else
{ {
WARN_LOG(RENDERER, "Warning: invalid texture. Address %08X %08X size %d", sa_tex, sa, size); WARN_LOG(RENDERER, "Warning: invalid texture. Address %08X %08X size %d", sa_tex, sa, size);
unprotectVRam();
return; return;
} }
} }

View File

@ -265,7 +265,7 @@ void DX11Context::resize()
#endif #endif
if (FAILED(hr)) if (FAILED(hr))
{ {
WARN_LOG(RENDERER, "ResizeBuffers failed"); WARN_LOG(RENDERER, "ResizeBuffers failed: %x", hr);
return; return;
} }
@ -274,14 +274,14 @@ void DX11Context::resize()
hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&backBuffer.get()); hr = swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&backBuffer.get());
if (FAILED(hr)) if (FAILED(hr))
{ {
WARN_LOG(RENDERER, "swapChain->GetBuffer() failed"); WARN_LOG(RENDERER, "swapChain->GetBuffer() failed: %x", hr);
return; return;
} }
hr = pDevice->CreateRenderTargetView(backBuffer, nullptr, &renderTargetView.get()); hr = pDevice->CreateRenderTargetView(backBuffer, nullptr, &renderTargetView.get());
if (FAILED(hr)) if (FAILED(hr))
{ {
WARN_LOG(RENDERER, "CreateRenderTargetView failed"); WARN_LOG(RENDERER, "CreateRenderTargetView failed: %x", hr);
return; return;
} }
pDeviceContext->OMSetRenderTargets(1, &renderTargetView.get(), nullptr); pDeviceContext->OMSetRenderTargets(1, &renderTargetView.get(), nullptr);

View File

@ -652,8 +652,6 @@ GLuint gl_CompileAndLink(const char *vertexShader, const char *fragmentShader)
glcache.UseProgram(program); glcache.UseProgram(program);
verify(glIsProgram(program));
return program; return program;
} }
@ -810,7 +808,7 @@ bool CompilePipelineShader(PipelineShader* s)
ShaderUniforms.Set(s); ShaderUniforms.Set(s);
return glIsProgram(s->program)==GL_TRUE; return true;
} }
#ifdef __ANDROID__ #ifdef __ANDROID__

View File

@ -50,13 +50,13 @@ OpenGLDriver::OpenGLDriver()
for (auto& tex : vmu_lcd_tex_ids) for (auto& tex : vmu_lcd_tex_ids)
tex = ImTextureID(); tex = ImTextureID();
ImGui_ImplOpenGL3_Init(); ImGui_ImplOpenGL3_Init();
EventManager::listen(Event::Start, emuEventCallback, this); EventManager::listen(Event::Resume, emuEventCallback, this);
EventManager::listen(Event::Terminate, emuEventCallback, this); EventManager::listen(Event::Terminate, emuEventCallback, this);
} }
OpenGLDriver::~OpenGLDriver() OpenGLDriver::~OpenGLDriver()
{ {
EventManager::unlisten(Event::Start, emuEventCallback, this); EventManager::unlisten(Event::Resume, emuEventCallback, this);
EventManager::unlisten(Event::Terminate, emuEventCallback, this); EventManager::unlisten(Event::Terminate, emuEventCallback, this);
std::vector<GLuint> texIds; std::vector<GLuint> texIds;

View File

@ -53,7 +53,7 @@ private:
{ {
switch (event) switch (event)
{ {
case Event::Start: case Event::Resume:
gameStarted = true; gameStarted = true;
break; break;
case Event::Terminate: case Event::Terminate:

View File

@ -2952,6 +2952,7 @@ void gui_term()
if (inited) if (inited)
{ {
inited = false; inited = false;
scanner.stop();
ImGui::DestroyContext(); ImGui::DestroyContext();
EventManager::unlisten(Event::Resume, emuEventCallback); EventManager::unlisten(Event::Resume, emuEventCallback);
EventManager::unlisten(Event::Start, emuEventCallback); EventManager::unlisten(Event::Start, emuEventCallback);

View File

@ -62,8 +62,11 @@ static void sdl_open_joystick(int index)
INFO_LOG(INPUT, "SDL: Cannot open joystick %d", index + 1); INFO_LOG(INPUT, "SDL: Cannot open joystick %d", index + 1);
return; return;
} }
std::shared_ptr<SDLGamepad> gamepad = std::make_shared<SDLGamepad>(index < MAPLE_PORTS ? index : -1, index, pJoystick); try {
SDLGamepad::AddSDLGamepad(gamepad); std::shared_ptr<SDLGamepad> gamepad = std::make_shared<SDLGamepad>(index < MAPLE_PORTS ? index : -1, index, pJoystick);
SDLGamepad::AddSDLGamepad(gamepad);
} catch (const FlycastException& e) {
}
} }
static void sdl_close_joystick(SDL_JoystickID instance) static void sdl_close_joystick(SDL_JoystickID instance)
@ -195,7 +198,7 @@ void input_sdl_init()
checkRawInput(); checkRawInput();
#ifdef __SWITCH__ #if defined(__SWITCH__) || defined(__OpenBSD__)
// when railed, both joycons are mapped to joystick #0, // when railed, both joycons are mapped to joystick #0,
// else joycons are individually mapped to joystick #0, joystick #1, ... // else joycons are individually mapped to joystick #0, joystick #1, ...
// https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L45 // https://github.com/devkitPro/SDL/blob/switch-sdl2/src/joystick/switch/SDL_sysjoystick.c#L45

View File

@ -170,12 +170,9 @@ public:
if (joyName == nullptr) if (joyName == nullptr)
{ {
WARN_LOG(INPUT, "Can't get joystick %d name: %s", joystick_idx, SDL_GetError()); WARN_LOG(INPUT, "Can't get joystick %d name: %s", joystick_idx, SDL_GetError());
_name = "Joystick " + std::to_string(joystick_idx); throw FlycastException("joystick failure");
}
else
{
_name = joyName;
} }
_name = joyName;
sdl_joystick_instance = SDL_JoystickInstanceID(sdl_joystick); sdl_joystick_instance = SDL_JoystickInstanceID(sdl_joystick);
_unique_id = "sdl_joystick_" + std::to_string(sdl_joystick_instance); _unique_id = "sdl_joystick_" + std::to_string(sdl_joystick_instance);
INFO_LOG(INPUT, "SDL: Opened joystick %d on port %d: '%s' unique_id=%s", sdl_joystick_instance, maple_port, _name.c_str(), _unique_id.c_str()); INFO_LOG(INPUT, "SDL: Opened joystick %d on port %d: '%s' unique_id=%s", sdl_joystick_instance, maple_port, _name.c_str(), _unique_id.c_str());