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

This commit is contained in:
Flyinghead 2023-02-05 22:20:28 +01:00
commit debe21de7b
35 changed files with 1746 additions and 483 deletions

View File

@ -368,6 +368,12 @@ if(NOT LIBRETRO)
set(SDL2_FOUND 1)
endif()
# SDL2::SDL2main may or may not be available. It is e.g. required by Windows GUI applications
if(TARGET SDL2::SDL2main)
# It has an implicit dependency on SDL2 functions, so it MUST be added before SDL2::SDL2 (or SDL2::SDL2-static)
target_link_libraries(${PROJECT_NAME} PRIVATE SDL2::SDL2main)
endif()
if((APPLE OR WIN32) AND TARGET SDL2::SDL2-static)
target_link_libraries(${PROJECT_NAME} PRIVATE SDL2::SDL2-static)
elseif(TARGET SDL2::SDL2)
@ -514,7 +520,12 @@ if(UNIX AND NOT APPLE AND NOT ANDROID)
target_compile_definitions(${PROJECT_NAME} PRIVATE EGL_NO_X11)
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS} rt)
find_library(LIBRT rt)
if(LIBRT)
target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBRT})
endif()
target_link_libraries(${PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS})
endif()
if(ASAN)

View File

@ -37,10 +37,10 @@ Option<bool> FullMMU("Dreamcast.FullMMU");
Option<bool> ForceWindowsCE("Dreamcast.ForceWindowsCE");
Option<bool> AutoLoadState("Dreamcast.AutoLoadState");
Option<bool> AutoSaveState("Dreamcast.AutoSaveState");
Option<int> SavestateSlot("Dreamcast.SavestateSlot");
Option<int, false> SavestateSlot("Dreamcast.SavestateSlot");
Option<bool> ForceFreePlay("ForceFreePlay", true);
Option<bool> FetchBoxart("FetchBoxart", true);
Option<bool> BoxartDisplayMode("BoxartDisplayMode", true);
Option<bool, false> FetchBoxart("FetchBoxart", true);
Option<bool, false> BoxartDisplayMode("BoxartDisplayMode", true);
// Sound
@ -122,7 +122,7 @@ Option<bool> OpenGlChecks("OpenGlChecks", false, "validate");
Option<std::vector<std::string>, false> ContentPath("Dreamcast.ContentPath");
Option<bool, false> HideLegacyNaomiRoms("Dreamcast.HideLegacyNaomiRoms", true);
Option<bool> UploadCrashLogs("UploadCrashLogs", true);
Option<bool, false> UploadCrashLogs("UploadCrashLogs", true);
// Profiler
Option<bool> ProfilerEnabled("Profiler.Enabled");
@ -183,11 +183,11 @@ std::array<std::array<Option<MapleDeviceType>, 2>, 4> MapleExpansionDevices {
Option<MapleDeviceType>("device4.2", MDT_None, "input"),
};
#ifdef _WIN32
Option<bool> UseRawInput("RawInput", false, "input");
Option<bool, false> UseRawInput("RawInput", false, "input");
#endif
#ifdef USE_LUA
OptionString LuaFileName("LuaFileName", "flycast.lua");
Option<std::string, false> LuaFileName("LuaFileName", "flycast.lua");
#endif
} // namespace config

View File

@ -157,8 +157,8 @@ public:
T& get() { return value; }
void set(T v) { value = v; }
void override(T v) {
verify(PerGameOption);
void override(T v)
{
overriddenDefault = v;
overridden = true;
value = v;
@ -372,10 +372,10 @@ extern Option<bool> FullMMU;
extern Option<bool> ForceWindowsCE;
extern Option<bool> AutoLoadState;
extern Option<bool> AutoSaveState;
extern Option<int> SavestateSlot;
extern Option<int, false> SavestateSlot;
extern Option<bool> ForceFreePlay;
extern Option<bool> FetchBoxart;
extern Option<bool> BoxartDisplayMode;
extern Option<bool, false> FetchBoxart;
extern Option<bool, false> BoxartDisplayMode;
// Sound
@ -416,10 +416,10 @@ extern Option<bool> VmuSound;
class RendererOption : public Option<RenderType> {
public:
RendererOption()
#ifdef USE_DX9
: Option<RenderType>("pvr.rend", RenderType::DirectX9) {}
#elif defined(USE_DX11)
#if defined(USE_DX11)
: Option<RenderType>("pvr.rend", RenderType::DirectX11) {}
#elif defined(USE_DX9)
: Option<RenderType>("pvr.rend", RenderType::DirectX9) {}
#else
: Option<RenderType>("pvr.rend", RenderType::OpenGL) {}
#endif
@ -483,7 +483,7 @@ extern Option<bool> OpenGlChecks;
extern Option<std::vector<std::string>, false> ContentPath;
extern Option<bool, false> HideLegacyNaomiRoms;
extern Option<bool> UploadCrashLogs;
extern Option<bool, false> UploadCrashLogs;
// Profiling
extern Option<bool> ProfilerEnabled;
@ -526,13 +526,13 @@ extern Option<int> VirtualGamepadVibration;
extern std::array<Option<MapleDeviceType>, 4> MapleMainDevices;
extern std::array<std::array<Option<MapleDeviceType>, 2>, 4> MapleExpansionDevices;
#ifdef _WIN32
extern Option<bool> UseRawInput;
extern Option<bool, false> UseRawInput;
#else
constexpr bool UseRawInput = false;
#endif
#ifdef USE_LUA
extern OptionString LuaFileName;
extern Option<std::string, false> LuaFileName;
#endif
} // namespace config

View File

@ -48,13 +48,11 @@ settings_t settings;
static void loadSpecialSettings()
{
std::string& prod_id = settings.content.gameId;
NOTICE_LOG(BOOT, "Game ID is [%s]", prod_id.c_str());
if (settings.platform.isConsole())
{
std::string prod_id(ip_meta.product_number, sizeof(ip_meta.product_number));
prod_id = trim_trailing_ws(prod_id);
NOTICE_LOG(BOOT, "Game ID is [%s]", prod_id.c_str());
if (ip_meta.isWindowsCE() || config::ForceWindowsCE
|| prod_id == "T26702N") // PBA Tour Bowling 2001
{
@ -216,7 +214,9 @@ static void loadSpecialSettings()
config::UseReios.override(false);
}
if (prod_id == "T-9707N" // San Francisco Rush 2049 (US)
|| prod_id == "MK-51146") // Sega Smash Pack - Volume 1
|| prod_id == "MK-51146" // Sega Smash Pack - Volume 1
|| prod_id == "T-9702D-50" // Hydro Thunder (PAL)
|| prod_id == "T41601N") // Elemental Gimmick Gear (US)
{
NOTICE_LOG(BOOT, "Forcing NTSC broadcasting");
config::Broadcast.override(0);
@ -235,132 +235,131 @@ static void loadSpecialSettings()
}
else if (settings.platform.isArcade())
{
NOTICE_LOG(BOOT, "Game ID is [%s]", naomi_game_id);
if (!strcmp("SAMURAI SPIRITS 6", naomi_game_id))
if (prod_id == "SAMURAI SPIRITS 6")
{
INFO_LOG(BOOT, "Enabling Extra depth scaling for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling Extra depth scaling for game %s", prod_id.c_str());
config::ExtraDepthScale.override(1e26f);
}
if (!strcmp("COSMIC SMASH IN JAPAN", naomi_game_id))
if (prod_id == "COSMIC SMASH IN JAPAN")
{
INFO_LOG(BOOT, "Enabling translucent depth multipass for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling translucent depth multipass for game %s", prod_id.c_str());
config::TranslucentPolygonDepthMask.override(true);
}
if (!strcmp(naomi_game_id, "BEACH SPIKERS JAPAN"))
if (prod_id == "BEACH SPIKERS JAPAN")
{
INFO_LOG(BOOT, "Enabling RTT Copy to VRAM for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling RTT Copy to VRAM for game %s", prod_id.c_str());
config::RenderToTextureBuffer.override(true);
}
if (!strcmp(naomi_game_id, "RADIRGY NOA"))
if (prod_id == "RADIRGY NOA")
{
INFO_LOG(BOOT, "Disabling Free Play for game %s", naomi_game_id);
INFO_LOG(BOOT, "Disabling Free Play for game %s", prod_id.c_str());
config::ForceFreePlay.override(false);
}
// Input configuration
settings.input.JammaSetup = JVS::Default;
if (!strcmp("DYNAMIC GOLF", naomi_game_id)
|| !strcmp("SHOOTOUT POOL", naomi_game_id)
|| !strcmp("SHOOTOUT POOL MEDAL", naomi_game_id)
|| !strcmp("CRACKIN'DJ ver JAPAN", naomi_game_id)
|| !strcmp("CRACKIN'DJ PART2 ver JAPAN", naomi_game_id)
|| !strcmp("KICK '4' CASH", naomi_game_id)
|| !strcmp("DRIVE", naomi_game_id)) // Waiwai drive
if (prod_id == "DYNAMIC GOLF"
|| prod_id == "SHOOTOUT POOL"
|| prod_id == "SHOOTOUT POOL MEDAL"
|| prod_id == "CRACKIN'DJ ver JAPAN"
|| prod_id == "CRACKIN'DJ PART2 ver JAPAN"
|| prod_id == "KICK '4' CASH"
|| prod_id == "DRIVE") // Waiwai drive
{
INFO_LOG(BOOT, "Enabling JVS rotary encoders for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling JVS rotary encoders for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::RotaryEncoders;
}
else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id) // Naomi
|| !strcmp("GUILTY GEAR isuka", naomi_game_id)) // AW
else if (prod_id == "POWER STONE 2 JAPAN" // Naomi
|| prod_id == "GUILTY GEAR isuka") // AW
{
INFO_LOG(BOOT, "Enabling 4-player setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling 4-player setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::FourPlayers;
}
else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id)
|| !strcmp(naomi_game_id, "BASS FISHING SIMULATOR VER.A")) // AW
else if (prod_id == "SEGA MARINE FISHING JAPAN"
|| prod_id == "BASS FISHING SIMULATOR VER.A") // AW
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::SegaMarineFishing;
}
else if (!strcmp("RINGOUT 4X4 JAPAN", naomi_game_id)
|| !strcmp("VIRTUA ATHLETE", naomi_game_id))
else if (prod_id == "RINGOUT 4X4 JAPAN"
|| prod_id == "VIRTUA ATHLETE")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::DualIOBoards4P;
}
else if (!strcmp("NINJA ASSAULT", naomi_game_id)
|| !strcmp(naomi_game_id, "Sports Shooting USA") // AW
|| !strcmp(naomi_game_id, "SEGA CLAY CHALLENGE") // AW
|| !strcmp(naomi_game_id, "RANGER MISSION") // AW
|| !strcmp(naomi_game_id, "EXTREME HUNTING")) // AW
else if (prod_id == "NINJA ASSAULT"
|| prod_id == "Sports Shooting USA" // AW
|| prod_id == "SEGA CLAY CHALLENGE" // AW
|| prod_id == "RANGER MISSION" // AW
|| prod_id == "EXTREME HUNTING") // AW
{
INFO_LOG(BOOT, "Enabling lightgun setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling lightgun setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::LightGun;
}
else if (!strcmp("MAZAN", naomi_game_id))
else if (prod_id == "MAZAN")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::Mazan;
}
else if (!strcmp(" BIOHAZARD GUN SURVIVOR2", naomi_game_id))
else if (prod_id == " BIOHAZARD GUN SURVIVOR2")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::GunSurvivor;
}
else if (!strcmp("WORLD KICKS", naomi_game_id))
else if (prod_id == "WORLD KICKS")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::WorldKicks;
}
else if (!strcmp("WORLD KICKS PCB", naomi_game_id))
else if (prod_id == "WORLD KICKS PCB")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::WorldKicksPCB;
}
else if (!strcmp("THE TYPING OF THE DEAD", naomi_game_id)
|| !strcmp(" LUPIN THE THIRD -THE TYPING-", naomi_game_id)
|| !strcmp("------La Keyboardxyu------", naomi_game_id))
else if (prod_id == "THE TYPING OF THE DEAD"
|| prod_id == " LUPIN THE THIRD -THE TYPING-"
|| prod_id == "------La Keyboardxyu------")
{
INFO_LOG(BOOT, "Enabling keyboard for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling keyboard for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::Keyboard;
}
else if (!strcmp("OUTTRIGGER JAPAN", naomi_game_id))
else if (prod_id == "OUTTRIGGER JAPAN")
{
INFO_LOG(BOOT, "Enabling JVS rotary encoders for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling JVS rotary encoders for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::OutTrigger;
}
else if (!strcmp(naomi_game_id, "THE MAZE OF THE KINGS")
|| !strcmp(naomi_game_id, " CONFIDENTIAL MISSION ---------")
|| !strcmp(naomi_game_id, "DEATH CRIMSON OX")
|| !strncmp(naomi_game_id, "hotd2", 5) // House of the Dead 2
|| !strcmp(naomi_game_id, "LUPIN THE THIRD -THE SHOOTING-"))
else if (prod_id == "THE MAZE OF THE KINGS"
|| prod_id == " CONFIDENTIAL MISSION ---------"
|| prod_id == "DEATH CRIMSON OX"
|| prod_id.substr(0, 5) == "hotd2" // House of the Dead 2
|| prod_id == "LUPIN THE THIRD -THE SHOOTING-")
{
INFO_LOG(BOOT, "Enabling lightgun as analog setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling lightgun as analog setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::LightGunAsAnalog;
}
else if (!strcmp("WAVE RUNNER GP", naomi_game_id))
else if (prod_id == "WAVE RUNNER GP")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::WaveRunnerGP;
}
else if (!strcmp(" 18WHEELER", naomi_game_id))
else if (prod_id == " 18WHEELER")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::_18Wheeler;
}
else if (!strcmp("F355 CHALLENGE JAPAN", naomi_game_id))
else if (prod_id == "F355 CHALLENGE JAPAN", naomi_game_id)
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
settings.input.JammaSetup = JVS::F355;
}
else if (!strcmp("INU NO OSANPO", naomi_game_id)) // Dog Walking
else if (prod_id == "INU NO OSANPO") // Dog Walking
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::DogWalking;
}
else if (!strcmp(" TOUCH DE UNOH -------------", naomi_game_id)
|| !strcmp("POKASUKA GHOST (JAPANESE)", naomi_game_id))
else if (prod_id == " TOUCH DE UNOH -------------"
|| prod_id == "POKASUKA GHOST (JAPANESE)")
{
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", naomi_game_id);
INFO_LOG(BOOT, "Enabling specific JVS setup for game %s", prod_id.c_str());
settings.input.JammaSetup = JVS::TouchDeUno;
}
}
@ -371,8 +370,8 @@ void dc_reset(bool hard)
NetworkHandshake::term();
if (hard)
{
addrspace::unprotectVram(0, VRAM_SIZE);
memwatch::elanWatcher.unprotectMem(0, 0xffffffff);
memwatch::unprotect();
memwatch::reset();
}
sh4_sched_reset(hard);
pvr::reset(hard);
@ -672,6 +671,10 @@ void Emulator::stop()
{
if (state != Running)
return;
// Avoid race condition with GGPO restarting the sh4 for a new frame
if (config::GGPOEnable)
NetworkHandshake::term();
// must be updated after GGPO is stopped since it may run some rollback frames
state = Loaded;
sh4_cpu.Stop();
if (config::ThreadedRendering)
@ -699,36 +702,30 @@ void Emulator::stop()
void Emulator::requestReset()
{
resetRequested = true;
if (config::GGPOEnable)
NetworkHandshake::term();
sh4_cpu.Stop();
}
void loadGameSpecificSettings()
{
char *reios_id;
if (settings.platform.isConsole())
{
static char _disk_id[sizeof(ip_meta.product_number) + 1];
reios_disk_id();
memcpy(_disk_id, ip_meta.product_number, sizeof(ip_meta.product_number));
reios_id = _disk_id;
settings.content.gameId = trim_trailing_ws(std::string(ip_meta.product_number, sizeof(ip_meta.product_number)));
char *p = reios_id + strlen(reios_id) - 1;
while (p >= reios_id && *p == ' ')
*p-- = '\0';
if (*p == '\0')
if (settings.content.gameId.empty())
return;
}
else
{
reios_id = naomi_game_id;
settings.content.gameId = naomi_game_id;
}
// Default per-game settings
loadSpecialSettings();
settings.content.gameId = reios_id;
config::Settings::instance().setGameId(reios_id);
config::Settings::instance().setGameId(settings.content.gameId);
// Reload per-game settings
config::Settings::instance().load(true);
@ -944,7 +941,9 @@ void Emulator::vblank()
if (sh4_sched_now64() - startTime <= 10000000)
return;
renderTimeout = true;
if (!ggpo::active() && !config::ThreadedRendering)
if (ggpo::active())
ggpo::endOfFrame();
else if (!config::ThreadedRendering)
sh4_cpu.Stop();
}

View File

@ -173,40 +173,34 @@ static void AicaInternalDMA()
template<typename T>
void writeTimerAndIntReg(u32 reg, T data)
{
constexpr size_t sz = sizeof(T);
switch (reg)
{
case SCIEB_addr:
verify(sz != 1);
SCIEB->full = data & 0x7ff;
update_arm_interrupts();
break;
case SCIPD_addr:
verify(sz!=1);
// other bits are read-only
if (data & (1<<5))
if (data & (1 << 5))
{
SCIPD->SCPU=1;
SCIPD->SCPU = 1;
update_arm_interrupts();
}
break;
case SCIRE_addr:
verify(sz != 1);
SCIPD->full &= ~data /*& SCIEB->full)*/; //is the & SCIEB->full needed ? doesn't seem like it
SCIPD->full &= ~data;
update_arm_interrupts();
break;
case MCIEB_addr:
verify(sz != 1);
MCIEB->full = data & 0x7ff;
if (UpdateSh4Ints())
arm::avoidRaceCondition();
break;
case MCIPD_addr:
verify(sz != 1);
// other bits are read-only
if (data & (1 << 5))
{
@ -217,7 +211,6 @@ void writeTimerAndIntReg(u32 reg, T data)
break;
case MCIRE_addr:
verify(sz != 1);
MCIPD->full &= ~data;
UpdateSh4Ints();
break;

View File

@ -222,8 +222,9 @@ static void CPUSwitchMode(int mode, bool saveState)
reg[RN_SPSR].I = reg[SPSR_UND].I;
break;
default:
// An illegal mode causes the processor to enter an unrecoverable state
ERROR_LOG(AICA_ARM, "Unsupported ARM mode %02x", mode);
die("Arm error..");
Arm7Enabled = false;
break;
}
armMode = mode;

View File

@ -845,7 +845,7 @@ maple_naomi_jamma::maple_naomi_jamma()
io_boards.push_back(std::unique_ptr<jvs_837_13844>(new jvs_837_13844(1, this)));
break;
case JVS::DualIOBoards4P:
if (!strcmp(naomi_game_id, "VIRTUA ATHLETE"))
if (settings.content.gameId == "VIRTUA ATHLETE")
{
// reverse the board order so that P1 is P1
io_boards.push_back(std::unique_ptr<jvs_837_13551>(new jvs_837_13551(1, this, 2)));
@ -1752,6 +1752,9 @@ u32 jvs_io_board::handle_jvs_message(u8 *buffer_in, u32 length_in, u8 *buffer_ou
axis_value = 0;
if (axisDesc.inverted)
axis_value = 0xff00u - axis_value;
// this fixes kingrt66 immediate win
if (axis_value == 0x8000)
axis_value = 0x8100;
}
else
{

View File

@ -215,8 +215,6 @@ inline static void protect()
inline static void unprotect()
{
if (!config::GGPOEnable)
return;
vramWatcher.unprotect();
ramWatcher.unprotect();
aramWatcher.unprotect();

View File

@ -8,6 +8,7 @@
#include "hw/holly/holly_intc.h"
#include "hw/sh4/sh4_if.h"
#include "profiler/fc_profiler.h"
#include "network/ggpo.h"
#include <mutex>
#include <deque>
@ -32,6 +33,7 @@ u32 fb_watch_addr_end;
bool fb_dirty;
static bool pend_rend;
static bool rendererEnabled = true;
TA_context* _pvrrc;
@ -226,7 +228,7 @@ private:
if (renderer->Present())
{
presented = true;
if (!config::ThreadedRendering)
if (!config::ThreadedRendering && !ggpo::active())
sh4_cpu.Stop();
#ifdef LIBRETRO
retro_rend_present();
@ -307,6 +309,7 @@ static void rend_create_renderer()
bool rend_init_renderer()
{
rendererEnabled = true;
if (renderer == nullptr)
rend_create_renderer();
bool success = renderer->Init();
@ -336,6 +339,7 @@ void rend_reset()
FrameCount = 1;
fb_w_cur = 1;
pvrQueue.reset();
rendererEnabled = true;
}
void rend_start_render()
@ -387,6 +391,9 @@ void rend_start_render()
ctx->rend.fog_clamp_min = FOG_CLAMP_MIN;
ctx->rend.fog_clamp_max = FOG_CLAMP_MAX;
if (!ctx->rend.isRTT)
ggpo::endOfFrame();
if (QueueRender(ctx))
{
palette_update();
@ -422,12 +429,15 @@ void rend_vblank()
if (config::EmulateFramebuffer
|| (!render_called && fb_dirty && FB_R_CTRL.fb_enable))
{
FramebufferInfo fbInfo;
fbInfo.update();
pvrQueue.enqueue(PvrMessageQueue::RenderFramebuffer, fbInfo);
pvrQueue.enqueue(PvrMessageQueue::Present);
if (!config::EmulateFramebuffer)
DEBUG_LOG(PVR, "Direct framebuffer write detected");
if (rend_is_enabled())
{
FramebufferInfo fbInfo;
fbInfo.update();
pvrQueue.enqueue(PvrMessageQueue::RenderFramebuffer, fbInfo);
pvrQueue.enqueue(PvrMessageQueue::Present);
if (!config::EmulateFramebuffer)
DEBUG_LOG(PVR, "Direct framebuffer write detected");
}
fb_dirty = false;
}
render_called = false;
@ -466,7 +476,7 @@ void rend_set_fb_write_addr(u32 fb_w_sof1)
void rend_swap_frame(u32 fb_r_sof)
{
if (!config::EmulateFramebuffer && fb_r_sof == fb_w_cur)
if (!config::EmulateFramebuffer && fb_r_sof == fb_w_cur && rend_is_enabled())
pvrQueue.enqueue(PvrMessageQueue::Present);
}
@ -486,6 +496,14 @@ void rend_start_rollback()
vramRollback.Wait();
}
void rend_enable_renderer(bool enabled) {
rendererEnabled = enabled;
}
bool rend_is_enabled() {
return rendererEnabled;
}
void rend_serialize(Serializer& ser)
{
ser << fb_w_cur;

View File

@ -17,6 +17,8 @@ void rend_reset();
void rend_disable_rollback();
void rend_start_rollback();
void rend_allow_rollback();
void rend_enable_renderer(bool enabled);
bool rend_is_enabled();
void rend_serialize(Serializer& ser);
void rend_deserialize(Deserializer& deser);

View File

@ -113,7 +113,6 @@ static int spg_line_sched(int tag, int cycles, int jitter)
SB_MDST = 0;
}
asic_RaiseInterrupt(holly_SCANINT1);
ggpo::endOfFrame();
}
if (SPG_VBLANK_INT.vblank_out_interrupt_line_number == prv_cur_scanline)

View File

@ -50,7 +50,7 @@ bool QueueRender(TA_context* ctx)
{
verify(ctx != 0);
bool skipFrame = settings.disableRenderer;
bool skipFrame = !rend_is_enabled();
if (!skipFrame)
{
RenderCount++;
@ -67,7 +67,7 @@ bool QueueRender(TA_context* ctx)
if (skipFrame || rqueue)
{
tactx_Recycle(ctx);
if (!settings.disableRenderer)
if (rend_is_enabled())
fskip++;
return false;
}

View File

@ -72,13 +72,10 @@ void sortTriangles(rend_context& ctx, RenderPass& pass, const RenderPass& previo
const PolyParam * const pp_base = &ctx.global_param_tr[first];
const PolyParam * const pp_end = pp_base + count;
int vtx_count = ctx.verts.size() - pp_base->first;
if (vtx_count <= 0)
return;
//make lists of all triangles, with their pid and vid
static std::vector<IndexTrig> triangleList;
int vtx_count = ctx.verts.size() - pp_base->first;
triangleList.reserve(vtx_count);
triangleList.clear();
@ -147,6 +144,7 @@ void sortTriangles(rend_context& ctx, RenderPass& pass, const RenderPass& previo
//re-assemble them into drawing commands
size_t initialSize = ctx.sortedTriangles.size();
int idx = -1;
int idxSize = ctx.idx.size();
@ -174,7 +172,7 @@ void sortTriangles(rend_context& ctx, RenderPass& pass, const RenderPass& previo
}
}
if (!ctx.sortedTriangles.empty())
if (!triangleList.empty())
{
SortedTriangle& last = ctx.sortedTriangles.back();
last.count = idxSize + triangleList.size() * 3 - last.first;
@ -184,7 +182,7 @@ void sortTriangles(rend_context& ctx, RenderPass& pass, const RenderPass& previo
// Add a dummy one to signal we're using sorted triangles
ctx.sortedTriangles.push_back({ pp_base, 0, 0});
}
pass.sorted_tr_count = ctx.sortedTriangles.size();
pass.sorted_tr_count = ctx.sortedTriangles.size() - initialSize;
#if PRINT_SORT_STATS
printf("Reassembled into %d from %d\n", (int)ctx.sortedTriangles.size(), pp_end - pp_base);

View File

@ -255,14 +255,14 @@ static bool advance_frame(int)
{
INFO_LOG(NETWORK, "advance_frame");
settings.aica.muteAudio = true;
settings.disableRenderer = true;
rend_enable_renderer(false);
inRollback = true;
emu.run();
ggpo_advance_frame(ggpoSession);
settings.aica.muteAudio = false;
settings.disableRenderer = false;
rend_enable_renderer(true);
inRollback = false;
_endOfFrame = false;
@ -597,6 +597,8 @@ void stopSession()
ggpoSession = nullptr;
miniupnp.Term();
emu.setNetworkState(false);
memwatch::unprotect();
memwatch::reset();
}
void getInput(MapleInputState inputState[4])

View File

@ -17,7 +17,6 @@
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "naomi_network.h"
#include "hw/naomi/naomi_cart.h"
#include "hw/naomi/naomi_flashrom.h"
#include "cfg/option.h"
#include "rend/gui.h"
@ -294,81 +293,81 @@ bool NaomiNetwork::receive(const sockaddr_in *addr, const Packet *packet, u32 si
// Node 0 is master, nodes 1+ are slave
void SetNaomiNetworkConfig(int node)
{
if (!strcmp("ALIEN FRONT", naomi_game_id))
const std::string& gameId = settings.content.gameId;
if (gameId == "ALIEN FRONT")
{
// no way to disable the network
write_naomi_eeprom(0x3f, node == 0 ? 0 : 1);
}
else if (!strcmp("MOBILE SUIT GUNDAM JAPAN", naomi_game_id) // gundmct
|| !strcmp("MOBILE SUIT GUNDAM DELUXE JAPAN", naomi_game_id)) // gundmxgd
else if (gameId == "MOBILE SUIT GUNDAM JAPAN" // gundmct
|| gameId == "MOBILE SUIT GUNDAM DELUXE JAPAN") // gundmxgd
{
write_naomi_eeprom(0x38, node == -1 ? 2
: node == 0 ? 0 : 1);
}
else if (!strcmp(" BIOHAZARD GUN SURVIVOR2", naomi_game_id))
else if (gameId == " BIOHAZARD GUN SURVIVOR2")
{
// FIXME need default flash
write_naomi_flash(0x21c, node == 0 ? 0 : 1); // CPU ID - 1
write_naomi_flash(0x22a, node == -1 ? 0 : 1); // comm link on
}
else if (!strcmp("HEAVY METAL JAPAN", naomi_game_id))
else if (gameId == "HEAVY METAL JAPAN")
{
write_naomi_eeprom(0x31, node == -1 ? 0 : node == 0 ? 1 : 2);
}
else if (!strcmp("OUTTRIGGER JAPAN", naomi_game_id))
else if (gameId == "OUTTRIGGER JAPAN")
{
// FIXME need default flash
write_naomi_flash(0x21a, node == -1 ? 0 : 1); // network on
write_naomi_flash(0x21b, node); // node id
}
else if (!strcmp("SLASHOUT JAPAN VERSION", naomi_game_id))
else if (gameId == "SLASHOUT JAPAN VERSION")
{
write_naomi_eeprom(0x30, node + 1);
}
else if (!strcmp("SPAWN JAPAN", naomi_game_id))
else if (gameId == "SPAWN JAPAN")
{
write_naomi_eeprom(0x44, node == -1 ? 0 : 1); // network on
write_naomi_eeprom(0x30, node <= 0 ? 1 : 2); // node id
}
else if (!strcmp("SPIKERS BATTLE JAPAN VERSION", naomi_game_id))
else if (gameId == "SPIKERS BATTLE JAPAN VERSION")
{
write_naomi_eeprom(0x30, node == -1 ? 0
: node == 0 ? 1 : 2);
}
else if (!strcmp("VIRTUAL-ON ORATORIO TANGRAM", naomi_game_id))
else if (gameId == "VIRTUAL-ON ORATORIO TANGRAM")
{
write_naomi_eeprom(0x45, node == -1 ? 3
: node == 0 ? 0 : 1);
write_naomi_eeprom(0x47, node == 0 ? 0 : 1);
}
else if (!strcmp("WAVE RUNNER GP", naomi_game_id))
else if (gameId == "WAVE RUNNER GP")
{
write_naomi_eeprom(0x33, node);
write_naomi_eeprom(0x35, node == -1 ? 2
: node == 0 ? 0 : 1);
}
else if (!strcmp("WORLD KICKS", naomi_game_id))
else if (gameId == "WORLD KICKS")
{
// FIXME need default flash
write_naomi_flash(0x224, node == -1 ? 0 : 1); // network on
write_naomi_flash(0x220, node == 0 ? 0 : 1); // node id
}
else if (!strcmp("CLUB KART IN JAPAN", naomi_game_id))
else if (gameId == "CLUB KART IN JAPAN")
{
write_naomi_eeprom(0x34, node + 1); // also 03 = satellite
}
else if (!strcmp("INITIAL D", naomi_game_id)
|| !strcmp("INITIAL D Ver.2", naomi_game_id)
|| !strcmp("INITIAL D Ver.3", naomi_game_id))
else if (gameId == "INITIAL D"
|| gameId == "INITIAL D Ver.2"
|| gameId == "INITIAL D Ver.3")
{
write_naomi_eeprom(0x34, node == -1 ? 0x02 : node == 0 ? 0x12 : 0x22);
}
else if (!strcmp("THE KING OF ROUTE66", naomi_game_id))
else if (gameId == "THE KING OF ROUTE66")
{
// FIXME no input when linked
write_naomi_eeprom(0x3d, node == -1 ? 0x44 : node == 0 ? 0x54 : 0x64);
}
else if (!strcmp("MAXIMUM SPEED", naomi_game_id))
else if (gameId == "MAXIMUM SPEED")
{
configure_maxspeed_flash(node != -1, node == 0);
}
@ -397,7 +396,7 @@ bool NaomiNetworkSupported()
if (!config::NetworkEnable)
return false;
for (auto game : games)
if (!strcmp(game, naomi_game_id))
if (settings.content.gameId == game)
return true;
return false;

View File

@ -89,7 +89,7 @@ static inline void set_tcp_nodelay(sock_t fd)
#if defined(_WIN32)
struct protoent *tcp_proto = getprotobyname("TCP");
setsockopt(fd, tcp_proto->p_proto, TCP_NODELAY, (const char *)&optval, optlen);
#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
#elif !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__) && !defined(__OpenBSD__)
setsockopt(fd, SOL_TCP, TCP_NODELAY, (const void *)&optval, optlen);
#else
struct protoent *tcp_proto = getprotobyname("TCP");

View File

@ -48,8 +48,6 @@ extern "C" {
#include "types.h"
#include "picoppp.h"
#include "miniupnp.h"
#include "reios/reios.h"
#include "hw/naomi/naomi_cart.h"
#include "cfg/option.h"
#include "emulator.h"
@ -843,24 +841,14 @@ static void *pico_thread_func(void *)
// Find the network ports for the current game
const GamePortList *ports = nullptr;
std::string gameId;
if (settings.platform.isConsole())
{
gameId = std::string(ip_meta.product_number, sizeof(ip_meta.product_number));
gameId = trim_trailing_ws(gameId);
}
else
{
gameId = naomi_game_id;
}
for (u32 i = 0; i < ARRAY_SIZE(GamesPorts) && ports == nullptr; i++)
{
const auto& game = GamesPorts[i];
for (u32 j = 0; j < ARRAY_SIZE(game.gameId) && game.gameId[j] != nullptr; j++)
{
if (gameId == game.gameId[j])
if (settings.content.gameId == game.gameId[j])
{
NOTICE_LOG(MODEM, "Found network ports for game %s", gameId.c_str());
NOTICE_LOG(MODEM, "Found network ports for game %s", settings.content.gameId.c_str());
ports = &game;
break;
}
@ -869,7 +857,8 @@ static void *pico_thread_func(void *)
// Web TV requires the VJ compression option, which picotcp doesn't support.
// This hack allows WebTV to connect although the correct fix would
// be to implement VJ compression.
dont_reject_opt_vj_hack = gameId == "6107117" || gameId == "610-7390" || gameId == "610-7391" ? 1 : 0;
dont_reject_opt_vj_hack = settings.content.gameId == "6107117"
|| settings.content.gameId == "610-7390" || settings.content.gameId == "610-7391" ? 1 : 0;
std::future<MiniUPnP> upnp =
std::async(std::launch::async, [ports]() {

View File

@ -92,6 +92,9 @@ void flycast_term()
void dc_savestate(int index)
{
if (settings.network.online)
return;
Serializer ser;
dc_serialize(ser);

View File

@ -1018,7 +1018,7 @@ bool OpenGL4Renderer::renderFrame(int width, int height)
#ifndef LIBRETRO
else {
gl.ofbo.aspectRatio = getOutputFramebufferAspectRatio();
RenderLastFrame();
renderLastFrame();
}
#endif
glBindVertexArray(0);

View File

@ -667,7 +667,7 @@ void OpenGLRenderer::RenderFramebuffer(const FramebufferInfo& info)
drawQuad(gl.dcfb.tex, false, true);
}
#ifndef LIBRETRO
RenderLastFrame();
renderLastFrame();
#endif
DrawOSD(false);
@ -752,7 +752,7 @@ void writeFramebufferToVRAM()
glCheck();
}
bool OpenGLRenderer::RenderLastFrame()
bool OpenGLRenderer::renderLastFrame()
{
GlFramebuffer *framebuffer = gl.ofbo2.ready ? gl.ofbo2.framebuffer.get() : gl.ofbo.framebuffer.get();
if (framebuffer == nullptr)

View File

@ -1087,7 +1087,7 @@ void OpenGLRenderer::DrawOSD(bool clear_screen)
{
glcache.ClearColor(0.7f, 0.7f, 0.7f, 1.f);
glClear(GL_COLOR_BUFFER_BIT);
RenderLastFrame();
renderLastFrame();
glViewport(0, 0, settings.display.width, settings.display.height);
}
@ -1098,7 +1098,6 @@ void OpenGLRenderer::DrawOSD(bool clear_screen)
#endif
SetupOSDVBO();
verify(glIsProgram(gl.OSD_SHADER.program));
glcache.UseProgram(gl.OSD_SHADER.program);
float scale_h = settings.display.height / 480.f;
@ -1401,7 +1400,7 @@ bool OpenGLRenderer::renderFrame(int width, int height)
#ifndef LIBRETRO
else {
gl.ofbo.aspectRatio = getOutputFramebufferAspectRatio();
RenderLastFrame();
renderLastFrame();
}
#endif
bindVertexArray(0);

View File

@ -414,7 +414,14 @@ struct OpenGLRenderer : Renderer
void RenderFramebuffer(const FramebufferInfo& info) override;
bool RenderLastFrame() override;
bool RenderLastFrame() override
{
saveCurrentFramebuffer();
bool ret = renderLastFrame();
restoreCurrentFramebuffer();
return ret;
}
void DrawOSD(bool clear_screen) override;
@ -451,6 +458,8 @@ protected:
glBindFramebuffer(GL_FRAMEBUFFER, gl.ofbo.origFbo);
}
bool renderLastFrame();
private:
bool renderFrame(int width, int height);

View File

@ -2665,20 +2665,11 @@ static void gui_network_start()
ImGui::Text("Starting...");
try {
if (networkStatus.get())
{
gui_state = GuiState::Closed;
}
else
{
emu.unloadGame();
gui_state = GuiState::Main;
}
gui_stop_game();
} catch (const FlycastException& e) {
if (NetworkHandshake::instance != nullptr)
NetworkHandshake::instance->stop();
emu.unloadGame();
gui_error(e.what());
gui_state = GuiState::Main;
gui_stop_game(e.what());
}
}
else
@ -2700,8 +2691,7 @@ static void gui_network_start()
}
catch (const FlycastException& e) {
}
emu.unloadGame();
gui_state = GuiState::Main;
gui_stop_game();
}
ImGui::PopStyleVar();
@ -2759,12 +2749,10 @@ static void gui_display_loadscreen()
}
} catch (const FlycastException& ex) {
ERROR_LOG(BOOT, "%s", ex.what());
gui_error(ex.what());
#ifdef TEST_AUTOMATION
die("Game load failed");
#endif
emu.unloadGame();
gui_state = GuiState::Main;
gui_stop_game(ex.what());
}
ImGui::PopStyleVar();

View File

@ -95,7 +95,10 @@ void mainui_loop()
fc_profiler::startThread("main");
mainui_rend_frame();
imguiDriver->present();
if (imguiDriver == nullptr)
forceReinit = true;
else
imguiDriver->present();
if (config::RendererType != currentRenderer || forceReinit)
{

View File

@ -578,9 +578,9 @@ void VulkanContext::CreateSwapChain()
vk::Extent2D swapchainExtent;
if (surfaceCapabilities.currentExtent.width == std::numeric_limits<uint32_t>::max())
{
// If the surface size is undefined, the size is set to the size of the images requested.
swapchainExtent.width = std::min(std::max(640u, surfaceCapabilities.minImageExtent.width), surfaceCapabilities.maxImageExtent.width);
swapchainExtent.height = std::min(std::max(480u, surfaceCapabilities.minImageExtent.height), surfaceCapabilities.maxImageExtent.height);
// If the surface size is undefined, use the current display size
swapchainExtent.width = std::min(std::max((u32)settings.display.width, surfaceCapabilities.minImageExtent.width), surfaceCapabilities.maxImageExtent.width);
swapchainExtent.height = std::min(std::max((u32)settings.display.height, surfaceCapabilities.minImageExtent.height), surfaceCapabilities.maxImageExtent.height);
}
else
{

View File

@ -122,7 +122,7 @@ public:
nameInfo.objectType = objectType;
nameInfo.object = object;
nameInfo.pObjectName = name.c_str();
vkDebugMarkerSetObjectNameEXT((VkDevice)*device, &nameInfo);
VULKAN_HPP_DEFAULT_DISPATCHER.vkDebugMarkerSetObjectNameEXT((VkDevice)*device, &nameInfo);
}
#endif
constexpr static int VENDOR_AMD = 0x1022;

View File

@ -95,6 +95,7 @@ public:
texCommandPool.Term();
fbCommandPool.Term();
framebufferTextures.clear();
framebufferTexIndex = 0;
shaderManager.term();
}
@ -144,8 +145,6 @@ public:
CheckFogTexture();
CheckPaletteTexture();
texCommandBuffer.end();
if (!ctx->rend.isRTT)
framebufferRendered = false;
}
void ReInitOSD()
@ -205,9 +204,11 @@ public:
void RenderFramebuffer(const FramebufferInfo& info) override
{
framebufferTexIndex = (framebufferTexIndex + 1) % GetContext()->GetSwapChainSize();
if (framebufferTextures.size() != GetContext()->GetSwapChainSize())
framebufferTextures.resize(GetContext()->GetSwapChainSize());
std::unique_ptr<Texture>& curTexture = framebufferTextures[GetContext()->GetCurrentImageIndex()];
std::unique_ptr<Texture>& curTexture = framebufferTextures[framebufferTexIndex];
if (!curTexture)
{
curTexture = std::unique_ptr<Texture>(new Texture());
@ -293,13 +294,14 @@ protected:
bool presentFramebuffer()
{
if (GetContext()->GetCurrentImageIndex() >= (int)framebufferTextures.size())
if (framebufferTexIndex >= (int)framebufferTextures.size())
return false;
Texture *fbTexture = framebufferTextures[GetContext()->GetCurrentImageIndex()].get();
Texture *fbTexture = framebufferTextures[framebufferTexIndex].get();
if (fbTexture == nullptr)
return false;
GetContext()->PresentFrame(fbTexture->GetImage(), fbTexture->GetImageView(), fbTexture->getSize(),
getDCFramebufferAspectRatio());
framebufferRendered = false;
return true;
}
@ -308,6 +310,7 @@ protected:
std::unique_ptr<Texture> paletteTexture;
CommandPool texCommandPool;
std::vector<std::unique_ptr<Texture>> framebufferTextures;
int framebufferTexIndex = 0;
OSDPipeline osdPipeline;
std::unique_ptr<Texture> vjoyTexture;
std::unique_ptr<BufferData> osdBuffer;

View File

@ -7,7 +7,7 @@
#include <SDL_syswm.h>
#endif
#include <SDL_video.h>
#if defined(__APPLE__) && defined(USE_VULKAN)
#if defined(USE_VULKAN)
#include <SDL_vulkan.h>
#endif
#endif
@ -29,6 +29,7 @@
#endif
static SDL_Window* window = NULL;
static u32 windowFlags;
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 480
@ -287,6 +288,17 @@ void input_sdl_handle()
|| event.window.event == SDL_WINDOWEVENT_MINIMIZED
|| event.window.event == SDL_WINDOWEVENT_MAXIMIZED)
{
#ifdef USE_VULKAN
if (windowFlags & SDL_WINDOW_VULKAN)
SDL_Vulkan_GetDrawableSize(window, &settings.display.width, &settings.display.height);
else
#endif
#ifdef USE_OPENGL
if (windowFlags & SDL_WINDOW_OPENGL)
SDL_GL_GetDrawableSize(window, &settings.display.width, &settings.display.height);
else
#endif
SDL_GetWindowSize(window, &settings.display.width, &settings.display.height);
GraphicsContext::Instance()->resize();
}
else if (event.window.event == SDL_WINDOWEVENT_FOCUS_GAINED)
@ -468,6 +480,7 @@ HWND getNativeHwnd()
bool sdl_recreate_window(u32 flags)
{
windowFlags = flags;
#ifdef _WIN32
//Enable HiDPI mode in Windows
typedef enum PROCESS_DPI_AWARENESS {

View File

@ -51,9 +51,14 @@
#endif
#include "profiler/fc_profiler.h"
#if defined(USE_SDL) || defined(DEF_CONSOLE)
#include <nowide/args.hpp>
#endif
#include <windows.h>
#include <windowsx.h>
#if !defined(USE_SDL) && !defined(DEF_CONSOLE)
static PCHAR*
commandLineToArgvA(
PCHAR CmdLine,
@ -147,6 +152,7 @@ static PCHAR*
(*_argc) = argc;
return argv;
}
#endif
#ifndef USE_SDL
@ -844,10 +850,12 @@ int remove(char const *name)
}
}
#endif
extern "C" int SDL_main(int argc, char* argv[])
#ifdef USE_SDL
int main(int argc, char* argv[])
{
nowide::args _(argc, argv);
#elif defined(DEF_CONSOLE)
// DEF_CONSOLE allows you to override linker subsystem and therefore default console
@ -856,6 +864,7 @@ extern "C" int SDL_main(int argc, char* argv[])
int main(int argc, char** argv)
{
nowide::args _(argc, argv);
#else
#pragma comment(linker, "/subsystem:windows")

View File

@ -82,7 +82,7 @@ bool EGLGraphicsContext::init()
}
ANativeWindow_setBuffersGeometry((ANativeWindow *)window, 0, 0, format);
#endif
surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)window, NULL);
surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)window, nullptr);
if (surface == EGL_NO_SURFACE)
{
@ -102,7 +102,7 @@ bool EGLGraphicsContext::init()
EGLint contextAttrs[] = { EGL_CONTEXT_MAJOR_VERSION_KHR, 3,
EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR, EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR,
EGL_NONE };
context = eglCreateContext(display, config, NULL, contextAttrs);
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttrs);
if (context != EGL_NO_CONTEXT)
{
makeCurrent();
@ -121,7 +121,7 @@ bool EGLGraphicsContext::init()
EGLint contextAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2 , EGL_NONE };
context = eglCreateContext(display, config, NULL, contextAttrs);
context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttrs);
if (context == EGL_NO_CONTEXT)
{
@ -171,7 +171,7 @@ bool EGLGraphicsContext::init()
void EGLGraphicsContext::term()
{
preTerm();
eglMakeCurrent(display, NULL, NULL, EGL_NO_CONTEXT);
eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (context != EGL_NO_CONTEXT)
eglDestroyContext(display, context);
if (surface != EGL_NO_SURFACE)

View File

@ -35,7 +35,6 @@ GraphicsContext *GraphicsContext::instance;
void initRenderApi(void *window, void *display)
{
bool dx11Failed = false;
#ifdef USE_VULKAN
if (isVulkan(config::RendererType))
{
@ -48,6 +47,7 @@ void initRenderApi(void *window, void *display)
}
#endif
#ifdef USE_DX11
bool dx11Failed = false;
if (config::RendererType == RenderType::DirectX11 || config::RendererType == RenderType::DirectX11_OIT)
{
theDX11Context.setWindow(window, display);

View File

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id 'com.android.application' version '7.4.0' apply false
id 'com.android.library' version '7.4.0' apply false
id 'com.android.application' version '7.4.1' apply false
id 'com.android.library' version '7.4.1' apply false
}
task clean(type: Delete) {

View File

@ -341,14 +341,19 @@ extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_setupMic(J
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_pause(JNIEnv *env,jobject obj)
{
if (emu.running())
{
stopEmu();
game_started = true; // restart when resumed
if (config::AutoSaveState)
dc_savestate(config::SavestateSlot);
}
gui_save();
if (config::GGPOEnable)
{
stopEmu();
gui_stop_game();
}
else if (emu.running())
{
stopEmu();
game_started = true; // restart when resumed
if (config::AutoSaveState)
dc_savestate(config::SavestateSlot);
}
gui_save();
}
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_resume(JNIEnv *env,jobject obj)
@ -359,10 +364,8 @@ extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_resume(JNI
extern "C" JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_stop(JNIEnv *env,jobject obj)
{
stopEmu();
emu.unloadGame();
gui_state = GuiState::Main;
game_started = false;
stopEmu();
gui_stop_game();
}
static void *render_thread_func(void *)

File diff suppressed because it is too large Load Diff

View File

@ -36,7 +36,7 @@ Option<bool> FullMMU("");
Option<bool> ForceWindowsCE(CORE_OPTION_NAME "_force_wince");
Option<bool> AutoLoadState("");
Option<bool> AutoSaveState("");
Option<int> SavestateSlot("");
Option<int, false> SavestateSlot("");
Option<bool> ForceFreePlay(CORE_OPTION_NAME "_force_freeplay", true);
// Sound