From f5a60ee5f18c18508db3e29e99bbcd650d3978e0 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 8 Apr 2019 15:54:37 +0200 Subject: [PATCH 01/10] New option to display VMUs in game --- core/nullDC.cpp | 3 +++ core/rend/gui.cpp | 55 +++++++++++++++++++++++++++++++++-------------- core/types.h | 1 + 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 844e38ba9..87155fefc 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -517,6 +517,7 @@ void InitSettings() settings.rend.ScreenScaling = 100; settings.rend.ScreenStretching = 100; settings.rend.Fog = true; + settings.rend.FloatVMUs = false; settings.pvr.ta_skip = 0; settings.pvr.rend = 0; @@ -601,6 +602,7 @@ void LoadSettings(bool game_specific) settings.rend.ScreenScaling = min(max(1, settings.rend.ScreenScaling), 100); settings.rend.ScreenStretching = cfgLoadInt(config_section, "rend.ScreenStretching", settings.rend.ScreenStretching); settings.rend.Fog = cfgLoadBool(config_section, "rend.Fog", settings.rend.Fog); + settings.rend.FloatVMUs = cfgLoadBool(config_section, "rend.FloatVMUs", settings.rend.FloatVMUs); settings.pvr.ta_skip = cfgLoadInt(config_section, "ta.skip", settings.pvr.ta_skip); settings.pvr.rend = cfgLoadInt(config_section, "pvr.rend", settings.pvr.rend); @@ -726,6 +728,7 @@ void SaveSettings() cfgSaveInt("config", "rend.ScreenScaling", settings.rend.ScreenScaling); cfgSaveInt("config", "rend.ScreenStretching", settings.rend.ScreenStretching); cfgSaveBool("config", "rend.Fog", settings.rend.Fog); + cfgSaveBool("config", "rend.FloatVMUs", settings.rend.FloatVMUs); cfgSaveInt("config", "ta.skip", settings.pvr.ta_skip); cfgSaveInt("config", "pvr.rend", settings.pvr.rend); diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 6c096d755..7a0fb107d 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -294,7 +294,9 @@ static void gui_display_commands() if (!settings_opening) ImGui_ImplOpenGL3_DrawBackground(); - display_vmus(); + if (!settings.rend.FloatVMUs) + // If floating VMUs, they are already visible on the background + display_vmus(); ImGui::SetNextWindowPos(ImVec2(screen_width / 2.f, screen_height / 2.f), ImGuiCond_Always, ImVec2(0.5f, 0.5f)); ImGui::SetNextWindowSize(ImVec2(330 * scaling, 0)); @@ -617,6 +619,8 @@ void directory_selected_callback(bool cancelled, std::string selection) static void gui_display_settings() { + static bool maple_devices_changed; + ImGui_Impl_NewFrame(); ImGui::NewFrame(); @@ -639,10 +643,14 @@ static void gui_display_settings() gui_state = Commands; else gui_state = Main; + if (maple_devices_changed) + { + maple_devices_changed = false; #if DC_PLATFORM == DC_PLATFORM_DREAMCAST - maple_ReconnectDevices(); - reset_vmus(); + maple_ReconnectDevices(); + reset_vmus(); #endif + } SaveSettings(); } if (game_started) @@ -813,7 +821,10 @@ static void gui_display_settings() { bool is_selected = settings.input.maple_devices[bus] == maple_device_type_from_index(i); if (ImGui::Selectable(maple_device_types[i], &is_selected)) + { settings.input.maple_devices[bus] = maple_device_type_from_index(i); + maple_devices_changed = true; + } if (is_selected) ImGui::SetItemDefaultFocus(); } @@ -831,7 +842,10 @@ static void gui_display_settings() { bool is_selected = settings.input.maple_expansion_devices[bus][port] == maple_expansion_device_type_from_index(i); if (ImGui::Selectable(maple_expansion_device_types[i], &is_selected)) + { settings.input.maple_expansion_devices[bus][port] = maple_expansion_device_type_from_index(i); + maple_devices_changed = true; + } if (is_selected) ImGui::SetItemDefaultFocus(); } @@ -949,6 +963,9 @@ static void gui_display_settings() ImGui::Checkbox("Show FPS Counter", &settings.rend.ShowFPS); ImGui::SameLine(); ShowHelpMarker("Show on-screen frame/sec counter"); + ImGui::Checkbox("Show VMU in game", &settings.rend.FloatVMUs); + ImGui::SameLine(); + ShowHelpMarker("Show the VMU LCD screens while in game"); ImGui::SliderInt("Scaling", (int *)&settings.rend.ScreenScaling, 1, 100); ImGui::SameLine(); ShowHelpMarker("Downscaling factor relative to native screen resolution. Higher is better"); @@ -1459,26 +1476,32 @@ void gui_display_osd() if (osd_message.empty()) { message = getFPSNotification(); - if (message.empty()) - return; } else message = osd_message; - ImGui_Impl_NewFrame(); - ImGui::NewFrame(); + if (!message.empty() || settings.rend.FloatVMUs) + { + ImGui_Impl_NewFrame(); + ImGui::NewFrame(); - ImGui::SetNextWindowBgAlpha(0); - ImGui::SetNextWindowPos(ImVec2(0, screen_height), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner + if (!message.empty()) + { + ImGui::SetNextWindowBgAlpha(0); + ImGui::SetNextWindowPos(ImVec2(0, screen_height), ImGuiCond_Always, ImVec2(0.f, 1.f)); // Lower left corner - ImGui::Begin("##osd", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav - | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground); - ImGui::SetWindowFontScale(1.5); - ImGui::TextColored(ImVec4(1, 1, 0, 0.7), "%s", message.c_str()); - ImGui::End(); + ImGui::Begin("##osd", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoNav + | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoBackground); + ImGui::SetWindowFontScale(1.5); + ImGui::TextColored(ImVec4(1, 1, 0, 0.7), "%s", message.c_str()); + ImGui::End(); + } + if (settings.rend.FloatVMUs) + display_vmus(); - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + } } void gui_open_onboarding() diff --git a/core/types.h b/core/types.h index bfd779ef8..2479fef25 100644 --- a/core/types.h +++ b/core/types.h @@ -635,6 +635,7 @@ struct settings_t int ScreenScaling; // in percent. 50 means half the native resolution int ScreenStretching; // in percent. 150 means stretch from 4/3 to 6/3 bool Fog; + bool FloatVMUs; } rend; struct From cf7434a9e6609c15534335baa3461eaa7e87a0fd Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 8 Apr 2019 17:09:10 +0200 Subject: [PATCH 02/10] atomiswave: fix coin input. Subclass sega controller instead of #def --- core/hw/maple/maple_cfg.cpp | 2 +- core/hw/maple/maple_devs.cpp | 118 ++++++++++++++++++++++------------- 2 files changed, 77 insertions(+), 43 deletions(-) diff --git a/core/hw/maple/maple_cfg.cpp b/core/hw/maple/maple_cfg.cpp index f14562411..fd6c18d18 100644 --- a/core/hw/maple/maple_cfg.cpp +++ b/core/hw/maple/maple_cfg.cpp @@ -115,7 +115,7 @@ bool maple_atomiswave_coin_chute(int slot) { for (int i = 0; i < 16; i++) { - if (awave_button_mapping[i] == AWAVE_COIN_KEY && (kcode[slot] & (1 << i)) == 0) + if ((kcode[slot] & (1 << i)) == 0 && awave_button_mapping[i] == AWAVE_COIN_KEY) return true; } return false; diff --git a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp index a26a3f01a..8ed632777 100755 --- a/core/hw/maple/maple_devs.cpp +++ b/core/hw/maple/maple_devs.cpp @@ -199,6 +199,35 @@ struct maple_base: maple_device */ struct maple_sega_controller: maple_base { + virtual u32 get_capabilities() { + // byte 0: 0 0 0 0 0 0 0 0 + // byte 1: 0 0 a5 a4 a3 a2 a1 a0 + // byte 2: R2 L2 D2 U2 D X Y Z + // byte 3: R L D U St A B C + + return 0xfe060f00; // 4 analog axes (0-3) X Y A B Start U D L R + } + + virtual u32 process_kcode(u32 kcode) { + return kcode; + } + + virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) { + switch (index) + { + case 0: + return pjs.trigger[PJTI_R]; // Right trigger + case 1: + return pjs.trigger[PJTI_L]; // Left trigger + case 2: + return pjs.joy[PJAI_X1]; // Stick X + case 3: + return pjs.joy[PJAI_Y1]; // Stick Y + default: + return 0x80; // unused + } + } + virtual MapleDeviceType get_device_type() { return MDT_SegaController; @@ -216,14 +245,9 @@ struct maple_sega_controller: maple_base //struct data //3*4 -#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE - w32(0xfe060f00); -#else - // More buttons, more digital axes - w32(0xff663f00); -#endif - w32( 0); - w32( 0); + w32(get_capabilities()); + w32(0); + w32(0); //1 area code w8(0xFF); @@ -254,54 +278,28 @@ struct maple_sega_controller: maple_base //4 w32(MFID_0_Input); -#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE //state data //2 key code - w16(pjs.kcode); + w16(process_kcode(pjs.kcode)); //triggers //1 R - w8(pjs.trigger[PJTI_R]); + w8(get_analog_axis(0, pjs)); //1 L - w8(pjs.trigger[PJTI_L]); + w8(get_analog_axis(1, pjs)); //joyx //1 - w8(pjs.joy[PJAI_X1]); + w8(get_analog_axis(2, pjs)); //joyy //1 - w8(pjs.joy[PJAI_Y1]); + w8(get_analog_axis(3, pjs)); //not used //1 - w8(0x80); + w8(get_analog_axis(4, pjs)); //1 - w8(0x80); -#else - //state data - //2 key code - w16(pjs.kcode | AWAVE_TRIGGER_KEY); - - //not used - //1 - w8(0); - //1 - w8(0); - - //joyx - //1 - w8(pjs.joy[PJAI_X1]); - //joyy - //1 - w8(pjs.joy[PJAI_Y1]); - - //joyrx - //1 - w8(pjs.joy[PJAI_X2]); - //joyry - //1 - w8(pjs.joy[PJAI_Y2]); -#endif + w8(get_analog_axis(5, pjs)); } return MDRS_DataTransfer; @@ -313,6 +311,38 @@ struct maple_sega_controller: maple_base } }; +struct maple_atomiswave_controller: maple_sega_controller +{ + virtual u32 get_capabilities() { + // byte 0: 0 0 0 0 0 0 0 0 + // byte 1: 0 0 a5 a4 a3 a2 a1 a0 + // byte 2: R2 L2 D2 U2 D X Y Z + // byte 3: R L D U St A B C + + return 0xff663f00; // 6 analog axes, X Y L2/D2(?) A B C Start U D L R + } + + virtual u32 process_kcode(u32 kcode) { + return kcode | AWAVE_TRIGGER_KEY; + } + + virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) { + switch (index) + { + case 2: + return pjs.joy[PJAI_X1]; + case 3: + return pjs.joy[PJAI_Y1]; + case 4: + return pjs.joy[PJAI_X2]; + case 5: + return pjs.joy[PJAI_Y2]; + default: + return 0x80; + } + } +}; + /* Sega Dreamcast Visual Memory Unit This is pretty much done (?) @@ -2592,7 +2622,11 @@ maple_device* maple_Create(MapleDeviceType type) switch(type) { case MDT_SegaController: - rv=new maple_sega_controller(); +#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE + rv = new maple_sega_controller(); +#else + rv = new maple_atomiswave_controller(); +#endif break; case MDT_Microphone: From b87a1cc31a3f7918e204ab3ac8666f54dc1f6dac Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 8 Apr 2019 19:14:55 +0200 Subject: [PATCH 03/10] atomiswave: setup maple controls depending on game more lightgun fixes but still not working --- core/hw/maple/maple_cfg.cpp | 29 ++++++++++++++++++++--------- core/hw/maple/maple_devs.cpp | 31 +++++++++++++++++++------------ core/nullDC.cpp | 12 ++++++++---- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/core/hw/maple/maple_cfg.cpp b/core/hw/maple/maple_cfg.cpp index fd6c18d18..4f8c9d2d6 100644 --- a/core/hw/maple/maple_cfg.cpp +++ b/core/hw/maple/maple_cfg.cpp @@ -149,16 +149,27 @@ void mcfg_CreateAtomisWaveControllers() // Game needs analog axes mcfg_Create(MDT_SegaController, 2, 5, 0); mcfg_Create(MDT_SegaController, 3, 5, 1); + // Faster Than Speed needs 1 std controller on port 0 (digital inputs) and one on port 2 (analog axes) + // Maximum Speed same + } + else if (settings.input.JammaSetup == 1) + { + // 4 players + mcfg_Create(MDT_SegaController, 2, 5); + mcfg_Create(MDT_SegaController, 3, 5); + } + else if (settings.input.JammaSetup == 5) + { + // Clay Challenge needs 2 std controllers on port 0 & 1 (digital in) and light guns on port 2 & 3 + // Sports Shooting same + mcfg_Create(MDT_LightGun, 2, 5, 0); + mcfg_Create(MDT_LightGun, 3, 5, 1); + } + else if (settings.input.JammaSetup == 3) + { + // Sega Bass Fishing Challenge needs a mouse (track-ball) on port 2 + mcfg_Create(MDT_Mouse, 2, 5, 0); } -// mcfg_Create(MDT_LightGun, 2, 5, 0); -// mcfg_Create(MDT_LightGun, 3, 5, 1); -// mcfg_Create(MDT_Mouse, 2, 5, 0); - // Guilty Gear Isuka (4P) needs 4 std controllers - // Faster Than Speed needs 1 std controller on port 0 (digital inputs) and one on port 2 (analog axes) - // Maximum Speed same - // Clay Challenge needs 2 std controllers on port 0 & 1 (digital in) and light guns on port 2 & 3 - // Sports Shooting same - // Sega Bass Fishing Challenge needs a mouse (track-ball) on port 3 } void mcfg_CreateDevices() diff --git a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp index 8ed632777..bb65dde69 100755 --- a/core/hw/maple/maple_devs.cpp +++ b/core/hw/maple/maple_devs.cpp @@ -313,7 +313,7 @@ struct maple_sega_controller: maple_base struct maple_atomiswave_controller: maple_sega_controller { - virtual u32 get_capabilities() { + virtual u32 get_capabilities() override { // byte 0: 0 0 0 0 0 0 0 0 // byte 1: 0 0 a5 a4 a3 a2 a1 a0 // byte 2: R2 L2 D2 U2 D X Y Z @@ -322,11 +322,11 @@ struct maple_atomiswave_controller: maple_sega_controller return 0xff663f00; // 6 analog axes, X Y L2/D2(?) A B C Start U D L R } - virtual u32 process_kcode(u32 kcode) { + virtual u32 process_kcode(u32 kcode) override { return kcode | AWAVE_TRIGGER_KEY; } - virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) { + virtual u32 get_analog_axis(int index, const PlainJoystickState &pjs) override { switch (index) { case 2: @@ -1329,6 +1329,10 @@ struct maple_mouse : maple_base struct maple_lightgun : maple_base { + virtual u32 process_kcode(u32 kcode) { + return kcode | 0xFF01; + } + virtual MapleDeviceType get_device_type() { return MDT_LightGun; @@ -1377,21 +1381,13 @@ struct maple_lightgun : maple_base PlainJoystickState pjs; config->GetInput(&pjs); - // Also use the mouse buttons - if (!(mo_buttons & 4)) // Left button - pjs.kcode &= ~4; // A - if (!(mo_buttons & 2)) // Right button - pjs.kcode &= ~2; // B - if (!(mo_buttons & 8)) // Wheel button - pjs.kcode &= ~8; // Start - //caps //4 w32(MFID_0_Input); //state data //2 key code - w16(pjs.kcode | 0xFF01); + w16(process_kcode(pjs.kcode)); //not used //2 @@ -1417,6 +1413,13 @@ struct maple_lightgun : maple_base } }; +struct atomiswave_lightgun : maple_lightgun +{ + virtual u32 process_kcode(u32 kcode) override { + return (kcode & AWAVE_TRIGGER_KEY) == 0 ? ~AWAVE_BTN0_KEY : ~0; + } +}; + extern u16 kcode[4]; extern s8 joyx[4],joyy[4]; extern u8 rt[4], lt[4]; @@ -2650,7 +2653,11 @@ maple_device* maple_Create(MapleDeviceType type) break; case MDT_LightGun: +#if DC_PLATFORM != DC_PLATFORM_ATOMISWAVE rv = new maple_lightgun(); +#else + rv = new atomiswave_lightgun(); +#endif break; case MDT_NaomiJamma: diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 87155fefc..dbbfe5325 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -213,12 +213,14 @@ void LoadSpecialSettings() printf("Enabling JVS rotary encoders for game %s\n", naomi_game_id); settings.input.JammaSetup = 2; } - else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id)) + else if (!strcmp("POWER STONE 2 JAPAN", naomi_game_id) // Naomi + || !strcmp("GUILTY GEAR isuka", naomi_game_id)) // AW { printf("Enabling 4-player setup for game %s\n", naomi_game_id); settings.input.JammaSetup = 1; } - else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id)) + else if (!strcmp("SEGA MARINE FISHING JAPAN", naomi_game_id) + || !strcmp(naomi_game_id, "BASS FISHING SIMULATOR VER.A")) // AW { printf("Enabling specific JVS setup for game %s\n", naomi_game_id); settings.input.JammaSetup = 3; @@ -228,9 +230,11 @@ void LoadSpecialSettings() printf("Enabling specific JVS setup for game %s\n", naomi_game_id); settings.input.JammaSetup = 4; } - else if (!strcmp("NINJA ASSAULT", naomi_game_id)) + else if (!strcmp("NINJA ASSAULT", naomi_game_id) + || !strcmp(naomi_game_id, "Sports Shooting USA") // AW + || !strcmp(naomi_game_id, "SEGA CLAY CHALLENGE")) // AW { - printf("Enabling specific JVS setup for game %s\n", naomi_game_id); + printf("Enabling lightgun setup for game %s\n", naomi_game_id); settings.input.JammaSetup = 5; } else if (!strcmp(" BIOHAZARD GUN SURVIVOR2", naomi_game_id)) From 0a6f503efcb712d9d53b7f6530f1d8c67802d8be Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 8 Apr 2019 21:51:59 +0200 Subject: [PATCH 04/10] Don't use screen stretching parameter for RTT --- core/rend/gl4/gles.cpp | 28 ++++++++++++++++++++-------- core/rend/gles/gles.cpp | 27 +++++++++++++++++++-------- 2 files changed, 39 insertions(+), 16 deletions(-) diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 93700f20b..73330cc66 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -661,17 +661,29 @@ static bool RenderFrame() /* Handle Dc to screen scaling */ - float screen_scaling = is_rtt ? 1.f : settings.rend.ScreenScaling / 100.f; + float screen_scaling = settings.rend.ScreenScaling / 100.f; float screen_stretching = settings.rend.ScreenStretching / 100.f; - float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0); - float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2); + float dc2s_scale_h; + float ds2s_offs_x; - //-1 -> too much to left - gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; - gl4ShaderUniforms.scale_coefs[1] = (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512 - gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width; - gl4ShaderUniforms.scale_coefs[3] = (is_rtt ? 1 : -1); + if (is_rtt) + { + gl4ShaderUniforms.scale_coefs[0] = 2.0f / dc_width; + gl4ShaderUniforms.scale_coefs[1] = 2.0f / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512 + gl4ShaderUniforms.scale_coefs[2] = 1; + gl4ShaderUniforms.scale_coefs[3] = 1; + } + else + { + dc2s_scale_h = screen_height / 480.0; + ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2; + //-1 -> too much to left + gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; + gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_height; + gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width; + gl4ShaderUniforms.scale_coefs[3] = -1; + } gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale; diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index fad89106d..b16274d99 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -1681,15 +1681,26 @@ bool RenderFrame() float screen_stretching = settings.rend.ScreenStretching / 100.f; float screen_scaling = settings.rend.ScreenScaling / 100.f; - float dc2s_scale_h = is_rtt ? (screen_width / dc_width) : (screen_height / 480.0); - float ds2s_offs_x = is_rtt ? 0 : ((screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2); - - //-1 -> too much to left - ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; - ShaderUniforms.scale_coefs[1]= (is_rtt ? 2 : -2) / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512 - ShaderUniforms.scale_coefs[2]= 1 - 2 * ds2s_offs_x / screen_width; - ShaderUniforms.scale_coefs[3]= (is_rtt ? 1 : -1); + float dc2s_scale_h; + float ds2s_offs_x; + if (is_rtt) + { + ShaderUniforms.scale_coefs[0] = 2.0f / dc_width; + ShaderUniforms.scale_coefs[1] = 2.0f / dc_height; // FIXME CT2 needs 480 here instead of dc_height=512 + ShaderUniforms.scale_coefs[2] = 1; + ShaderUniforms.scale_coefs[3] = 1; + } + else + { + dc2s_scale_h = screen_height / 480.0; + ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2; + //-1 -> too much to left + ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; + ShaderUniforms.scale_coefs[1] = -2.0f / dc_height; + ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width; + ShaderUniforms.scale_coefs[3] = -1; + } ShaderUniforms.depth_coefs[0]=2/(vtx_max_fZ-vtx_min_fZ); ShaderUniforms.depth_coefs[1]=-vtx_min_fZ-1; From 1b04ef4cb11b286e7487683a8283512976579cb5 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Mon, 8 Apr 2019 22:09:22 +0200 Subject: [PATCH 05/10] Get rid of RTC in settings --- core/hw/aica/aica.cpp | 7 ++++++- core/hw/aica/aica_if.cpp | 20 +++++++++----------- core/hw/aica/aica_if.h | 3 ++- core/hw/sh4/interpr/sh4_interpreter.cpp | 2 +- core/nullDC.cpp | 3 --- core/types.h | 1 - 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/hw/aica/aica.cpp b/core/hw/aica/aica.cpp index 1eea5a03d..3cbf02bd9 100644 --- a/core/hw/aica/aica.cpp +++ b/core/hw/aica/aica.cpp @@ -1,4 +1,5 @@ #include "aica.h" +#include "aica_if.h" #include "sgc_if.h" #include "aica_mem.h" #include @@ -180,6 +181,7 @@ template void WriteAicaReg<2>(u32 reg,u32 data); s32 libAICA_Init() { init_mem(); + aica_Init(); verify(sizeof(*CommonData)==0x508); verify(sizeof(*DSPData)==0x15C8); @@ -203,9 +205,12 @@ s32 libAICA_Init() return rv_ok; } -void libAICA_Reset(bool m) +void libAICA_Reset(bool manual) { + if (!manual) + init_mem(); sgc_Init(); + aica_Reset(manual); } void libAICA_Term() diff --git a/core/hw/aica/aica_if.cpp b/core/hw/aica/aica_if.cpp index c717f8507..9ba65c0a7 100644 --- a/core/hw/aica/aica_if.cpp +++ b/core/hw/aica/aica_if.cpp @@ -18,6 +18,7 @@ u32 VREG;//video reg =P u32 ARMRST;//arm reset reg u32 rtc_EN=0; int dma_sched_id; +u32 RealTimeClock; u32 GetRTC_now() { @@ -39,9 +40,9 @@ u32 ReadMem_aica_rtc(u32 addr,u32 sz) switch( addr & 0xFF ) { case 0: - return settings.dreamcast.RTC>>16; + return RealTimeClock>>16; case 4: - return settings.dreamcast.RTC &0xFFFF; + return RealTimeClock &0xFFFF; case 8: return 0; } @@ -57,16 +58,16 @@ void WriteMem_aica_rtc(u32 addr,u32 data,u32 sz) case 0: if (rtc_EN) { - settings.dreamcast.RTC&=0xFFFF; - settings.dreamcast.RTC|=(data&0xFFFF)<<16; + RealTimeClock&=0xFFFF; + RealTimeClock|=(data&0xFFFF)<<16; rtc_EN=0; } return; case 4: if (rtc_EN) { - settings.dreamcast.RTC&=0xFFFF0000; - settings.dreamcast.RTC|= data&0xFFFF; + RealTimeClock&=0xFFFF0000; + RealTimeClock|= data&0xFFFF; //TODO: Clean the internal timer ? } return; @@ -153,15 +154,12 @@ void WriteMem_aica_reg(u32 addr,u32 data,u32 sz) //Init/res/term void aica_Init() { - //mmnnn ? gotta fill it w/ something + RealTimeClock = GetRTC_now(); } void aica_Reset(bool Manual) { - if (!Manual) - { - aica_ram.Zero(); - } + aica_Init(); } void aica_Term() diff --git a/core/hw/aica/aica_if.h b/core/hw/aica/aica_if.h index 8c6009a66..8c58b5326 100644 --- a/core/hw/aica/aica_if.h +++ b/core/hw/aica/aica_if.h @@ -3,6 +3,7 @@ extern u32 VREG; extern VArray2 aica_ram; +extern u32 RealTimeClock; u32 ReadMem_aica_rtc(u32 addr,u32 sz); void WriteMem_aica_rtc(u32 addr,u32 data,u32 sz); u32 ReadMem_aica_reg(u32 addr,u32 sz); @@ -17,4 +18,4 @@ void aica_Term(); void aica_sb_Init(); void aica_sb_Reset(bool Manual); -void aica_sb_Term(); \ No newline at end of file +void aica_sb_Term(); diff --git a/core/hw/sh4/interpr/sh4_interpreter.cpp b/core/hw/sh4/interpr/sh4_interpreter.cpp index ddc7d509c..5f48886a2 100644 --- a/core/hw/sh4/interpr/sh4_interpreter.cpp +++ b/core/hw/sh4/interpr/sh4_interpreter.cpp @@ -232,7 +232,7 @@ int AicaUpdate(int tag, int c, int j) int DreamcastSecond(int tag, int c, int j) { - settings.dreamcast.RTC++; + RealTimeClock++; #if 1 //HOST_OS==OS_WINDOWS prof_periodical(); diff --git a/core/nullDC.cpp b/core/nullDC.cpp index dbbfe5325..ffc4d524f 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -313,7 +313,6 @@ int dc_start_game(const char *path) { InitSettings(); LoadSettings(false); - settings.dreamcast.RTC = GetRTC_now(); // FIXME This shouldn't be in settings anymore #if DC_PLATFORM == DC_PLATFORM_DREAMCAST if (!settings.bios.UseReios) #endif @@ -351,7 +350,6 @@ int dc_start_game(const char *path) return 0; } - settings.dreamcast.RTC = GetRTC_now(); // FIXME This shouldn't be in settings anymore if (settings.bios.UseReios || !LoadRomFiles(get_readonly_data_path(DATA_PATH))) { #ifdef USE_REIOS @@ -491,7 +489,6 @@ void dc_exit() void InitSettings() { - settings.dreamcast.RTC = GetRTC_now(); settings.dynarec.Enable = true; settings.dynarec.idleskip = true; settings.dynarec.unstable_opt = false; diff --git a/core/types.h b/core/types.h index 2479fef25..c04f79442 100644 --- a/core/types.h +++ b/core/types.h @@ -656,7 +656,6 @@ struct settings_t struct { u32 cable; // 0 -> VGA, 1 -> VGA, 2 -> RGB, 3 -> TV - u32 RTC; u32 region; // 0 -> JP, 1 -> USA, 2 -> EU, 3 -> default u32 broadcast; // 0 -> NTSC, 1 -> PAL, 2 -> PAL/M, 3 -> PAL/N, 4 -> default u32 language; // 0 -> JP, 1 -> EN, 2 -> DE, 3 -> FR, 4 -> SP, 5 -> IT, 6 -> default From 37a533740bfbc056e03486bbf59f7ce01fffaf52 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 9 Apr 2019 10:37:49 +0200 Subject: [PATCH 06/10] win32: close thread handle when finished --- core/windows/winmain.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/windows/winmain.cpp b/core/windows/winmain.cpp index 68db4682c..b2a90b8ed 100644 --- a/core/windows/winmain.cpp +++ b/core/windows/winmain.cpp @@ -749,6 +749,7 @@ cThread::cThread(ThreadEntryFP* function,void* prm) void cThread::Start() { + verify(hThread == NULL); hThread=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)Entry,param,0,NULL); ResumeThread(hThread); } @@ -756,6 +757,8 @@ void cThread::Start() void cThread::WaitToEnd() { WaitForSingleObject(hThread,INFINITE); + CloseHandle(hThread); + hThread = NULL; } //End thread class From 1fa052987bebbfe58ea3b7ec28f6b8581fa340fb Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 9 Apr 2019 10:39:29 +0200 Subject: [PATCH 07/10] android: run renderer in a separate native thread fixes simultaneous gamepad button presses not being registered on some platforms --- .../java/com/reicast/emulator/emu/JNIdc.java | 3 +- .../reicast/emulator/emu/NativeGLView.java | 24 +------ .../reicast/src/main/jni/src/Android.cpp | 71 ++++++++++++------- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java index 6262fb27a..fef8b9dfa 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/JNIdc.java @@ -21,8 +21,7 @@ public final class JNIdc public static native int send(int cmd, int opt); public static native int data(int cmd, byte[] data); - public static native void rendinitNative(Surface surface, int w, int h); - public static native boolean rendframeNative(); + public static native void rendinitNative(Surface surface); public static native void rendinitJava(int w, int h); public static native boolean rendframeJava(); public static native void rendtermJava(); diff --git a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java index 3a7268401..383a8684a 100644 --- a/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java +++ b/shell/android-studio/reicast/src/main/java/com/reicast/emulator/emu/NativeGLView.java @@ -19,8 +19,6 @@ import com.reicast.emulator.NativeGLActivity; import com.reicast.emulator.config.Config; public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback { - private Handler handler = new Handler(); - private boolean surfaceReady = false; private boolean paused = false; VirtualJoystickDelegate vjoyDelegate; @@ -66,23 +64,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback if (NativeGLActivity.syms != null) JNIdc.data(1, NativeGLActivity.syms); - - startRendering(); - } - - private void startRendering() { - // Continuously render frames - handler.removeCallbacksAndMessages(null); - handler.postAtTime(new Runnable() { - @Override - public void run() { - if (!paused) - { - JNIdc.rendframeNative(); - handler.post(this); - } - } - }, SystemClock.uptimeMillis() + 500); } @Override @@ -111,7 +92,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int w, int h) { //Log.i("reicast", "NativeGLView.surfaceChanged: " + w + "x" + h); surfaceReady = true; - JNIdc.rendinitNative(surfaceHolder.getSurface(), w, h); + JNIdc.rendinitNative(surfaceHolder.getSurface()); Emulator.getCurrentActivity().handleStateChange(false); } @@ -119,7 +100,7 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback public void surfaceDestroyed(SurfaceHolder surfaceHolder) { //Log.i("reicast", "NativeGLView.surfaceDestroyed"); surfaceReady = false; - JNIdc.rendinitNative(null, 0, 0); + JNIdc.rendinitNative(null); Emulator.getCurrentActivity().handleStateChange(true); } @@ -142,7 +123,6 @@ public class NativeGLView extends SurfaceView implements SurfaceHolder.Callback requestFocus(); JNIdc.resume(); } - startRendering(); } @TargetApi(19) diff --git a/shell/android-studio/reicast/src/main/jni/src/Android.cpp b/shell/android-studio/reicast/src/main/jni/src/Android.cpp index 3ab96e5dd..ced2f366d 100644 --- a/shell/android-studio/reicast/src/main/jni/src/Android.cpp +++ b/shell/android-studio/reicast/src/main/jni/src/Android.cpp @@ -91,8 +91,7 @@ JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_destroy(JNIEnv *env,j JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_send(JNIEnv *env,jobject obj,jint id, jint v) __attribute__((visibility("default"))); JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env,jobject obj,jint id, jbyteArray d) __attribute__((visibility("default"))); -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface, jint w, jint h) __attribute__((visibility("default"))); -JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj) __attribute__((visibility("default"))); +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv *env, jobject obj, jobject surface) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv *env, jobject obj, jint w, jint h) __attribute__((visibility("default"))); JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeJava(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendtermJava(JNIEnv *env, jobject obj) __attribute__((visibility("default"))); @@ -404,35 +403,57 @@ JNIEXPORT jint JNICALL Java_com_reicast_emulator_emu_JNIdc_data(JNIEnv *env, job extern void gl_swap(); extern void egl_stealcntx(); +volatile static bool render_running; +volatile static bool render_reinit; -JNIEXPORT jboolean JNICALL Java_com_reicast_emulator_emu_JNIdc_rendframeNative(JNIEnv *env,jobject obj) +void *render_thread_func(void *) { - if (g_window == NULL) - return false; - if (!egl_makecurrent()) - return false; - jboolean ret = (jboolean)rend_single_frame(); - if (ret) - gl_swap(); - return ret; + render_running = true; + + rend_init_renderer(); + + while (render_running) { + if (render_reinit) + { + render_reinit = false; + rend_init_renderer(); + } + else + if (!egl_makecurrent()) + break;; + + bool ret = rend_single_frame(); + if (ret) + gl_swap(); + } + egl_makecurrent(); + rend_term_renderer(); + ANativeWindow_release(g_window); + g_window = NULL; + render_running = false; + + return NULL; } -JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface, jint width, jint height) +static cThread render_thread(render_thread_func, NULL); + +JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitNative(JNIEnv * env, jobject obj, jobject surface) { - if (g_window != NULL) - { - egl_makecurrent(); - rend_term_renderer(); - ANativeWindow_release(g_window); - g_window = NULL; - } - if (surface != NULL) - { + if (render_thread.hThread != NULL) + { + if (surface == NULL) + { + render_running = false; + render_thread.WaitToEnd(); + } + else + render_reinit = true; + } + else if (surface != NULL) + { g_window = ANativeWindow_fromSurface(env, surface); - rend_init_renderer(); - screen_width = width; - screen_height = height; - } + render_thread.Start(); + } } JNIEXPORT void JNICALL Java_com_reicast_emulator_emu_JNIdc_rendinitJava(JNIEnv * env, jobject obj, jint width, jint height) From 251b4d381d8da7a57b559f4b198ef4a653715974 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 9 Apr 2019 13:09:45 +0200 Subject: [PATCH 08/10] android: add activity alias for intents backward-compatibility --- .../reicast/src/dreamcast/AndroidManifest.xml | 51 +++++++++++++++ .../reicast/src/main/AndroidManifest.xml | 10 +++ .../reicast/src/naomi/AndroidManifest.xml | 63 ++++++++++++++++++- 3 files changed, 123 insertions(+), 1 deletion(-) diff --git a/shell/android-studio/reicast/src/dreamcast/AndroidManifest.xml b/shell/android-studio/reicast/src/dreamcast/AndroidManifest.xml index 165b7b014..112f56962 100644 --- a/shell/android-studio/reicast/src/dreamcast/AndroidManifest.xml +++ b/shell/android-studio/reicast/src/dreamcast/AndroidManifest.xml @@ -52,5 +52,56 @@ android:scheme="file" /> + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/shell/android-studio/reicast/src/main/AndroidManifest.xml b/shell/android-studio/reicast/src/main/AndroidManifest.xml index de600f7bc..ac89e2bb2 100644 --- a/shell/android-studio/reicast/src/main/AndroidManifest.xml +++ b/shell/android-studio/reicast/src/main/AndroidManifest.xml @@ -61,6 +61,16 @@ + + + + + + + + + android:name="com.reicast.emulator.NativeGLActivity"> @@ -62,5 +62,66 @@ android:scheme="file" /> + + + + + + + + + + + + + + + + + + + From 0445542ec240e806c753eb20a3710d2f41d9c284 Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Tue, 9 Apr 2019 15:18:48 +0200 Subject: [PATCH 09/10] gl: 90deg screen rotation option. Fix scissor/clip wrt scale/stretch 90deg CC screen rotation option for some arcade games Fix scissoring and clipping when screen scaling/stretching/rotating Clear shader cache when screen rotation changes Properly delete all gl programs and shaders when needed --- core/nullDC.cpp | 3 + core/rend/gl4/abuffer.cpp | 19 ++++- core/rend/gl4/gl4.h | 4 +- core/rend/gl4/gldraw.cpp | 7 +- core/rend/gl4/gles.cpp | 87 ++++++++++++++++------ core/rend/gles/glcache.h | 13 ++++ core/rend/gles/gldraw.cpp | 31 ++++++-- core/rend/gles/gles.cpp | 103 ++++++++++++++++++-------- core/rend/gles/gles.h | 1 + core/rend/gles/imgui_impl_opengl3.cpp | 8 +- core/rend/gui.cpp | 10 ++- core/types.h | 1 + 12 files changed, 211 insertions(+), 76 deletions(-) diff --git a/core/nullDC.cpp b/core/nullDC.cpp index ffc4d524f..3baf42fa8 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -519,6 +519,7 @@ void InitSettings() settings.rend.ScreenStretching = 100; settings.rend.Fog = true; settings.rend.FloatVMUs = false; + settings.rend.Rotate90 = false; settings.pvr.ta_skip = 0; settings.pvr.rend = 0; @@ -604,6 +605,7 @@ void LoadSettings(bool game_specific) settings.rend.ScreenStretching = cfgLoadInt(config_section, "rend.ScreenStretching", settings.rend.ScreenStretching); settings.rend.Fog = cfgLoadBool(config_section, "rend.Fog", settings.rend.Fog); settings.rend.FloatVMUs = cfgLoadBool(config_section, "rend.FloatVMUs", settings.rend.FloatVMUs); + settings.rend.Rotate90 = cfgLoadBool(config_section, "rend.Rotate90", settings.rend.Rotate90); settings.pvr.ta_skip = cfgLoadInt(config_section, "ta.skip", settings.pvr.ta_skip); settings.pvr.rend = cfgLoadInt(config_section, "pvr.rend", settings.pvr.rend); @@ -730,6 +732,7 @@ void SaveSettings() cfgSaveInt("config", "rend.ScreenStretching", settings.rend.ScreenStretching); cfgSaveBool("config", "rend.Fog", settings.rend.Fog); cfgSaveBool("config", "rend.FloatVMUs", settings.rend.FloatVMUs); + cfgSaveBool("config", "rend.Rotate90", settings.rend.Rotate90); cfgSaveInt("config", "ta.skip", settings.pvr.ta_skip); cfgSaveInt("config", "pvr.rend", settings.pvr.rend); diff --git a/core/rend/gl4/abuffer.cpp b/core/rend/gl4/abuffer.cpp index b09cc962d..7e9b67c64 100644 --- a/core/rend/gl4/abuffer.cpp +++ b/core/rend/gl4/abuffer.cpp @@ -331,23 +331,23 @@ void initABuffer() { char source[16384]; sprintf(source, final_shader_source, 1); - gl4CompilePipelineShader(&g_abuffer_final_shader, source); + gl4CompilePipelineShader(&g_abuffer_final_shader, false, source); } if (g_abuffer_final_nosort_shader.program == 0) { char source[16384]; sprintf(source, final_shader_source, 0); - gl4CompilePipelineShader(&g_abuffer_final_nosort_shader, source); + gl4CompilePipelineShader(&g_abuffer_final_nosort_shader, false, source); } if (g_abuffer_clear_shader.program == 0) - gl4CompilePipelineShader(&g_abuffer_clear_shader, clear_shader_source); + gl4CompilePipelineShader(&g_abuffer_clear_shader, false, clear_shader_source); if (g_abuffer_tr_modvol_shaders[0].program == 0) { char source[16384]; for (int mode = 0; mode < ModeCount; mode++) { sprintf(source, tr_modvol_shader_source, mode); - gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], source); + gl4CompilePipelineShader(&g_abuffer_tr_modvol_shaders[mode], false, source); } } @@ -417,6 +417,17 @@ void termABuffer() glDeleteBuffers(1, &g_quadBuffer); g_quadBuffer = 0; } + glcache.DeleteProgram(g_abuffer_final_shader.program); + g_abuffer_final_shader.program = 0; + glcache.DeleteProgram(g_abuffer_final_nosort_shader.program); + g_abuffer_final_nosort_shader.program = 0; + glcache.DeleteProgram(g_abuffer_clear_shader.program); + g_abuffer_clear_shader.program = 0; + for (int mode = 0; mode < ModeCount; mode++) + { + glcache.DeleteProgram(g_abuffer_tr_modvol_shaders[mode].program); + g_abuffer_tr_modvol_shaders[mode].program = 0; + } } void reshapeABuffer(int w, int h) diff --git a/core/rend/gl4/gl4.h b/core/rend/gl4/gl4.h index 5ca4dd141..4c3ca82ac 100755 --- a/core/rend/gl4/gl4.h +++ b/core/rend/gl4/gl4.h @@ -45,6 +45,7 @@ struct gl4_ctx } modvol_shader; std::unordered_map shaders; + bool rotate90; struct { @@ -66,7 +67,8 @@ bool gl4_render_output_framebuffer(); void abufferDrawQuad(bool upsideDown = false, float x = 0.f, float y = 0.f, float w = 0.f, float h = 0.f); extern const char *gl4PixelPipelineShader; -bool gl4CompilePipelineShader(gl4PipelineShader* s, const char *source = gl4PixelPipelineShader); +bool gl4CompilePipelineShader(gl4PipelineShader* s, bool rotate_90, const char *source = gl4PixelPipelineShader); +void gl4_delete_shaders(); extern GLuint stencilTexId; extern GLuint depthTexId; diff --git a/core/rend/gl4/gldraw.cpp b/core/rend/gl4/gldraw.cpp index 75ad7eda9..dfa403a19 100644 --- a/core/rend/gl4/gldraw.cpp +++ b/core/rend/gl4/gldraw.cpp @@ -49,6 +49,11 @@ static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode, u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, u32 pp_FogCtrl, bool pp_TwoVolumes, u32 pp_DepthFunc, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, int pass) { + if (settings.rend.Rotate90 != gl4.rotate90) + { + gl4_delete_shaders(); + gl4.rotate90 = settings.rend.Rotate90; + } u32 rv=0; rv|=pp_ClipTestMode; @@ -83,7 +88,7 @@ static gl4PipelineShader *gl4GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode, shader->pp_BumpMap = pp_BumpMap; shader->fog_clamping = fog_clamping; shader->pass = pass; - gl4CompilePipelineShader(shader); + gl4CompilePipelineShader(shader, settings.rend.Rotate90); } return shader; diff --git a/core/rend/gl4/gles.cpp b/core/rend/gl4/gles.cpp index 73330cc66..aa2da9c99 100644 --- a/core/rend/gl4/gles.cpp +++ b/core/rend/gl4/gles.cpp @@ -14,6 +14,7 @@ static const char* VertexShaderSource = "\ #version 140 \n\ #define pp_Gouraud %d \n\ +#define ROTATE_90 %d \n\ \n\ #if pp_Gouraud == 0 \n\ #define INTERPOLATION flat \n\ @@ -56,6 +57,9 @@ void main() \n\ \n\ vpos.w = extra_depth_scale / vpos.z; \n\ vpos.z = vpos.w; \n\ +#if ROTATE_90 == 1 \n\ + vpos.xy = vec2(vpos.y, -vpos.x); \n\ +#endif \n\ vpos.xy=vpos.xy*scale.xy-scale.zw; \n\ vpos.xy*=vpos.w; \n\ gl_Position = vpos; \n\ @@ -393,11 +397,11 @@ gl4_ctx gl4; struct gl4ShaderUniforms_t gl4ShaderUniforms; -bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *source /* = PixelPipelineShader */) +bool gl4CompilePipelineShader( gl4PipelineShader* s, bool rotate_90, const char *source /* = PixelPipelineShader */) { char vshader[16384]; - sprintf(vshader, VertexShaderSource, s->pp_Gouraud); + sprintf(vshader, VertexShaderSource, s->pp_Gouraud, rotate_90); char pshader[16384]; @@ -478,27 +482,45 @@ bool gl4CompilePipelineShader( gl4PipelineShader* s, const char *source /* = Pix void gl_term(); +void gl4_delete_shaders() +{ + for (auto it : gl4.shaders) + { + if (it.second.program != 0) + glcache.DeleteProgram(it.second.program); + } + gl4.shaders.clear(); + glcache.DeleteProgram(gl4.modvol_shader.program); + gl4.modvol_shader.program = 0; +} + static void gles_term(void) { - glDeleteProgram(gl4.modvol_shader.program); glDeleteBuffers(1, &gl4.vbo.geometry); gl4.vbo.geometry = 0; glDeleteBuffers(1, &gl4.vbo.modvols); glDeleteBuffers(1, &gl4.vbo.idxs); glDeleteBuffers(1, &gl4.vbo.idxs2); glDeleteBuffers(1, &gl4.vbo.tr_poly_params); - for (auto it = gl4.shaders.begin(); it != gl4.shaders.end(); it++) - { - if (it->second.program != 0) - glDeleteProgram(it->second.program); - } - gl4.shaders.clear(); + gl4_delete_shaders(); glDeleteVertexArrays(1, &gl4.vbo.main_vao); glDeleteVertexArrays(1, &gl4.vbo.modvol_vao); gl_term(); } +static void create_modvol_shader() +{ + if (gl4.modvol_shader.program != 0) + return; + char vshader[16384]; + sprintf(vshader, VertexShaderSource, 1, settings.rend.Rotate90); + + gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader); + gl4.modvol_shader.scale = glGetUniformLocation(gl4.modvol_shader.program, "scale"); + gl4.modvol_shader.extra_depth_scale = glGetUniformLocation(gl4.modvol_shader.program, "extra_depth_scale"); +} + static bool gl_create_resources() { if (gl4.vbo.geometry != 0) @@ -520,12 +542,7 @@ static bool gl_create_resources() gl4SetupMainVBO(); gl4SetupModvolVBO(); - char vshader[16384]; - sprintf(vshader, VertexShaderSource, 1); - - gl4.modvol_shader.program=gl_CompileAndLink(vshader, ModifierVolumeShader); - gl4.modvol_shader.scale = glGetUniformLocation(gl4.modvol_shader.program, "scale"); - gl4.modvol_shader.extra_depth_scale = glGetUniformLocation(gl4.modvol_shader.program, "extra_depth_scale"); + create_modvol_shader(); gl_load_osd_resources(); @@ -603,6 +620,7 @@ static bool RenderFrame() old_screen_scaling = settings.rend.ScreenScaling; } DoCleanup(); + create_modvol_shader(); bool is_rtt=pvrrc.isRTT; @@ -676,13 +694,25 @@ static bool RenderFrame() } else { - dc2s_scale_h = screen_height / 480.0; - ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2; - //-1 -> too much to left - gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; - gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_height; - gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width; - gl4ShaderUniforms.scale_coefs[3] = -1; + if (settings.rend.Rotate90) + { + dc2s_scale_h = screen_height / 640.0; + ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0 * screen_stretching) / 2; + gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; + gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_width; + gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width; + gl4ShaderUniforms.scale_coefs[3] = 1; + } + else + { + dc2s_scale_h = screen_height / 480.0; + ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2; + //-1 -> too much to left + gl4ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; + gl4ShaderUniforms.scale_coefs[1] = -2.0f / dc_height; + gl4ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width; + gl4ShaderUniforms.scale_coefs[3] = -1; + } } gl4ShaderUniforms.extra_depth_scale = settings.rend.ExtraDepthScale; @@ -838,11 +868,20 @@ static bool RenderFrame() float min_y = pvrrc.fb_Y_CLIP.min / scale_y; if (!is_rtt) { + if (settings.rend.Rotate90) + { + float t = width; + width = height; + height = t; + t = min_x; + min_x = min_y; + min_y = 640 - t - height; + } // Add x offset for aspect ratio > 4/3 - min_x = min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x * screen_scaling; + min_x = (min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x) * screen_scaling; // Invert y coordinates when rendering to screen min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling; - width *= dc2s_scale_h * screen_scaling * screen_stretching; + width *= dc2s_scale_h * screen_stretching * screen_scaling; height *= dc2s_scale_h * screen_scaling; if (ds2s_offs_x > 0) diff --git a/core/rend/gles/glcache.h b/core/rend/gles/glcache.h index e245a368d..32c73c644 100644 --- a/core/rend/gles/glcache.h +++ b/core/rend/gles/glcache.h @@ -149,6 +149,19 @@ public: return _texture_ids[--_texture_cache_size]; } + void DeleteProgram(GLuint program) + { + GLsizei shader_count; + GLuint shaders[2]; + glGetAttachedShaders(program, ARRAY_SIZE(shaders), &shader_count, shaders); + for (int i = 0; i < shader_count; i++) + glDeleteShader(shaders[i]); + + glDeleteProgram(program); + if (_program == program) + _program = 0; + } + void Reset() { _texture = 0xFFFFFFFFu; _src_blend_factor = 0xFFFFFFFFu; diff --git a/core/rend/gles/gldraw.cpp b/core/rend/gles/gldraw.cpp index 618a3e33f..b4381170d 100644 --- a/core/rend/gles/gldraw.cpp +++ b/core/rend/gles/gldraw.cpp @@ -114,13 +114,30 @@ s32 SetTileClip(u32 val, GLint uniform) csy /= scale_y; cex /= scale_x; cey /= scale_y; - float t = cey; - cey = 480 - csy; - csy = 480 - t; - float dc2s_scale_h = screen_height / 480.0f; - float ds2s_offs_x = (screen_width - dc2s_scale_h * 640) / 2; - csx = csx * dc2s_scale_h + ds2s_offs_x; - cex = cex * dc2s_scale_h + ds2s_offs_x; + float dc2s_scale_h; + float ds2s_offs_x; + float screen_stretching = settings.rend.ScreenStretching / 100.f; + + if (settings.rend.Rotate90) + { + float t = cex; + cex = cey; + cey = 640 - csx; + csx = csy; + csy = 640 - t; + dc2s_scale_h = screen_height / 640.0f; + ds2s_offs_x = (screen_width - dc2s_scale_h * 480.0 * screen_stretching) / 2; + } + else + { + float t = cey; + cey = 480 - csy; + csy = 480 - t; + dc2s_scale_h = screen_height / 480.0f; + ds2s_offs_x = (screen_width - dc2s_scale_h * 640.0 * screen_stretching) / 2; + } + csx = csx * dc2s_scale_h * screen_stretching + ds2s_offs_x; + cex = cex * dc2s_scale_h * screen_stretching + ds2s_offs_x; csy = csy * dc2s_scale_h; cey = cey * dc2s_scale_h; } diff --git a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp index b16274d99..a2155f460 100644 --- a/core/rend/gles/gles.cpp +++ b/core/rend/gles/gles.cpp @@ -79,6 +79,7 @@ const char* VertexShaderSource = %s \n\ #define TARGET_GL %s \n\ #define pp_Gouraud %d \n\ +#define ROTATE_90 %d \n\ \n\ #define GLES2 0 \n\ #define GLES3 1 \n\ @@ -136,6 +137,9 @@ void main() \n\ vpos.z = vpos.w; \n\ #else \n\ vpos.z=depth_scale.x+depth_scale.y*vpos.w; \n\ +#endif \n\ +#if ROTATE_90 == 1 \n\ + vpos.xy = vec2(vpos.y, -vpos.x); \n\ #endif \n\ vpos.xy=vpos.xy*scale.xy-scale.zw; \n\ vpos.xy*=vpos.w; \n\ @@ -850,9 +854,20 @@ GLuint fogTextureId; extern void gl_term(); #endif +static void gl_delete_shaders() +{ + for (auto it : gl.shaders) + { + if (it.second.program != 0) + glcache.DeleteProgram(it.second.program); + } + gl.shaders.clear(); + glcache.DeleteProgram(gl.modvol_shader.program); + gl.modvol_shader.program = 0; +} + static void gles_term() { - glDeleteProgram(gl.modvol_shader.program); glDeleteBuffers(1, &gl.vbo.geometry); gl.vbo.geometry = 0; glDeleteBuffers(1, &gl.vbo.modvols); @@ -865,7 +880,7 @@ static void gles_term() gl_free_osd_resources(); free_output_framebuffer(); - gl.shaders.clear(); + gl_delete_shaders(); gl_term(); } @@ -1018,6 +1033,11 @@ PipelineShader *GetProgram(u32 cp_AlphaTest, u32 pp_ClipTestMode, u32 pp_Texture, u32 pp_UseAlpha, u32 pp_IgnoreTexA, u32 pp_ShadInstr, u32 pp_Offset, u32 pp_FogCtrl, bool pp_Gouraud, bool pp_BumpMap, bool fog_clamping, bool trilinear) { + if (settings.rend.Rotate90 != gl.rotate90) + { + gl_delete_shaders(); + gl.rotate90 = settings.rend.Rotate90; + } u32 rv=0; rv|=pp_ClipTestMode; @@ -1058,7 +1078,7 @@ bool CompilePipelineShader( PipelineShader* s) { char vshader[8192]; - sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud); + sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, s->pp_Gouraud, settings.rend.Rotate90); char pshader[8192]; @@ -1144,13 +1164,30 @@ void gl_load_osd_resources() void gl_free_osd_resources() { - glDeleteProgram(gl.OSD_SHADER.program); + glcache.DeleteProgram(gl.OSD_SHADER.program); if (osd_tex != 0) { glcache.DeleteTextures(1, &osd_tex); osd_tex = 0; } } + +static void create_modvol_shader() +{ + if (gl.modvol_shader.program != 0) + return; + char vshader[8192]; + sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, 1, settings.rend.Rotate90); + char fshader[8192]; + sprintf(fshader, ModifierVolumeShader, gl.glsl_version_header, gl.gl_version); + + gl.modvol_shader.program=gl_CompileAndLink(vshader, fshader); + gl.modvol_shader.scale = glGetUniformLocation(gl.modvol_shader.program, "scale"); + gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor"); + gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale"); + gl.modvol_shader.extra_depth_scale = glGetUniformLocation(gl.modvol_shader.program, "extra_depth_scale"); +} + bool gl_create_resources() { if (gl.vbo.geometry != 0) @@ -1174,25 +1211,7 @@ bool gl_create_resources() glGenBuffers(1, &gl.vbo.idxs); glGenBuffers(1, &gl.vbo.idxs2); - char vshader[8192]; - sprintf(vshader, VertexShaderSource, gl.glsl_version_header, gl.gl_version, 1); - char fshader[8192]; - sprintf(fshader, ModifierVolumeShader, gl.glsl_version_header, gl.gl_version); - - gl.modvol_shader.program=gl_CompileAndLink(vshader, fshader); - gl.modvol_shader.scale = glGetUniformLocation(gl.modvol_shader.program, "scale"); - gl.modvol_shader.sp_ShaderColor = glGetUniformLocation(gl.modvol_shader.program, "sp_ShaderColor"); - gl.modvol_shader.depth_scale = glGetUniformLocation(gl.modvol_shader.program, "depth_scale"); - gl.modvol_shader.extra_depth_scale = glGetUniformLocation(gl.modvol_shader.program, "extra_depth_scale"); - - //#define PRECOMPILE_SHADERS - #ifdef PRECOMPILE_SHADERS - for (u32 i=0;i too much to left - ShaderUniforms.scale_coefs[0] = 2.0f / (screen_width / dc2s_scale_h * scale_x) * screen_stretching; - ShaderUniforms.scale_coefs[1] = -2.0f / dc_height; - ShaderUniforms.scale_coefs[2] = 1 - 2 * ds2s_offs_x / screen_width; - ShaderUniforms.scale_coefs[3] = -1; } ShaderUniforms.depth_coefs[0]=2/(vtx_max_fZ-vtx_min_fZ); @@ -1868,11 +1900,20 @@ bool RenderFrame() float min_y = pvrrc.fb_Y_CLIP.min / scale_y; if (!is_rtt) { + if (settings.rend.Rotate90) + { + float t = width; + width = height; + height = t; + t = min_x; + min_x = min_y; + min_y = 640 - t - height; + } // Add x offset for aspect ratio > 4/3 - min_x = min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x * screen_scaling; + min_x = (min_x * dc2s_scale_h * screen_stretching + ds2s_offs_x) * screen_scaling; // Invert y coordinates when rendering to screen min_y = (screen_height - (min_y + height) * dc2s_scale_h) * screen_scaling; - width *= dc2s_scale_h * screen_scaling * screen_stretching; + width *= dc2s_scale_h * screen_stretching * screen_scaling; height *= dc2s_scale_h * screen_scaling; if (ds2s_offs_x > 0) diff --git a/core/rend/gles/gles.h b/core/rend/gles/gles.h index 7e0cec3cb..85f1b90e8 100755 --- a/core/rend/gles/gles.h +++ b/core/rend/gles/gles.h @@ -96,6 +96,7 @@ struct gl_ctx } modvol_shader; std::unordered_map shaders; + bool rotate90; struct { diff --git a/core/rend/gles/imgui_impl_opengl3.cpp b/core/rend/gles/imgui_impl_opengl3.cpp index ddb363c1c..0380a8901 100644 --- a/core/rend/gles/imgui_impl_opengl3.cpp +++ b/core/rend/gles/imgui_impl_opengl3.cpp @@ -490,15 +490,9 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects() if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle); g_VboHandle = g_ElementsHandle = 0; - if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle); - if (g_VertHandle) glDeleteShader(g_VertHandle); + glcache.DeleteProgram(g_ShaderHandle); g_VertHandle = 0; - - if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle); - if (g_FragHandle) glDeleteShader(g_FragHandle); g_FragHandle = 0; - - if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle); g_ShaderHandle = 0; ImGui_ImplOpenGL3_DestroyFontsTexture(); diff --git a/core/rend/gui.cpp b/core/rend/gui.cpp index 7a0fb107d..c02e81005 100644 --- a/core/rend/gui.cpp +++ b/core/rend/gui.cpp @@ -804,13 +804,14 @@ static void gui_display_settings() if (ImGui::BeginTabItem("Controls")) { ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, normal_padding); -#if DC_PLATFORM == DC_PLATFORM_DREAMCAST +#if DC_PLATFORM == DC_PLATFORM_DREAMCAST || DC_PLATFORM == DC_PLATFORM_ATOMISWAVE if (ImGui::CollapsingHeader("Dreamcast Devices", ImGuiTreeNodeFlags_DefaultOpen)) { for (int bus = 0; bus < MAPLE_PORTS; bus++) { ImGui::Text("Device %c", bus + 'A'); ImGui::SameLine(); +#if DC_PLATFORM == DC_PLATFORM_DREAMCAST char device_name[32]; sprintf(device_name, "##device%d", bus); float w = ImGui::CalcItemWidth() / 3; @@ -854,6 +855,10 @@ static void gui_display_settings() ImGui::PopID(); } ImGui::PopItemWidth(); +#elif DC_PLATFORM == DC_PLATFORM_ATOMISWAVE + if (MapleDevices[bus][5] != NULL) + ImGui::Text("%s", maple_device_name(MapleDevices[bus][5]->get_device_type())); +#endif } ImGui::Spacing(); } @@ -966,6 +971,9 @@ static void gui_display_settings() ImGui::Checkbox("Show VMU in game", &settings.rend.FloatVMUs); ImGui::SameLine(); ShowHelpMarker("Show the VMU LCD screens while in game"); + ImGui::Checkbox("Rotate screen 90°", &settings.rend.Rotate90); + ImGui::SameLine(); + ShowHelpMarker("Rotate the screen 90° counterclockwise"); ImGui::SliderInt("Scaling", (int *)&settings.rend.ScreenScaling, 1, 100); ImGui::SameLine(); ShowHelpMarker("Downscaling factor relative to native screen resolution. Higher is better"); diff --git a/core/types.h b/core/types.h index c04f79442..3d48ae574 100644 --- a/core/types.h +++ b/core/types.h @@ -636,6 +636,7 @@ struct settings_t int ScreenStretching; // in percent. 150 means stretch from 4/3 to 6/3 bool Fog; bool FloatVMUs; + bool Rotate90; // Rotate the screen 90 deg CC } rend; struct From 13341ecd597ddb83cc31508d56c068b03f88a7cf Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Wed, 10 Apr 2019 11:31:08 +0200 Subject: [PATCH 10/10] maple: process_kcode -> transform_kcode --- core/hw/maple/maple_devs.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp index bb65dde69..90b4c972a 100755 --- a/core/hw/maple/maple_devs.cpp +++ b/core/hw/maple/maple_devs.cpp @@ -208,7 +208,7 @@ struct maple_sega_controller: maple_base return 0xfe060f00; // 4 analog axes (0-3) X Y A B Start U D L R } - virtual u32 process_kcode(u32 kcode) { + virtual u32 transform_kcode(u32 kcode) { return kcode; } @@ -280,7 +280,7 @@ struct maple_sega_controller: maple_base //state data //2 key code - w16(process_kcode(pjs.kcode)); + w16(transform_kcode(pjs.kcode)); //triggers //1 R @@ -322,7 +322,7 @@ struct maple_atomiswave_controller: maple_sega_controller return 0xff663f00; // 6 analog axes, X Y L2/D2(?) A B C Start U D L R } - virtual u32 process_kcode(u32 kcode) override { + virtual u32 transform_kcode(u32 kcode) override { return kcode | AWAVE_TRIGGER_KEY; } @@ -1329,7 +1329,7 @@ struct maple_mouse : maple_base struct maple_lightgun : maple_base { - virtual u32 process_kcode(u32 kcode) { + virtual u32 transform_kcode(u32 kcode) { return kcode | 0xFF01; } @@ -1387,7 +1387,7 @@ struct maple_lightgun : maple_base //state data //2 key code - w16(process_kcode(pjs.kcode)); + w16(transform_kcode(pjs.kcode)); //not used //2 @@ -1415,7 +1415,7 @@ struct maple_lightgun : maple_base struct atomiswave_lightgun : maple_lightgun { - virtual u32 process_kcode(u32 kcode) override { + virtual u32 transform_kcode(u32 kcode) override { return (kcode & AWAVE_TRIGGER_KEY) == 0 ? ~AWAVE_BTN0_KEY : ~0; } };