cheats: support for .CHT cheat files
Issue #167 gui: no need to save background in opengl, use RenderLastFrame instead disable cheats when online
This commit is contained in:
parent
2fa3cfea8d
commit
72968290bf
|
@ -790,6 +790,7 @@ target_sources(${PROJECT_NAME} PRIVATE
|
|||
core/rend/gui.h
|
||||
core/rend/gui_android.cpp
|
||||
core/rend/gui_android.h
|
||||
core/rend/gui_cheats.cpp
|
||||
core/rend/gui_util.cpp
|
||||
core/rend/gui_util.h
|
||||
core/rend/mainui.cpp
|
||||
|
|
221
core/cheats.cpp
221
core/cheats.cpp
|
@ -22,10 +22,11 @@
|
|||
*/
|
||||
#include "cheats.h"
|
||||
#include "hw/sh4/sh4_mem.h"
|
||||
#include "hw/naomi/naomi_cart.h"
|
||||
#include "reios/reios.h"
|
||||
#include "network/picoppp.h"
|
||||
#include "cfg/cfg.h"
|
||||
|
||||
const Cheat CheatManager::_widescreen_cheats[] =
|
||||
const WidescreenCheat CheatManager::widescreen_cheats[] =
|
||||
{
|
||||
{ "MK-51064", nullptr, { 0x39EFF4, 0 }, { 0x43700000 } }, // 18 wheeler (USA)
|
||||
{ "MK-5106450", nullptr, { 0x39EFF4, 0 }, { 0x43700000 } }, // 18 wheeler (PAL)
|
||||
|
@ -290,7 +291,7 @@ const Cheat CheatManager::_widescreen_cheats[] =
|
|||
|
||||
{ nullptr },
|
||||
};
|
||||
const Cheat CheatManager::_naomi_widescreen_cheats[] =
|
||||
const WidescreenCheat CheatManager::naomi_widescreen_cheats[] =
|
||||
{
|
||||
{ "KNIGHTS OF VALOUR THE 7 SPIRITS", nullptr, { 0x475B70, 0x475B40, 0 }, { 0x3F400000, 0x43F00000 } },
|
||||
{ "Dolphin Blue", nullptr, { 0x3F2E2C, 0x3F2190, 0x3F2E6C, 0x3F215C, 0 },
|
||||
|
@ -303,54 +304,216 @@ const Cheat CheatManager::_naomi_widescreen_cheats[] =
|
|||
};
|
||||
CheatManager cheatManager;
|
||||
|
||||
bool CheatManager::Reset()
|
||||
void CheatManager::loadCheatFile(const std::string& filename)
|
||||
{
|
||||
FILE* cheatfile = nowide::fopen(filename.c_str(), "r");
|
||||
if (cheatfile == nullptr)
|
||||
{
|
||||
WARN_LOG(COMMON, "Cannot open cheat file '%s'", filename.c_str());
|
||||
return;
|
||||
}
|
||||
cheats.clear();
|
||||
Cheat cheat;
|
||||
int cheatNumber = 0;
|
||||
char buffer[512];
|
||||
while (fgets(buffer, sizeof(buffer), cheatfile) != nullptr)
|
||||
{
|
||||
std::string l = buffer;
|
||||
auto equalPos = l.find("=");
|
||||
if (equalPos == std::string::npos)
|
||||
continue;
|
||||
auto quotePos = l.find("\"", equalPos);
|
||||
if (quotePos == std::string::npos)
|
||||
continue;
|
||||
auto quote2Pos = l.find("\"", quotePos + 1);
|
||||
if (quote2Pos == std::string::npos)
|
||||
continue;
|
||||
if (l.substr(0, 5) != "cheat" || l[5] < '0' || l[5] > '9')
|
||||
continue;
|
||||
char *p;
|
||||
int number = strtol(&l[5], &p, 10);
|
||||
if (number != cheatNumber && cheat.type != Cheat::Type::disabled)
|
||||
{
|
||||
cheatNumber = number;
|
||||
cheats.push_back(cheat);
|
||||
cheat = Cheat();
|
||||
}
|
||||
std::string param = trim_trailing_ws(l.substr(p - &l[0], equalPos - (p - &l[0])));
|
||||
std::string value = l.substr(quotePos + 1, quote2Pos - quotePos - 1);
|
||||
|
||||
if (param == "_address")
|
||||
{
|
||||
cheat.address = strtol(value.c_str(), nullptr, 10);
|
||||
verify(cheat.address < RAM_SIZE);
|
||||
}
|
||||
else if (param == "_cheat_type")
|
||||
cheat.type = (Cheat::Type)strtol(value.c_str(), nullptr, 10);
|
||||
else if (param == "_desc")
|
||||
cheat.description = value;
|
||||
else if (param == "_memory_search_size")
|
||||
cheat.size = 1 << strtol(value.c_str(), nullptr, 10);
|
||||
else if (param == "_value")
|
||||
cheat.value = strtol(value.c_str(), nullptr, 10);
|
||||
else if (param == "_repeat_count")
|
||||
cheat.repeatCount = strtol(value.c_str(), nullptr, 10);
|
||||
else if (param == "_repeat_add_to_value")
|
||||
cheat.repeatValueIncrement = strtol(value.c_str(), nullptr, 10);
|
||||
else if (param == "_repeat_add_to_address")
|
||||
cheat.repeatAddressIncrement = strtol(value.c_str(), nullptr, 10);
|
||||
else if (param == "_enable")
|
||||
cheat.enabled = value == "true";
|
||||
}
|
||||
std::fclose(cheatfile);
|
||||
if (cheat.type != Cheat::Type::disabled)
|
||||
cheats.push_back(cheat);
|
||||
active = !cheats.empty();
|
||||
INFO_LOG(COMMON, "%d cheats loaded", (int)cheats.size());
|
||||
cfgSaveStr("cheats", gameId, filename);
|
||||
}
|
||||
|
||||
void CheatManager::reset(const std::string& gameId)
|
||||
{
|
||||
if (this->gameId != gameId)
|
||||
{
|
||||
cheats.clear();
|
||||
active = false;
|
||||
_widescreen_cheat = nullptr;
|
||||
this->gameId = gameId;
|
||||
std::string cheatFile = cfgLoadStr("cheats", gameId, "");
|
||||
if (!cheatFile.empty())
|
||||
loadCheatFile(cheatFile);
|
||||
}
|
||||
widescreen_cheat = nullptr;
|
||||
if (!config::WidescreenGameHacks)
|
||||
return false;
|
||||
return;
|
||||
if (settings.platform.system == DC_PLATFORM_DREAMCAST)
|
||||
{
|
||||
std::string game_id(ip_meta.product_number, sizeof(ip_meta.product_number));
|
||||
for (int i = 0; _widescreen_cheats[i].game_id != nullptr; i++)
|
||||
for (int i = 0; widescreen_cheats[i].game_id != nullptr; i++)
|
||||
{
|
||||
if (!strncmp(game_id.c_str(), _widescreen_cheats[i].game_id, game_id.length())
|
||||
&& (_widescreen_cheats[i].area_or_version == nullptr
|
||||
|| !strncmp(ip_meta.area_symbols, _widescreen_cheats[i].area_or_version, sizeof(ip_meta.area_symbols))
|
||||
|| !strncmp(ip_meta.product_version, _widescreen_cheats[i].area_or_version, sizeof(ip_meta.product_version))))
|
||||
if (!strcmp(gameId.c_str(), widescreen_cheats[i].game_id)
|
||||
&& (widescreen_cheats[i].area_or_version == nullptr
|
||||
|| !strncmp(ip_meta.area_symbols, widescreen_cheats[i].area_or_version, sizeof(ip_meta.area_symbols))
|
||||
|| !strncmp(ip_meta.product_version, widescreen_cheats[i].area_or_version, sizeof(ip_meta.product_version))))
|
||||
{
|
||||
_widescreen_cheat = &_widescreen_cheats[i];
|
||||
NOTICE_LOG(COMMON, "Applying widescreen hack to game %s", game_id.c_str());
|
||||
widescreen_cheat = &widescreen_cheats[i];
|
||||
NOTICE_LOG(COMMON, "Applying widescreen hack to game %s", gameId.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; _naomi_widescreen_cheats[i].game_id != nullptr; i++)
|
||||
for (int i = 0; naomi_widescreen_cheats[i].game_id != nullptr; i++)
|
||||
{
|
||||
if (!strcmp(naomi_game_id, _naomi_widescreen_cheats[i].game_id))
|
||||
if (!strcmp(gameId.c_str(), naomi_widescreen_cheats[i].game_id))
|
||||
{
|
||||
_widescreen_cheat = &_naomi_widescreen_cheats[i];
|
||||
NOTICE_LOG(COMMON, "Applying widescreen hack to game %s", naomi_game_id);
|
||||
widescreen_cheat = &naomi_widescreen_cheats[i];
|
||||
NOTICE_LOG(COMMON, "Applying widescreen hack to game %s", gameId.c_str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_widescreen_cheat == nullptr)
|
||||
return false;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(_widescreen_cheat->addresses) && _widescreen_cheat->addresses[i] != 0; i++)
|
||||
verify(_widescreen_cheat->addresses[i] < RAM_SIZE);
|
||||
|
||||
active = true;
|
||||
return true;
|
||||
if (widescreen_cheat == nullptr)
|
||||
return;
|
||||
for (size_t i = 0; i < ARRAY_SIZE(widescreen_cheat->addresses) && widescreen_cheat->addresses[i] != 0; i++)
|
||||
verify(widescreen_cheat->addresses[i] < RAM_SIZE);
|
||||
}
|
||||
|
||||
void CheatManager::Apply()
|
||||
u32 CheatManager::readRam(u32 addr, u32 bits)
|
||||
{
|
||||
if (_widescreen_cheat != nullptr)
|
||||
switch (bits)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(_widescreen_cheat->addresses) && _widescreen_cheat->addresses[i] != 0; i++)
|
||||
WriteMem32_nommu(0x8C000000 + _widescreen_cheat->addresses[i], _widescreen_cheat->values[i]);
|
||||
case 8:
|
||||
return ReadMem8_nommu(0x8C000000 + addr);
|
||||
case 16:
|
||||
return ReadMem16_nommu(0x8C000000 + addr);
|
||||
case 32:
|
||||
return ReadMem32_nommu(0x8C000000 + addr);
|
||||
default:
|
||||
die("invalid size");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManager::writeRam(u32 addr, u32 value, u32 bits)
|
||||
{
|
||||
switch (bits)
|
||||
{
|
||||
case 8:
|
||||
WriteMem8_nommu(0x8C000000 + addr, (u8)value);
|
||||
break;
|
||||
case 16:
|
||||
WriteMem16_nommu(0x8C000000 + addr, (u16)value);
|
||||
break;
|
||||
case 32:
|
||||
WriteMem32_nommu(0x8C000000 + addr, value);
|
||||
break;
|
||||
default:
|
||||
die("invalid size");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CheatManager::apply()
|
||||
{
|
||||
if (widescreen_cheat != nullptr)
|
||||
{
|
||||
for (size_t i = 0; i < ARRAY_SIZE(widescreen_cheat->addresses) && widescreen_cheat->addresses[i] != 0; i++)
|
||||
writeRam(widescreen_cheat->addresses[i], widescreen_cheat->values[i], 32);
|
||||
}
|
||||
if (active && !networkStarted())
|
||||
{
|
||||
bool skipCheat = false;
|
||||
for (const Cheat& cheat : cheats)
|
||||
{
|
||||
if (skipCheat) {
|
||||
skipCheat = false;
|
||||
continue;
|
||||
}
|
||||
if (!cheat.enabled)
|
||||
continue;
|
||||
|
||||
bool setValue = false;
|
||||
u32 valueToSet = 0;
|
||||
switch (cheat.type)
|
||||
{
|
||||
case Cheat::Type::disabled:
|
||||
default:
|
||||
break;
|
||||
case Cheat::Type::setValue:
|
||||
setValue = true;
|
||||
valueToSet = cheat.value;
|
||||
break;
|
||||
case Cheat::Type::increase:
|
||||
setValue = true;
|
||||
valueToSet = readRam(cheat.address, cheat.size) + cheat.value;
|
||||
break;
|
||||
case Cheat::Type::decrease:
|
||||
setValue = true;
|
||||
valueToSet = readRam(cheat.address, cheat.size) - cheat.value;
|
||||
break;
|
||||
case Cheat::Type::runNextIfEq:
|
||||
skipCheat = readRam(cheat.address, cheat.size) != cheat.value;
|
||||
break;
|
||||
case Cheat::Type::runNextIfNeq:
|
||||
skipCheat = readRam(cheat.address, cheat.size) == cheat.value;
|
||||
break;
|
||||
case Cheat::Type::runNextIfGt:
|
||||
skipCheat = readRam(cheat.address, cheat.size) <= cheat.value;
|
||||
break;
|
||||
case Cheat::Type::runNextIfLt:
|
||||
skipCheat = readRam(cheat.address, cheat.size) >= cheat.value;
|
||||
break;
|
||||
}
|
||||
if (setValue)
|
||||
{
|
||||
u32 address = cheat.address;
|
||||
for (u32 repeat = 0; repeat < cheat.repeatCount; repeat++)
|
||||
{
|
||||
writeRam(address, valueToSet, cheat.size);
|
||||
address += cheat.repeatAddressIncrement * cheat.size / 8;
|
||||
valueToSet += cheat.repeatValueIncrement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
struct Cheat
|
||||
struct WidescreenCheat
|
||||
{
|
||||
const char *game_id;
|
||||
const char *area_or_version;
|
||||
|
@ -29,19 +29,52 @@ struct Cheat
|
|||
u32 values[16];
|
||||
};
|
||||
|
||||
struct Cheat
|
||||
{
|
||||
enum class Type {
|
||||
disabled,
|
||||
setValue,
|
||||
increase,
|
||||
decrease,
|
||||
runNextIfEq,
|
||||
runNextIfNeq,
|
||||
runNextIfGt,
|
||||
runNextIfLt
|
||||
};
|
||||
Type type = Type::disabled;
|
||||
std::string description;
|
||||
bool enabled = false;
|
||||
u32 size = 0;
|
||||
u32 address = 0;
|
||||
u32 value = 0;
|
||||
u32 repeatCount = 1;
|
||||
u32 repeatValueIncrement = 0;
|
||||
u32 repeatAddressIncrement = 0;
|
||||
};
|
||||
|
||||
class CheatManager
|
||||
{
|
||||
public:
|
||||
CheatManager() : _widescreen_cheat(nullptr) {}
|
||||
bool Reset(); // Returns true if using 16:9 anamorphic screen ratio
|
||||
void Apply();
|
||||
bool isActive() const { return active; }
|
||||
void reset(const std::string& gameId);
|
||||
void apply();
|
||||
size_t cheatCount() const { return cheats.size(); }
|
||||
const std::string& cheatDescription(size_t index) const { return cheats[index].description; }
|
||||
bool cheatEnabled(size_t index) const { return cheats[index].enabled; }
|
||||
void enableCheat(size_t index, bool enabled) { cheats[index].enabled = enabled; }
|
||||
void loadCheatFile(const std::string& filename);
|
||||
// Returns true if using 16:9 anamorphic screen ratio
|
||||
bool isWidescreen() const { return widescreen_cheat != nullptr; }
|
||||
|
||||
private:
|
||||
static const Cheat _widescreen_cheats[];
|
||||
static const Cheat _naomi_widescreen_cheats[];
|
||||
const Cheat *_widescreen_cheat;
|
||||
u32 readRam(u32 addr, u32 bits);
|
||||
void writeRam(u32 addr, u32 value, u32 bits);
|
||||
|
||||
static const WidescreenCheat widescreen_cheats[];
|
||||
static const WidescreenCheat naomi_widescreen_cheats[];
|
||||
const WidescreenCheat *widescreen_cheat = nullptr;
|
||||
bool active = false;
|
||||
std::vector<Cheat> cheats;
|
||||
std::string gameId;
|
||||
};
|
||||
|
||||
extern CheatManager cheatManager;
|
||||
|
|
|
@ -392,7 +392,7 @@ void rend_vblank()
|
|||
}
|
||||
render_called = false;
|
||||
check_framebuffer_write();
|
||||
cheatManager.Apply();
|
||||
cheatManager.apply();
|
||||
}
|
||||
|
||||
void check_framebuffer_write()
|
||||
|
|
|
@ -1079,6 +1079,11 @@ void stop_pico()
|
|||
pico_thread.WaitToEnd();
|
||||
}
|
||||
|
||||
bool networkStarted()
|
||||
{
|
||||
return pico_thread_running;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include "types.h"
|
||||
|
@ -1088,5 +1093,8 @@ void stop_pico() { }
|
|||
void write_pico(u8 b) { }
|
||||
int read_pico() { return -1; }
|
||||
void pico_receive_eth_frame(const u8* frame, u32 size) {}
|
||||
|
||||
bool networkStarted()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@ bool start_pico();
|
|||
void stop_pico();
|
||||
void write_pico(u8 b);
|
||||
int read_pico();
|
||||
bool networkStarted();
|
||||
|
||||
void pico_receive_eth_frame(const u8 *frame, u32 size);
|
||||
// implemented in bba
|
||||
|
|
|
@ -580,7 +580,8 @@ static void dc_start_game(const char *path)
|
|||
else if (settings.platform.system == DC_PLATFORM_ATOMISWAVE)
|
||||
mcfg_CreateAtomisWaveControllers();
|
||||
}
|
||||
if (cheatManager.Reset())
|
||||
cheatManager.reset(config::Settings::instance().getGameId());
|
||||
if (cheatManager.isWidescreen())
|
||||
{
|
||||
gui_display_notification("Widescreen cheat activated", 1000);
|
||||
config::ScreenStretching.override(134); // 4:3 -> 16:9
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
|
||||
#include "wsi/gl_context.h"
|
||||
#include "glcache.h"
|
||||
#include "hw/pvr/Renderer_if.h"
|
||||
|
||||
// OpenGL Data
|
||||
static char g_GlslVersionString[32] = "";
|
||||
|
@ -76,7 +77,6 @@ static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;
|
|||
static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;
|
||||
static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;
|
||||
static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;
|
||||
static GLuint g_BackgroundTexture = 0;
|
||||
|
||||
// Functions
|
||||
bool ImGui_ImplOpenGL3_Init(const char* glsl_version)
|
||||
|
@ -118,7 +118,7 @@ void ImGui_ImplOpenGL3_NewFrame()
|
|||
// OpenGL3 Render function.
|
||||
// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)
|
||||
// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.
|
||||
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_background)
|
||||
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
|
||||
{
|
||||
// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
@ -140,28 +140,6 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_backgr
|
|||
}
|
||||
#endif
|
||||
|
||||
if (save_background)
|
||||
{
|
||||
#ifndef GLES2
|
||||
if (!theGLContext.IsGLES() && glReadBuffer != NULL)
|
||||
glReadBuffer(GL_FRONT);
|
||||
|
||||
// (Re-)create the background texture and reserve space for it
|
||||
if (g_BackgroundTexture != 0)
|
||||
glcache.DeleteTextures(1, &g_BackgroundTexture);
|
||||
g_BackgroundTexture = glcache.GenTexture();
|
||||
glcache.BindTexture(GL_TEXTURE_2D, g_BackgroundTexture);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glcache.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fb_width, fb_height, 0, GL_RGB, GL_UNSIGNED_BYTE, (GLvoid*)NULL);
|
||||
|
||||
// Copy the current framebuffer into it
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, fb_width, fb_height);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
|
||||
glcache.Enable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
|
@ -506,10 +484,6 @@ void ImGui_ImplOpenGL3_DestroyDeviceObjects()
|
|||
g_ShaderHandle = 0;
|
||||
|
||||
ImGui_ImplOpenGL3_DestroyFontsTexture();
|
||||
|
||||
if (g_BackgroundTexture != 0)
|
||||
glcache.DeleteTextures(1, &g_BackgroundTexture);
|
||||
g_BackgroundTexture = 0;
|
||||
}
|
||||
|
||||
void ImGui_ImplOpenGL3_DrawBackground()
|
||||
|
@ -518,16 +492,8 @@ void ImGui_ImplOpenGL3_DrawBackground()
|
|||
glcache.Disable(GL_SCISSOR_TEST);
|
||||
glcache.ClearColor(0, 0, 0, 0);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
if (g_BackgroundTexture != 0)
|
||||
{
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
ImGui::SetNextWindowSize(io.DisplaySize);
|
||||
ImGui::Begin("background", NULL, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoFocusOnAppearing
|
||||
| ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoBackground);
|
||||
ImGui::GetWindowDrawList()->AddImage((ImTextureID)(uintptr_t)g_BackgroundTexture, ImVec2(0, 0), io.DisplaySize, ImVec2(0, 1), ImVec2(1, 0), 0xffffffff);
|
||||
ImGui::End();
|
||||
}
|
||||
if (renderer != nullptr)
|
||||
renderer->RenderLastFrame();
|
||||
}
|
||||
|
||||
static ImTextureID createSimpleTexture(const unsigned int *data, u32 width, u32 height)
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
IMGUI_IMPL_API bool ImGui_ImplOpenGL3_Init(const char* glsl_version = NULL);
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_Shutdown();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_NewFrame();
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data, bool save_background = false);
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data);
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DrawBackground();
|
||||
IMGUI_IMPL_API ImTextureID ImGui_ImplOpenGL3_CreateVmuTexture(const unsigned int *);
|
||||
IMGUI_IMPL_API void ImGui_ImplOpenGL3_DeleteTexture(ImTextureID);
|
||||
|
|
|
@ -45,7 +45,6 @@
|
|||
extern void UpdateInputState();
|
||||
static bool game_started;
|
||||
|
||||
extern int screen_width, screen_height;
|
||||
extern u8 kb_shift; // shift keys pressed (bitmask)
|
||||
extern u8 kb_key[6]; // normal keys pressed
|
||||
|
||||
|
@ -54,7 +53,6 @@ int screen_dpi = 96;
|
|||
static bool inited = false;
|
||||
float scaling = 1;
|
||||
GuiState gui_state = GuiState::Main;
|
||||
static bool settings_opening;
|
||||
#ifdef __ANDROID__
|
||||
static bool touch_up;
|
||||
#endif
|
||||
|
@ -70,11 +68,6 @@ static void displayCrosshairs();
|
|||
|
||||
GameScanner scanner;
|
||||
|
||||
float gui_get_scaling()
|
||||
{
|
||||
return scaling;
|
||||
}
|
||||
|
||||
static void emuEventCallback(Event event)
|
||||
{
|
||||
switch (event)
|
||||
|
@ -249,7 +242,7 @@ void gui_init()
|
|||
EventManager::listen(Event::Terminate, emuEventCallback);
|
||||
}
|
||||
|
||||
void ImGui_Impl_NewFrame()
|
||||
static void ImGui_Impl_NewFrame()
|
||||
{
|
||||
if (config::RendererType.isOpenGL())
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
|
@ -358,7 +351,6 @@ void gui_open_settings()
|
|||
if (gui_state == GuiState::Closed)
|
||||
{
|
||||
gui_state = GuiState::Commands;
|
||||
settings_opening = true;
|
||||
HideOSD();
|
||||
}
|
||||
else if (gui_state == GuiState::VJoyEdit)
|
||||
|
@ -391,16 +383,12 @@ static void gui_display_commands()
|
|||
{
|
||||
dc_stop();
|
||||
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
if (!settings_opening && config::RendererType.isOpenGL())
|
||||
if (config::RendererType.isOpenGL())
|
||||
ImGui_ImplOpenGL3_DrawBackground();
|
||||
|
||||
if (!config::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));
|
||||
centerNextWindow();
|
||||
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 0));
|
||||
|
||||
ImGui::Begin("##commands", NULL, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
@ -454,7 +442,13 @@ static void gui_display_commands()
|
|||
}
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::Button("Exit", ImVec2(150 * scaling, 50 * scaling)))
|
||||
if (ImGui::Button("Cheats", ImVec2(150 * scaling, 50 * scaling)))
|
||||
{
|
||||
gui_state = GuiState::Cheats;
|
||||
}
|
||||
ImGui::Columns(1, nullptr, false);
|
||||
if (ImGui::Button("Exit", ImVec2(300 * scaling + ImGui::GetStyle().ColumnsMinSpacing + ImGui::GetStyle().FramePadding.x * 2 - 1,
|
||||
50 * scaling)))
|
||||
{
|
||||
// Exit to main menu
|
||||
dc_term_game();
|
||||
|
@ -464,10 +458,6 @@ static void gui_display_commands()
|
|||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), settings_opening);
|
||||
settings_opening = false;
|
||||
}
|
||||
|
||||
const char *maple_device_types[] = { "None", "Sega Controller", "Light Gun", "Keyboard", "Mouse", "Twin Stick", "Ascii Stick" };
|
||||
|
@ -597,11 +587,6 @@ static double map_start_time;
|
|||
static bool arcade_button_mode;
|
||||
static u32 gamepad_port;
|
||||
|
||||
static void input_detected(u32 code)
|
||||
{
|
||||
mapped_code = code;
|
||||
}
|
||||
|
||||
static void detect_input_popup(int index, bool analog)
|
||||
{
|
||||
ImVec2 padding = ImVec2(20 * scaling, 20 * scaling);
|
||||
|
@ -725,7 +710,10 @@ static void controller_mapping_popup(const std::shared_ptr<GamepadDevice>& gamep
|
|||
ImGui::OpenPopup("Map Button");
|
||||
mapped_device = gamepad;
|
||||
mapped_code = -1;
|
||||
gamepad->detect_btn_input(&input_detected);
|
||||
gamepad->detect_btn_input([](u32 code)
|
||||
{
|
||||
mapped_code = code;
|
||||
});
|
||||
}
|
||||
detect_input_popup(j, false);
|
||||
ImGui::NextColumn();
|
||||
|
@ -772,7 +760,10 @@ static void controller_mapping_popup(const std::shared_ptr<GamepadDevice>& gamep
|
|||
ImGui::OpenPopup("Map Axis");
|
||||
mapped_device = gamepad;
|
||||
mapped_code = -1;
|
||||
gamepad->detect_axis_input(&input_detected);
|
||||
gamepad->detect_axis_input([](u32 code)
|
||||
{
|
||||
mapped_code = code;
|
||||
});
|
||||
}
|
||||
detect_input_popup(j, true);
|
||||
ImGui::NextColumn();
|
||||
|
@ -848,7 +839,7 @@ static void contentpath_warning_popup()
|
|||
{
|
||||
scanner.stop();
|
||||
ImGui::OpenPopup("Select Directory");
|
||||
select_directory_popup("Select Directory", scaling, [](bool cancelled, std::string selection)
|
||||
select_file_popup("Select Directory", [](bool cancelled, std::string selection)
|
||||
{
|
||||
show_contentpath_selection = false;
|
||||
if (!cancelled)
|
||||
|
@ -861,23 +852,10 @@ static void contentpath_warning_popup()
|
|||
}
|
||||
}
|
||||
|
||||
void directory_selected_callback(bool cancelled, std::string selection)
|
||||
{
|
||||
if (!cancelled)
|
||||
{
|
||||
scanner.stop();
|
||||
config::ContentPath.get().push_back(selection);
|
||||
scanner.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
static void gui_display_settings()
|
||||
{
|
||||
static bool maple_devices_changed;
|
||||
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
RenderType pvr_rend = config::RendererType;
|
||||
bool vulkan = !config::RendererType.isOpenGL();
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
|
@ -991,7 +969,15 @@ static void gui_display_settings()
|
|||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(24 * scaling, 3 * scaling));
|
||||
if (ImGui::Button("Add"))
|
||||
ImGui::OpenPopup("Select Directory");
|
||||
select_directory_popup("Select Directory", scaling, &directory_selected_callback);
|
||||
select_file_popup("Select Directory", [](bool cancelled, std::string selection)
|
||||
{
|
||||
if (!cancelled)
|
||||
{
|
||||
scanner.stop();
|
||||
config::ContentPath.get().push_back(selection);
|
||||
scanner.refresh();
|
||||
}
|
||||
});
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::ListBoxFooter();
|
||||
|
@ -1624,9 +1610,6 @@ static void gui_display_settings()
|
|||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), false);
|
||||
|
||||
if (vulkan != !config::RendererType.isOpenGL())
|
||||
pvr_rend = !vulkan ? RenderType::OpenGL
|
||||
: config::RendererType == RenderType::OpenGL_OIT ? RenderType::Vulkan_OIT : RenderType::Vulkan;
|
||||
|
@ -1650,19 +1633,11 @@ static std::string get_notification()
|
|||
|
||||
inline static void gui_display_demo()
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::ShowDemoWindow();
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), false);
|
||||
}
|
||||
|
||||
static void gui_display_content()
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
||||
ImGui::SetNextWindowSize(ImVec2(screen_width, screen_height));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
|
||||
|
@ -1672,7 +1647,9 @@ static void gui_display_content()
|
|||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 8 * scaling)); // from 8, 4
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Indent(10 * scaling);
|
||||
ImGui::Text("GAMES");
|
||||
ImGui::Unindent(10 * scaling);
|
||||
|
||||
static ImGuiTextFilter filter;
|
||||
if (KeyboardDevice::GetInstance() != NULL)
|
||||
|
@ -1682,8 +1659,8 @@ static void gui_display_content()
|
|||
}
|
||||
if (gui_state != GuiState::SelectDisk)
|
||||
{
|
||||
ImGui::SameLine(ImGui::GetContentRegionAvail().x - ImGui::CalcTextSize("Settings").x - ImGui::GetStyle().FramePadding.x * 2.0f /*+ ImGui::GetStyle().ItemSpacing.x*/);
|
||||
if (ImGui::Button("Settings"))//, ImVec2(0, 30 * scaling)))
|
||||
ImGui::SameLine(ImGui::GetContentRegionMax().x - ImGui::CalcTextSize("Settings").x - ImGui::GetStyle().FramePadding.x * 2.0f);
|
||||
if (ImGui::Button("Settings"))
|
||||
gui_state = GuiState::Settings;
|
||||
}
|
||||
ImGui::PopStyleVar();
|
||||
|
@ -1751,9 +1728,6 @@ static void gui_display_content()
|
|||
|
||||
error_popup();
|
||||
contentpath_warning_popup();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), false);
|
||||
}
|
||||
|
||||
static void systemdir_selected_callback(bool cancelled, std::string selection)
|
||||
|
@ -1793,14 +1767,8 @@ static void systemdir_selected_callback(bool cancelled, std::string selection)
|
|||
|
||||
static void gui_display_onboarding()
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::OpenPopup("Select System Directory");
|
||||
select_directory_popup("Select System Directory", scaling, &systemdir_selected_callback);
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), false);
|
||||
select_file_popup("Select System Directory", &systemdir_selected_callback);
|
||||
}
|
||||
|
||||
static std::future<bool> networkStatus;
|
||||
|
@ -1813,10 +1781,7 @@ static void start_network()
|
|||
|
||||
static void gui_network_start()
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screen_width / 2, screen_height / 2), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
centerNextWindow();
|
||||
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 180 * scaling));
|
||||
|
||||
ImGui::Begin("##network", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize);
|
||||
|
@ -1860,21 +1825,16 @@ static void gui_network_start()
|
|||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), false);
|
||||
|
||||
if ((kcode[0] & DC_BTN_START) == 0)
|
||||
naomiNetwork.startNow();
|
||||
}
|
||||
|
||||
static void gui_display_loadscreen()
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
if (config::RendererType.isOpenGL())
|
||||
ImGui_ImplOpenGL3_DrawBackground();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screen_width / 2, screen_height / 2), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
centerNextWindow();
|
||||
ImGui::SetNextWindowSize(ImVec2(330 * scaling, 180 * scaling));
|
||||
|
||||
ImGui::Begin("##loading", NULL, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize);
|
||||
|
@ -1923,13 +1883,25 @@ static void gui_display_loadscreen()
|
|||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), false);
|
||||
}
|
||||
|
||||
void gui_display_ui()
|
||||
{
|
||||
if (gui_state == GuiState::Closed || gui_state == GuiState::VJoyEdit)
|
||||
return;
|
||||
if (gui_state == GuiState::Main)
|
||||
{
|
||||
std::string game_file = settings.imgread.ImagePath;
|
||||
if (!game_file.empty())
|
||||
{
|
||||
gui_start_game(game_file);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
switch (gui_state)
|
||||
{
|
||||
case GuiState::Settings:
|
||||
|
@ -1940,13 +1912,7 @@ void gui_display_ui()
|
|||
break;
|
||||
case GuiState::Main:
|
||||
//gui_display_demo();
|
||||
{
|
||||
std::string game_file = settings.imgread.ImagePath;
|
||||
if (!game_file.empty())
|
||||
gui_start_game(game_file);
|
||||
else
|
||||
gui_display_content();
|
||||
}
|
||||
break;
|
||||
case GuiState::Closed:
|
||||
break;
|
||||
|
@ -1969,10 +1935,15 @@ void gui_display_ui()
|
|||
case GuiState::NetworkStart:
|
||||
gui_network_start();
|
||||
break;
|
||||
case GuiState::Cheats:
|
||||
gui_cheats();
|
||||
break;
|
||||
default:
|
||||
die("Unknown UI state");
|
||||
break;
|
||||
}
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
if (gui_state == GuiState::Closed)
|
||||
dc_resume();
|
||||
|
|
|
@ -28,6 +28,7 @@ void gui_display_osd();
|
|||
void gui_open_onboarding();
|
||||
void gui_term();
|
||||
void gui_refresh_files();
|
||||
void gui_cheats();
|
||||
|
||||
extern int screen_dpi;
|
||||
extern float scaling;
|
||||
|
@ -45,10 +46,10 @@ enum class GuiState {
|
|||
VJoyEditCommands,
|
||||
SelectDisk,
|
||||
Loading,
|
||||
NetworkStart
|
||||
NetworkStart,
|
||||
Cheats
|
||||
};
|
||||
extern GuiState gui_state;
|
||||
void ImGui_Impl_NewFrame();
|
||||
|
||||
static inline bool gui_is_open()
|
||||
{
|
||||
|
@ -58,7 +59,9 @@ static inline bool gui_is_content_browser()
|
|||
{
|
||||
return gui_state == GuiState::Main;
|
||||
}
|
||||
float gui_get_scaling();
|
||||
static inline float gui_get_scaling() {
|
||||
return scaling;
|
||||
}
|
||||
|
||||
#define XHAIR_WIDTH (40 * scaling)
|
||||
#define XHAIR_HEIGHT (40 * scaling)
|
||||
|
|
|
@ -31,10 +31,7 @@ void vjoy_stop_editing(bool canceled);
|
|||
|
||||
void gui_display_vjoy_commands(int screen_width, int screen_height, float scaling)
|
||||
{
|
||||
ImGui_Impl_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::SetNextWindowPos(ImVec2(screen_width / 2.f, screen_height / 2.f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
centerNextWindow();
|
||||
|
||||
ImGui::Begin("Virtual Joystick", NULL, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse
|
||||
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
@ -58,9 +55,6 @@ void gui_display_vjoy_commands(int screen_width, int screen_height, float scalin
|
|||
gui_state = GuiState::Settings;
|
||||
}
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Render();
|
||||
ImGui_impl_RenderDrawData(ImGui::GetDrawData(), false);
|
||||
}
|
||||
|
||||
#endif // __ANDROID__
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
Copyright 2021 flyinghead
|
||||
|
||||
This file is part of Flycast.
|
||||
|
||||
Flycast is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Flycast is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Flycast. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "gui.h"
|
||||
#include "imgui/imgui.h"
|
||||
#include "gui_util.h"
|
||||
#include "cheats.h"
|
||||
|
||||
void gui_cheats()
|
||||
{
|
||||
if (config::RendererType.isOpenGL())
|
||||
ImGui_ImplOpenGL3_DrawBackground();
|
||||
|
||||
centerNextWindow();
|
||||
ImGui::SetNextWindowSize(ImVec2(std::min<float>(screen_width, 600 * scaling), std::min<float>(screen_height, 400 * scaling)));
|
||||
|
||||
ImGui::Begin("##main", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoTitleBar
|
||||
| ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(20 * scaling, 8 * scaling)); // from 8, 4
|
||||
ImGui::AlignTextToFramePadding();
|
||||
ImGui::Indent(10 * scaling);
|
||||
ImGui::Text("CHEATS");
|
||||
|
||||
ImGui::SameLine(ImGui::GetWindowContentRegionMax().x - ImGui::CalcTextSize("Close").x - ImGui::GetStyle().FramePadding.x * 4.f
|
||||
- ImGui::CalcTextSize("Load").x - ImGui::GetStyle().ItemSpacing.x);
|
||||
if (ImGui::Button("Load"))
|
||||
ImGui::OpenPopup("Select cheat file");
|
||||
select_file_popup("Select cheat file", [](bool cancelled, std::string selection)
|
||||
{
|
||||
if (cancelled)
|
||||
return;
|
||||
cheatManager.loadCheatFile(selection);
|
||||
}, true, "cht");
|
||||
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Close"))
|
||||
gui_state = GuiState::Commands;
|
||||
|
||||
ImGui::Unindent(10 * scaling);
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
ImGui::BeginChild(ImGui::GetID("cheats"), ImVec2(0, 0), true);
|
||||
{
|
||||
if (cheatManager.cheatCount() == 0)
|
||||
ImGui::Text("(No cheat loaded)");
|
||||
else
|
||||
for (size_t i = 0; i < cheatManager.cheatCount(); i++)
|
||||
{
|
||||
ImGui::PushID(("cheat" + std::to_string(i)).c_str());
|
||||
bool v = cheatManager.cheatEnabled(i);
|
||||
if (ImGui::Checkbox(cheatManager.cheatDescription(i).c_str(), &v))
|
||||
cheatManager.enableCheat(i, v);
|
||||
ImGui::PopID();
|
||||
}
|
||||
}
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
}
|
|
@ -28,11 +28,9 @@
|
|||
#include "imgui/imgui.h"
|
||||
#include "imgui/imgui_internal.h"
|
||||
|
||||
extern int screen_width, screen_height;
|
||||
|
||||
static std::string select_current_directory;
|
||||
static std::vector<std::string> select_subfolders;
|
||||
static std::vector<std::string> display_files;
|
||||
static std::vector<std::string> subfolders;
|
||||
static std::vector<std::string> folderFiles;
|
||||
bool subfolders_read;
|
||||
#ifdef _WIN32
|
||||
static const std::string separators = "/\\";
|
||||
|
@ -43,7 +41,8 @@ static const std::string native_separator = "/";
|
|||
#endif
|
||||
#define PSEUDO_ROOT ":"
|
||||
|
||||
void select_directory_popup(const char *prompt, float scaling, StringCallback callback)
|
||||
void select_file_popup(const char *prompt, StringCallback callback,
|
||||
bool selectFile, const std::string& selectExtension)
|
||||
{
|
||||
if (select_current_directory.empty())
|
||||
{
|
||||
|
@ -93,8 +92,8 @@ void select_directory_popup(const char *prompt, float scaling, StringCallback ca
|
|||
|
||||
if (!subfolders_read)
|
||||
{
|
||||
select_subfolders.clear();
|
||||
display_files.clear();
|
||||
subfolders.clear();
|
||||
folderFiles.clear();
|
||||
error_message.clear();
|
||||
#ifdef _WIN32
|
||||
if (select_current_directory == PSEUDO_ROOT)
|
||||
|
@ -104,7 +103,7 @@ void select_directory_popup(const char *prompt, float scaling, StringCallback ca
|
|||
u32 drives = GetLogicalDrives();
|
||||
for (int i = 0; i < 32; i++)
|
||||
if ((drives & (1 << i)) != 0)
|
||||
select_subfolders.push_back(std::string(1, (char)('A' + i)) + ":\\");
|
||||
subfolders.push_back(std::string(1, (char)('A' + i)) + ":\\");
|
||||
}
|
||||
else
|
||||
#elif __ANDROID__
|
||||
|
@ -117,12 +116,12 @@ void select_directory_popup(const char *prompt, float scaling, StringCallback ca
|
|||
const char *pcolon = strchr(home, ':');
|
||||
if (pcolon != NULL)
|
||||
{
|
||||
select_subfolders.push_back(std::string(home, pcolon - home));
|
||||
subfolders.push_back(std::string(home, pcolon - home));
|
||||
home = pcolon + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
select_subfolders.push_back(home);
|
||||
subfolders.push_back(home);
|
||||
home = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +133,7 @@ void select_directory_popup(const char *prompt, float scaling, StringCallback ca
|
|||
if (dir == NULL)
|
||||
{
|
||||
error_message = "Cannot read " + select_current_directory;
|
||||
select_subfolders.emplace_back("..");
|
||||
subfolders.emplace_back("..");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -169,36 +168,45 @@ void select_directory_popup(const char *prompt, float scaling, StringCallback ca
|
|||
{
|
||||
if (name == "..")
|
||||
dotdot_seen = true;
|
||||
select_subfolders.push_back(name);
|
||||
subfolders.push_back(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string extension = get_file_extension(name);
|
||||
if (extension == "zip" || extension == "7z" || extension == "chd" || extension == "gdi" || ((config::HideLegacyNaomiRoms
|
||||
|| (extension != "bin" && extension != "lst" && extension != "dat"))
|
||||
&& extension != "cdi" && extension != "cue") == false )
|
||||
display_files.push_back(name);
|
||||
if (selectFile)
|
||||
{
|
||||
if (extension == selectExtension)
|
||||
folderFiles.push_back(name);
|
||||
}
|
||||
else if (extension == "zip" || extension == "7z" || extension == "chd"
|
||||
|| extension == "gdi" || extension == "cdi" || extension == "cue"
|
||||
|| (!config::HideLegacyNaomiRoms
|
||||
&& (extension == "bin" || extension == "lst" || extension == "dat")))
|
||||
folderFiles.push_back(name);
|
||||
}
|
||||
}
|
||||
flycast::closedir(dir);
|
||||
#if defined(_WIN32) || defined(__ANDROID__)
|
||||
if (!dotdot_seen)
|
||||
select_subfolders.emplace_back("..");
|
||||
subfolders.emplace_back("..");
|
||||
#else
|
||||
(void)dotdot_seen;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
std::stable_sort(select_subfolders.begin(), select_subfolders.end());
|
||||
std::stable_sort(subfolders.begin(), subfolders.end());
|
||||
std::stable_sort(folderFiles.begin(), folderFiles.end());
|
||||
subfolders_read = true;
|
||||
}
|
||||
|
||||
ImGui::Text("%s", error_message.empty() ? select_current_directory.c_str() : error_message.c_str());
|
||||
ImGui::BeginChild(ImGui::GetID("dir_list"), ImVec2(0, - 30 * scaling - ImGui::GetStyle().ItemSpacing.y), true);
|
||||
ImGui::BeginChild(ImGui::GetID("dir_list"), ImVec2(0, - 30 * gui_get_scaling() - ImGui::GetStyle().ItemSpacing.y), true);
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8 * scaling, 20 * scaling)); // from 8, 4
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8 * gui_get_scaling(), 20 * gui_get_scaling())); // from 8, 4
|
||||
|
||||
|
||||
for (auto& name : select_subfolders)
|
||||
for (const auto& name : subfolders)
|
||||
{
|
||||
std::string child_path;
|
||||
if (name == "..")
|
||||
|
@ -253,23 +261,38 @@ void select_directory_popup(const char *prompt, float scaling, StringCallback ca
|
|||
select_current_directory = child_path;
|
||||
}
|
||||
}
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, { 1, 1, 1, 0.3f });
|
||||
for (auto& name : display_files)
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, { 1, 1, 1, selectFile ? 1.f : 0.3f });
|
||||
for (const auto& name : folderFiles)
|
||||
{
|
||||
if (selectFile)
|
||||
{
|
||||
if (ImGui::Selectable(name.c_str()))
|
||||
{
|
||||
subfolders_read = false;
|
||||
callback(false, select_current_directory + native_separator + name);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("%s", name.c_str());
|
||||
}
|
||||
}
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::EndChild();
|
||||
if (ImGui::Button("Select Current Directory", ImVec2(0, 30 * scaling)))
|
||||
if (!selectFile)
|
||||
{
|
||||
if (ImGui::Button("Select Current Directory", ImVec2(0, 30 * gui_get_scaling())))
|
||||
{
|
||||
subfolders_read = false;
|
||||
callback(false, select_current_directory);
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel", ImVec2(0, 30 * scaling)))
|
||||
}
|
||||
if (ImGui::Button("Cancel", ImVec2(0, 30 * gui_get_scaling())))
|
||||
{
|
||||
subfolders_read = false;
|
||||
callback(true, "");
|
||||
|
|
|
@ -28,11 +28,14 @@
|
|||
#include "vulkan/vulkan_context.h"
|
||||
#include "gui.h"
|
||||
|
||||
extern int screen_width, screen_height;
|
||||
|
||||
typedef void (*StringCallback)(bool cancelled, std::string selection);
|
||||
|
||||
void select_directory_popup(const char *prompt, float scaling, StringCallback callback);
|
||||
void select_file_popup(const char *prompt, StringCallback callback,
|
||||
bool selectFile = false, const std::string& extension = "");
|
||||
|
||||
static inline void ImGui_impl_RenderDrawData(ImDrawData *draw_data, bool save_background = false)
|
||||
static inline void ImGui_impl_RenderDrawData(ImDrawData *draw_data)
|
||||
{
|
||||
#ifdef USE_VULKAN
|
||||
if (!config::RendererType.isOpenGL())
|
||||
|
@ -61,7 +64,7 @@ static inline void ImGui_impl_RenderDrawData(ImDrawData *draw_data, bool save_ba
|
|||
else
|
||||
#endif
|
||||
{
|
||||
ImGui_ImplOpenGL3_RenderDrawData(draw_data, save_background);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(draw_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,3 +82,8 @@ template<typename T>
|
|||
bool OptionRadioButton(const char *name, config::Option<T>& option, T value, const char *help = nullptr);
|
||||
void OptionComboBox(const char *name, config::Option<int>& option, const char *values[], int count,
|
||||
const char *help = nullptr);
|
||||
|
||||
static inline void centerNextWindow()
|
||||
{
|
||||
ImGui::SetNextWindowPos(ImVec2(screen_width / 2.f, screen_height / 2.f), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
|
||||
}
|
||||
|
|
|
@ -126,6 +126,7 @@
|
|||
84B7BF7F1B72720200F9733F /* stdclass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 84B7BEA71B72720200F9733F /* stdclass.cpp */; };
|
||||
84B7BF831B727AD700F9733F /* osx-main.mm in Sources */ = {isa = PBXBuildFile; fileRef = 84B7BF821B727AD700F9733F /* osx-main.mm */; };
|
||||
84B7BF861B72871600F9733F /* EmuGLView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84B7BF851B72871600F9733F /* EmuGLView.swift */; };
|
||||
AE039B40261C61C8005E24C5 /* gui_cheats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE039B3F261C61C8005E24C5 /* gui_cheats.cpp */; };
|
||||
AE1E293B2095FB1600FC6BA2 /* rec_cpp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE1E293A2095FB1600FC6BA2 /* rec_cpp.cpp */; };
|
||||
AE1E294020A96B0B00FC6BA2 /* rec_x64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE1E293F20A96B0B00FC6BA2 /* rec_x64.cpp */; };
|
||||
AE2A24DA22AE7EB600DD3034 /* ssa.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AE2A24D922AE7EB600DD3034 /* ssa.cpp */; };
|
||||
|
@ -665,6 +666,7 @@
|
|||
84B7BF821B727AD700F9733F /* osx-main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "osx-main.mm"; sourceTree = "<group>"; };
|
||||
84B7BF841B72821900F9733F /* emulator-osx-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "emulator-osx-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
84B7BF851B72871600F9733F /* EmuGLView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmuGLView.swift; sourceTree = "<group>"; };
|
||||
AE039B3F261C61C8005E24C5 /* gui_cheats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gui_cheats.cpp; sourceTree = "<group>"; };
|
||||
AE1E293A2095FB1600FC6BA2 /* rec_cpp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rec_cpp.cpp; sourceTree = "<group>"; };
|
||||
AE1E293F20A96B0B00FC6BA2 /* rec_x64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rec_x64.cpp; sourceTree = "<group>"; };
|
||||
AE2A234922941A0500DD3034 /* NaomiConfig.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = NaomiConfig.xcconfig; sourceTree = "<group>"; };
|
||||
|
@ -1993,6 +1995,7 @@
|
|||
84B7BE9B1B72720200F9733F /* gles */,
|
||||
AED73EAB2348E49800ECDB64 /* CustomTexture.cpp */,
|
||||
AED73EAC2348E49900ECDB64 /* CustomTexture.h */,
|
||||
AE039B3F261C61C8005E24C5 /* gui_cheats.cpp */,
|
||||
AEE6279222247C0A00EC7E89 /* gui_util.cpp */,
|
||||
AEE6279322247C0A00EC7E89 /* gui_util.h */,
|
||||
AEE6276A220D7B5500EC7E89 /* gui.cpp */,
|
||||
|
@ -2936,6 +2939,7 @@
|
|||
559E934125FCBFCA001B0F40 /* decoder-aarch64.cc in Sources */,
|
||||
AE7BCB592415515B007285F8 /* arm7_rec.cpp in Sources */,
|
||||
AE649C3C218C555600EF4A81 /* cdrom.c in Sources */,
|
||||
AE039B40261C61C8005E24C5 /* gui_cheats.cpp in Sources */,
|
||||
AE649BF3218C552500EF4A81 /* bitmath.c in Sources */,
|
||||
AE649C30218C553A00EF4A81 /* Sort.c in Sources */,
|
||||
AE82C6B325B64AE200C79BC2 /* zip_source_file_stdio.c in Sources */,
|
||||
|
|
Loading…
Reference in New Issue