feat: merged WHDLoad panel and other improvements from preview

This commit is contained in:
Dimitris Panokostas 2024-03-17 22:12:37 +01:00
parent 5913bfc5ad
commit d0dfc4561a
No known key found for this signature in database
GPG Key ID: 330156A68E9E0929
30 changed files with 2080 additions and 964 deletions

View File

@ -290,6 +290,7 @@ add_executable(${PROJECT_NAME}
src/threaddep/threading.cpp
src/osdep/gui/ControllerMap.cpp
src/osdep/gui/SelectorEntry.cpp
src/osdep/gui/ShowCustomFields.cpp
src/osdep/gui/ShowHelp.cpp
src/osdep/gui/ShowMessage.cpp
src/osdep/gui/ShowDiskInfo.cpp
@ -322,6 +323,7 @@ add_executable(${PROJECT_NAME}
src/osdep/gui/PanelPrio.cpp
src/osdep/gui/PanelSavestate.cpp
src/osdep/gui/PanelVirtualKeyboard.cpp
src/osdep/gui/PanelWHDLoad.cpp
src/osdep/gui/main_window.cpp
src/osdep/gui/Navigation.cpp
src/osdep/vkbd/vkbd.cpp
@ -387,7 +389,8 @@ target_link_options(${PROJECT_NAME} PRIVATE "LINKER:-as-needed,-no-pie")
if (USE_OPENGL)
add_definitions(-DUSE_OPENGL)
find_package(OpenGL REQUIRED)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} PRIVATE ${TARGET_LINK_LIBRARIES} OpenGL::GL)
find_package(GLEW REQUIRED)
TARGET_LINK_LIBRARIES(${PROJECT_NAME} PRIVATE ${TARGET_LINK_LIBRARIES} GLEW OpenGL::GL)
endif ()
add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD

View File

@ -51,7 +51,7 @@ LDFLAGS += -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -lpthread -lz -lpng -lrt
ifdef USE_OPENGL
CFLAGS += -DUSE_OPENGL
LDFLAGS += -lGL
LDFLAGS += -lGLEW -lGL
endif
ifdef USE_LTO
@ -636,6 +636,7 @@ OBJS = \
src/threaddep/threading.o \
src/osdep/gui/ControllerMap.o \
src/osdep/gui/SelectorEntry.o \
src/osdep/gui/ShowCustomFields.o \
src/osdep/gui/ShowHelp.o \
src/osdep/gui/ShowMessage.o \
src/osdep/gui/ShowDiskInfo.o \
@ -668,6 +669,7 @@ OBJS = \
src/osdep/gui/PanelPrio.o \
src/osdep/gui/PanelSavestate.o \
src/osdep/gui/PanelVirtualKeyboard.o \
src/osdep/gui/PanelWHDLoad.o \
src/osdep/gui/main_window.o \
src/osdep/gui/Navigation.o \
src/osdep/vkbd/vkbd.o \
@ -737,7 +739,7 @@ clean:
cleanprofile:
$(RM) $(OBJS:%.o=%.gcda)
$(MAKE) -C external/libguisan cleanprofile
guisan:
$(MAKE) -C external/libguisan

View File

@ -0,0 +1,3 @@
set(CMAKE_C_FLAGS_INIT "-march=x86-64 -msse2 -mfpmath=sse -mstackrealign")
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_C_FLAGS_INIT}")

View File

@ -117,13 +117,13 @@ class Widget;
extern "C"
{
/**
* Gets the the version of Guisan. As it is a C function
/**
* Gets the the version of Guisan. As it is a C function
* it can be used to check for Guisan with autotools.
*
* @return the version of Guisan.
*/
GCN_CORE_DECLSPEC extern const char* gcnGuisanVersion();
*
* @return the version of Guisan.
*/
GCN_CORE_DECLSPEC extern const char* gcnGuisanVersion();
}
#endif // end GCN_GUISAN_HPP

View File

@ -44,7 +44,7 @@
</screenshot>
</screenshots>
<releases>
<release version="5.6.9" date="2024-03-09"/>
<release version="5.6.9" date="2024-03-17"/>
<release version="5.6.8" date="2024-02-29"/>
<release version="5.6.7" date="2024-02-14"/>
<release version="5.6.6" date="2024-01-14"/>

View File

@ -2968,18 +2968,18 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)
#ifdef AMIBERRY
cfg_write(_T("; *** WHDLoad Booter. Options"), f);
cfgfile_write_str(f, _T("whdload_slave"), p->whdbootprefs.slave);
cfgfile_write_bool(f, _T("whdload_showsplash"), p->whdbootprefs.showsplash);
cfgfile_write_bool(f, _T("whdload_buttonwait"), p->whdbootprefs.buttonwait);
cfgfile_dwrite(f, _T("whdload_configdelay"), _T("%d"), p->whdbootprefs.configdelay);
cfgfile_write(f, _T("whdload_custom1"), _T("%d"), p->whdbootprefs.custom1);
cfgfile_write(f, _T("whdload_custom2"), _T("%d"), p->whdbootprefs.custom2);
cfgfile_write(f, _T("whdload_custom3"), _T("%d"), p->whdbootprefs.custom3);
cfgfile_write(f, _T("whdload_custom4"), _T("%d"), p->whdbootprefs.custom4);
cfgfile_write(f, _T("whdload_custom5"), _T("%d"), p->whdbootprefs.custom5);
cfgfile_write_str(f, _T("whdload_custom"), p->whdbootprefs.custom);
cfgfile_write_bool(f, _T("whdload_writecache"), p->whdbootprefs.writecache);
cfgfile_write_bool(f, _T("whdload_quit_on_exit"), p->whdbootprefs.quit_on_exit);
cfgfile_write_str(f, _T("whdload_slave"), whdload_prefs.selected_slave.filename.c_str());
cfgfile_write_bool(f, _T("whdload_showsplash"), whdload_prefs.show_splash);
cfgfile_write_bool(f, _T("whdload_buttonwait"), whdload_prefs.button_wait);
cfgfile_dwrite(f, _T("whdload_configdelay"), _T("%d"), whdload_prefs.config_delay);
cfgfile_write(f, _T("whdload_custom1"), _T("%d"), whdload_prefs.selected_slave.custom1.value);
cfgfile_write(f, _T("whdload_custom2"), _T("%d"), whdload_prefs.selected_slave.custom2.value);
cfgfile_write(f, _T("whdload_custom3"), _T("%d"), whdload_prefs.selected_slave.custom3.value);
cfgfile_write(f, _T("whdload_custom4"), _T("%d"), whdload_prefs.selected_slave.custom4.value);
cfgfile_write(f, _T("whdload_custom5"), _T("%d"), whdload_prefs.selected_slave.custom5.value);
cfgfile_write_str(f, _T("whdload_custom"), whdload_prefs.custom.c_str());
cfgfile_write_bool(f, _T("whdload_writecache"), whdload_prefs.write_cache);
cfgfile_write_bool(f, _T("whdload_quit_on_exit"), whdload_prefs.quit_on_exit);
#endif
}
@ -3518,18 +3518,18 @@ static int cfgfile_parse_host (struct uae_prefs *p, TCHAR *option, TCHAR *value)
}
/* Read in WHDLoad Options */
if (cfgfile_string(option, value, _T("whdload_slave"), p->whdbootprefs.slave, sizeof p->whdbootprefs.slave / sizeof(TCHAR))
|| cfgfile_string(option, value, _T("whdload_custom"), p->whdbootprefs.custom, sizeof p->whdbootprefs.custom / sizeof(TCHAR))
|| cfgfile_intval(option, value, _T("whdload_custom1"), &p->whdbootprefs.custom1, 1)
|| cfgfile_intval(option, value, _T("whdload_custom2"), &p->whdbootprefs.custom2, 1)
|| cfgfile_intval(option, value, _T("whdload_custom3"), &p->whdbootprefs.custom3, 1)
|| cfgfile_intval(option, value, _T("whdload_custom4"), &p->whdbootprefs.custom4, 1)
|| cfgfile_intval(option, value, _T("whdload_custom5"), &p->whdbootprefs.custom5, 1)
|| cfgfile_yesno(option, value, _T("whdload_buttonwait"), &p->whdbootprefs.buttonwait)
|| cfgfile_yesno(option, value, _T("whdload_showsplash"), &p->whdbootprefs.showsplash)
|| cfgfile_intval(option, value, _T("whdload_configdelay"), &p->whdbootprefs.configdelay, 1)
|| cfgfile_yesno(option, value, _T("whdload_writecache"), &p->whdbootprefs.writecache)
|| cfgfile_yesno(option, value, _T("whdload_quit_on_exit"), &p->whdbootprefs.quit_on_exit)
if (cfgfile_string(option, value, _T("whdload_slave"), whdload_prefs.selected_slave.filename)
|| cfgfile_intval(option, value, _T("whdload_custom1"), &whdload_prefs.selected_slave.custom1.value, 1)
|| cfgfile_intval(option, value, _T("whdload_custom2"), &whdload_prefs.selected_slave.custom2.value, 1)
|| cfgfile_intval(option, value, _T("whdload_custom3"), &whdload_prefs.selected_slave.custom3.value, 1)
|| cfgfile_intval(option, value, _T("whdload_custom4"), &whdload_prefs.selected_slave.custom4.value, 1)
|| cfgfile_intval(option, value, _T("whdload_custom5"), &whdload_prefs.selected_slave.custom5.value, 1)
|| cfgfile_string(option, value, _T("whdload_custom"), whdload_prefs.custom)
|| cfgfile_yesno(option, value, _T("whdload_buttonwait"), &whdload_prefs.button_wait)
|| cfgfile_yesno(option, value, _T("whdload_showsplash"), &whdload_prefs.show_splash)
|| cfgfile_intval(option, value, _T("whdload_configdelay"), &whdload_prefs.config_delay, 1)
|| cfgfile_yesno(option, value, _T("whdload_writecache"), &whdload_prefs.write_cache)
|| cfgfile_yesno(option, value, _T("whdload_quit_on_exit"), &whdload_prefs.quit_on_exit)
)
{
return 1;
@ -8380,7 +8380,7 @@ void default_prefs (struct uae_prefs *p, bool reset, int type)
p->sampler_freq = 0;
#ifdef AMIBERRY
p->sound_volume_cd = 20;
p->whdbootprefs.writecache = false;
whdload_prefs.write_cache = false;
#endif
p->comptrustbyte = 0;
p->comptrustword = 0;

View File

@ -161,10 +161,10 @@ extern unsigned int my_read (struct my_openfile_s*, void*, unsigned int);
extern unsigned int my_write (struct my_openfile_s*, void*, unsigned int);
extern int my_truncate (const TCHAR *name, uae_u64 len);
extern int dos_errno (void);
extern int my_existslink(const char* name);
extern int my_existsfile (const TCHAR *name);
extern int my_existsfile2(const TCHAR* name);
extern int my_existsdir (const TCHAR *name);
extern bool my_existslink(const char* name);
extern bool my_existsfile (const TCHAR *name);
extern bool my_existsfile2(const TCHAR* name);
extern bool my_existsdir (const TCHAR *name);
extern FILE *my_opentext (const TCHAR*);
extern bool my_stat (const TCHAR *name, struct mystat *ms);
@ -187,7 +187,7 @@ extern bool my_createshortcut(const TCHAR *source, const TCHAR *target, const TC
#define MYVOLUMEINFO_CDFS 16
extern int my_getvolumeinfo (const TCHAR *root);
extern const std::string my_get_sha1_of_file(const char* filepath);
extern std::string my_get_sha1_of_file(const char* filepath);
#ifdef AMIBERRY
char* fsdb_native_path(const char* root_dir, const char* amiga_path);

View File

@ -11,6 +11,8 @@
#define UAE_OPTIONS_H
#include <array>
#include <vector>
#include "uae/types.h"
#include "traps.h"
@ -18,7 +20,7 @@
#define UAEMAJOR 5
#define UAEMINOR 6
#define UAESUBREV 8
#define UAESUBREV 9
#define MAX_AMIGADISPLAYS 1
@ -533,20 +535,83 @@ struct monconfig
};
#ifdef AMIBERRY
struct whdbooter
enum custom_type
{
int custom1 = 0;
int custom2 = 0;
int custom3 = 0;
int custom4 = 0;
int custom5 = 0;
TCHAR custom[256]{};
bool buttonwait{};
TCHAR slave[4096]{};
bool showsplash{};
int configdelay = 0;
bool writecache{};
bool quit_on_exit{};
none,
bool_type,
bit_type,
list_type
};
struct whdload_custom
{
/**
* \brief The value of this custom field. This will be sent to WHDLoad
*/
int value;
/**
* \brief The type of the custom field: None, Boolean, Bit or List
*/
custom_type type;
/**
* \brief Caption for this custom field function. Used in the label which describes what this option does
*/
std::string caption;
/**
* \brief The list of labels to show in the dropdown. Used in List type custom fields
*/
std::vector<std::string> labels;
/**
* \brief When the type is a Bit, it can contain multiple entries for the same custom field.
* Each entry has it's own label and a different value that goes with it.
*/
std::vector<std::pair<std::string, int>> label_bit_pairs;
};
struct whdload_slave
{
std::string filename;
std::string data_path;
whdload_custom custom1;
whdload_custom custom2;
whdload_custom custom3;
whdload_custom custom4;
whdload_custom custom5;
whdload_custom& get_custom(const int index)
{
switch (index)
{
case 1:
return custom1;
case 2:
return custom2;
case 3:
return custom3;
case 4:
return custom4;
case 5:
return custom5;
default:
return custom1;
}
}
};
struct whdload_options
{
std::string filename;
std::string game_name;
std::string sub_path;
std::string variant_uuid;
int slave_count;
std::string slave_default;
bool slave_libraries;
std::vector<whdload_slave> slaves;
whdload_slave selected_slave;
std::string custom;
bool button_wait;
bool show_splash;
int config_delay;
bool write_cache;
bool quit_on_exit;
};
#endif
@ -1032,11 +1097,12 @@ struct uae_prefs
bool use_retroarch_statebuttons;
bool use_retroarch_vkbd;
struct whdbooter whdbootprefs;
#endif
};
extern whdload_options whdload_prefs;
extern int config_changed, config_changed_flags;
extern void config_check_vsync(void);
extern void set_config_changed(int flags = 0);
@ -1143,7 +1209,7 @@ extern bool cfgfile_createconfigstore(struct uae_prefs* p);
extern void cfgfile_get_shader_config(struct uae_prefs* p, int rtg);
#ifdef AMIBERRY
extern void whdload_auto_prefs(struct uae_prefs* prefs, char* filepath);
extern void whdload_auto_prefs(struct uae_prefs* prefs, const char* filepath);
extern void cd_auto_prefs(struct uae_prefs* prefs, char* filepath);
extern void symlink_roms(struct uae_prefs* prefs);
extern void drawbridge_update_profiles(struct uae_prefs* prefs);

View File

@ -74,7 +74,7 @@
#include "fsdb_host.h"
#include "keyboard.h"
static const char __ver[40] = "$VER: Amiberry 5.6.9 (2024-3-09)";
static const char __ver[40] = "$VER: Amiberry 5.6.9 (2024-03-17)";
long int version = 256 * 65536L * UAEMAJOR + 65536L * UAEMINOR + UAESUBREV;
struct uae_prefs currprefs, changed_prefs;

View File

@ -110,6 +110,7 @@ bool host_poweroff = false;
int relativepaths = 0;
int saveimageoriginalpath = 0;
struct whdload_options whdload_prefs = {};
struct amiberry_options amiberry_options = {};
struct amiberry_gui_theme gui_theme = {};
amiberry_hotkey enter_gui_key;
@ -1502,6 +1503,9 @@ void process_event(SDL_Event event)
case SDL_MOUSEMOTION:
{
if (event.window.windowID != SDL_GetWindowID(mon->sdl_window))
return;
// This will be useful when/if SDL2 supports more than 1 mouse.
// Currently, it always returns 0.
auto wm = event.motion.which;
@ -2211,11 +2215,11 @@ void target_default_options(struct uae_prefs* p, int type)
p->use_retroarch_reset = amiberry_options.default_retroarch_reset;
p->use_retroarch_vkbd = amiberry_options.default_retroarch_vkbd;
p->whdbootprefs.buttonwait = amiberry_options.default_whd_buttonwait;
p->whdbootprefs.showsplash = amiberry_options.default_whd_showsplash;
p->whdbootprefs.configdelay = amiberry_options.default_whd_configdelay;
p->whdbootprefs.writecache = amiberry_options.default_whd_writecache;
p->whdbootprefs.quit_on_exit = amiberry_options.default_whd_quit_on_exit;
whdload_prefs.button_wait = amiberry_options.default_whd_buttonwait;
whdload_prefs.show_splash = amiberry_options.default_whd_showsplash;
whdload_prefs.config_delay = amiberry_options.default_whd_configdelay;
whdload_prefs.write_cache = amiberry_options.default_whd_writecache;
whdload_prefs.quit_on_exit = amiberry_options.default_whd_quit_on_exit;
if (amiberry_options.default_soundcard > 0) p->soundcard = amiberry_options.default_soundcard;
@ -2975,7 +2979,7 @@ int target_cfgfile_load(struct uae_prefs* p, const char* filename, int type, int
p->floppyslots[i].df[0] = 0;
disk_insert(i, p->floppyslots[i].df);
if (strlen(p->floppyslots[i].df) > 0)
AddFileToDiskList(p->floppyslots[i].df, 1);
add_file_to_mru_list(lstMRUDiskList, std::string(p->floppyslots[i].df));
}
if (!isdefault)
@ -3023,6 +3027,12 @@ void extract_filename(const char* str, char* buffer)
strncpy(buffer, p, MAX_DPATH - 1);
}
std::string extract_filename(const std::string& path)
{
const std::filesystem::path file_path(path);
return file_path.filename().string();
}
void extract_path(char* str, char* buffer)
{
strncpy(buffer, str, MAX_DPATH - 1);
@ -3051,7 +3061,7 @@ void remove_file_extension(char* filename)
std::string remove_file_extension(const std::string& filename)
{
const size_t last_dot = filename.find_last_of(".");
const size_t last_dot = filename.find_last_of('.');
if (last_dot == std::string::npos) {
// No extension found, return the original filename
return filename;
@ -3059,50 +3069,43 @@ std::string remove_file_extension(const std::string& filename)
return filename.substr(0, last_dot);
}
void read_directory(const std::string path, std::vector<std::string>* dirs, std::vector<std::string>* files)
void read_directory(const std::string& path, std::vector<std::string>* dirs, std::vector<std::string>* files)
{
struct dirent* dent;
if (dirs != nullptr)
dirs->clear();
if (files != nullptr)
files->clear();
auto* const dir = opendir(path.c_str());
if (dir != nullptr)
// check if the path exists first
if (!std::filesystem::exists(path))
return;
for (const auto& entry : std::filesystem::directory_iterator(path))
{
while ((dent = readdir(dir)) != nullptr)
if (entry.is_directory())
{
if (dent->d_type == DT_DIR)
{
if (dirs != nullptr
&& (dent->d_name[0] != '.' || (dent->d_name[0] == '.' && dent->d_name[1] == '.')))
dirs->emplace_back(dent->d_name);
}
else if (dent->d_type == DT_LNK)
{
struct stat stbuf{};
stat(dent->d_name, &stbuf);
if (S_ISDIR(stbuf.st_mode))
{
if (dirs != nullptr
&& (dent->d_name[0] != '.' || (dent->d_name[0] == '.' && dent->d_name[1] == '.')))
dirs->emplace_back(dent->d_name);
}
else
{
if (files != nullptr && dent->d_name[0] != '.')
files->emplace_back(dent->d_name);
}
}
else if (files != nullptr && dent->d_name[0] != '.')
files->emplace_back(dent->d_name);
if (dirs != nullptr && (entry.path().filename().string()[0] != '.' || (entry.path().filename().string()[0] == '.' && entry.path().filename().string()[1] == '.')))
dirs->emplace_back(entry.path().filename().string());
}
if (dirs != nullptr && !dirs->empty() && (*dirs)[0] == ".")
dirs->erase(dirs->begin());
closedir(dir);
else if (entry.is_symlink())
{
if (std::filesystem::is_directory(entry))
{
if (dirs != nullptr && (entry.path().filename().string()[0] != '.' || (entry.path().filename().string()[0] == '.' && entry.path().filename().string()[1] == '.')))
dirs->emplace_back(entry.path().filename().string());
}
else
{
if (files != nullptr && entry.path().filename().string()[0] != '.')
files->emplace_back(entry.path().filename().string());
}
}
else if (files != nullptr && entry.path().filename().string()[0] != '.')
files->emplace_back(entry.path().filename().string());
}
if (dirs != nullptr && !dirs->empty() && (*dirs)[0] == ".")
dirs->erase(dirs->begin());
if (dirs != nullptr)
sort(dirs->begin(), dirs->end());
if (files != nullptr)
@ -3117,300 +3120,222 @@ void save_amiberry_settings(void)
char buffer[MAX_DPATH];
auto write_bool_option = [&](const char* name, bool value) {
snprintf(buffer, MAX_DPATH, "%s=%s\n", name, value ? "yes" : "no");
fputs(buffer, f);
};
auto write_int_option = [&](const char* name, int value) {
snprintf(buffer, MAX_DPATH, "%s=%d\n", name, value);
fputs(buffer, f);
};
auto write_string_option = [&](const char* name, const std::string& value) {
snprintf(buffer, MAX_DPATH, "%s=%s\n", name, value.c_str());
fputs(buffer, f);
};
// Should the Quickstart Panel be the default when opening the GUI?
snprintf(buffer, MAX_DPATH, "Quickstart=%d\n", amiberry_options.quickstart_start);
fputs(buffer, f);
write_int_option("Quickstart", amiberry_options.quickstart_start);
// Open each config file and read the Description field?
// This will slow down scanning the config list if it's very large
snprintf(buffer, MAX_DPATH, "read_config_descriptions=%s\n", amiberry_options.read_config_descriptions ? "yes" : "no");
fputs(buffer, f);
write_bool_option("read_config_descriptions", amiberry_options.read_config_descriptions);
// Write to logfile?
// If enabled, a file named "amiberry_log.txt" will be generated in the startup folder
snprintf(buffer, MAX_DPATH, "write_logfile=%s\n", amiberry_options.write_logfile ? "yes" : "no");
fputs(buffer, f);
write_bool_option("write_logfile", amiberry_options.write_logfile);
// Scanlines ON by default?
// This will only be enabled if the vertical height is enough, as we need Line Doubling set to ON also
// Beware this comes with a performance hit, as double the amount of lines need to be drawn on-screen
snprintf(buffer, MAX_DPATH, "default_line_mode=%d\n", amiberry_options.default_line_mode);
fputs(buffer, f);
write_int_option("default_line_mode", amiberry_options.default_line_mode);
// Map RCtrl key to RAmiga key?
// This helps with keyboards that may not have 2 Win keys and no Menu key either
snprintf(buffer, MAX_DPATH, "rctrl_as_ramiga=%s\n", amiberry_options.rctrl_as_ramiga ? "yes" : "no");
fputs(buffer, f);
write_bool_option("rctrl_as_ramiga", amiberry_options.rctrl_as_ramiga);
// Disable controller in the GUI?
// If you want to disable the default behavior for some reason
snprintf(buffer, MAX_DPATH, "gui_joystick_control=%s\n", amiberry_options.gui_joystick_control ? "yes" : "no");
fputs(buffer, f);
write_bool_option("gui_joystick_control", amiberry_options.gui_joystick_control);
// Use a separate thread for drawing native chipset output
// This helps with performance, but may cause glitches in some cases
snprintf(buffer, MAX_DPATH, "default_multithreaded_drawing=%s\n", amiberry_options.default_multithreaded_drawing ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_multithreaded_drawing", amiberry_options.default_multithreaded_drawing);
// Default mouse input speed
snprintf(buffer, MAX_DPATH, "input_default_mouse_speed=%d\n", amiberry_options.input_default_mouse_speed);
fputs(buffer, f);
write_int_option("input_default_mouse_speed", amiberry_options.input_default_mouse_speed);
// When using Keyboard as Joystick, stop any double keypresses
snprintf(buffer, MAX_DPATH, "input_keyboard_as_joystick_stop_keypresses=%s\n", amiberry_options.input_keyboard_as_joystick_stop_keypresses ? "yes" : "no");
fputs(buffer, f);
write_bool_option("input_keyboard_as_joystick_stop_keypresses", amiberry_options.input_keyboard_as_joystick_stop_keypresses);
// Default key for opening the GUI (e.g. "F12")
snprintf(buffer, MAX_DPATH, "default_open_gui_key=%s\n", amiberry_options.default_open_gui_key);
fputs(buffer, f);
write_string_option("default_open_gui_key", amiberry_options.default_open_gui_key);
// Default key for Quitting the emulator
snprintf(buffer, MAX_DPATH, "default_quit_key=%s\n", amiberry_options.default_quit_key);
fputs(buffer, f);
write_string_option("default_quit_key", amiberry_options.default_quit_key);
// Default key for opening Action Replay
snprintf(buffer, MAX_DPATH, "default_ar_key=%s\n", amiberry_options.default_ar_key);
fputs(buffer, f);
write_string_option("default_ar_key", amiberry_options.default_ar_key);
// Default key for Fullscreen Toggle
snprintf(buffer, MAX_DPATH, "default_fullscreen_toggle_key=%s\n", amiberry_options.default_fullscreen_toggle_key);
fputs(buffer, f);
write_string_option("default_fullscreen_toggle_key", amiberry_options.default_fullscreen_toggle_key);
// Rotation angle of the output display (useful for screens with portrait orientation, like the Go Advance)
snprintf(buffer, MAX_DPATH, "rotation_angle=%d\n", amiberry_options.rotation_angle);
fputs(buffer, f);
write_int_option("rotation_angle", amiberry_options.rotation_angle);
// Enable Horizontal Centering by default?
snprintf(buffer, MAX_DPATH, "default_horizontal_centering=%s\n", amiberry_options.default_horizontal_centering ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_horizontal_centering", amiberry_options.default_horizontal_centering);
// Enable Vertical Centering by default?
snprintf(buffer, MAX_DPATH, "default_vertical_centering=%s\n", amiberry_options.default_vertical_centering ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_vertical_centering", amiberry_options.default_vertical_centering);
// Scaling method to use by default?
// Valid options are: -1 Auto, 0 Nearest Neighbor, 1 Linear
snprintf(buffer, MAX_DPATH, "default_scaling_method=%d\n", amiberry_options.default_scaling_method);
fputs(buffer, f);
write_int_option("default_scaling_method", amiberry_options.default_scaling_method);
// Enable frameskip by default?
snprintf(buffer, MAX_DPATH, "default_frameskip=%s\n", amiberry_options.default_frameskip ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_frameskip", amiberry_options.default_frameskip);
// Correct Aspect Ratio by default?
snprintf(buffer, MAX_DPATH, "default_correct_aspect_ratio=%s\n", amiberry_options.default_correct_aspect_ratio ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_correct_aspect_ratio", amiberry_options.default_correct_aspect_ratio);
// Enable Auto-Height by default?
snprintf(buffer, MAX_DPATH, "default_auto_crop=%s\n", amiberry_options.default_auto_crop ? "yes" : "no");
fputs(buffer, f);
// Enable Auto-Crop by default?
write_bool_option("default_auto_crop", amiberry_options.default_auto_crop);
// Default Screen Width
snprintf(buffer, MAX_DPATH, "default_width=%d\n", amiberry_options.default_width);
fputs(buffer, f);
write_int_option("default_width", amiberry_options.default_width);
// Default Screen Height
snprintf(buffer, MAX_DPATH, "default_height=%d\n", amiberry_options.default_height);
fputs(buffer, f);
write_int_option("default_height", amiberry_options.default_height);
// Full screen mode (0, 1, 2)
snprintf(buffer, MAX_DPATH, "default_fullscreen_mode=%d\n", amiberry_options.default_fullscreen_mode);
fputs(buffer, f);
write_int_option("default_fullscreen_mode", amiberry_options.default_fullscreen_mode);
// Default Stereo Separation
snprintf(buffer, MAX_DPATH, "default_stereo_separation=%d\n", amiberry_options.default_stereo_separation);
fputs(buffer, f);
write_int_option("default_stereo_separation", amiberry_options.default_stereo_separation);
// Default Sound buffer size
snprintf(buffer, MAX_DPATH, "default_sound_buffer=%d\n", amiberry_options.default_sound_buffer);
fputs(buffer, f);
write_int_option("default_sound_buffer", amiberry_options.default_sound_buffer);
// Default Sound Mode (Pull/Push)
snprintf(buffer, MAX_DPATH, "default_sound_pull=%s\n", amiberry_options.default_sound_pull ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_sound_pull", amiberry_options.default_sound_pull);
// Default Joystick Deadzone
snprintf(buffer, MAX_DPATH, "default_joystick_deadzone=%d\n", amiberry_options.default_joystick_deadzone);
fputs(buffer, f);
write_int_option("default_joystick_deadzone", amiberry_options.default_joystick_deadzone);
// Enable RetroArch Quit by default?
snprintf(buffer, MAX_DPATH, "default_retroarch_quit=%s\n", amiberry_options.default_retroarch_quit ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_retroarch_quit", amiberry_options.default_retroarch_quit);
// Enable RetroArch Menu by default?
snprintf(buffer, MAX_DPATH, "default_retroarch_menu=%s\n", amiberry_options.default_retroarch_menu ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_retroarch_menu", amiberry_options.default_retroarch_menu);
// Enable RetroArch Reset by default?
snprintf(buffer, MAX_DPATH, "default_retroarch_reset=%s\n", amiberry_options.default_retroarch_reset ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_retroarch_reset", amiberry_options.default_retroarch_reset);
// Enable RetroArch Reset by default?
snprintf(buffer, MAX_DPATH, "default_retroarch_vkbd=%s\n", amiberry_options.default_retroarch_vkbd ? "yes" : "no");
fputs(buffer, f);
// Enable RetroArch VKBD by default?
write_bool_option("default_retroarch_vkbd", amiberry_options.default_retroarch_vkbd);
// Controller1
snprintf(buffer, MAX_DPATH, "default_controller1=%s\n", amiberry_options.default_controller1);
fputs(buffer, f);
write_string_option("default_controller1", amiberry_options.default_controller1);
// Controller2
snprintf(buffer, MAX_DPATH, "default_controller2=%s\n", amiberry_options.default_controller2);
fputs(buffer, f);
write_string_option("default_controller2", amiberry_options.default_controller2);
// Controller3
snprintf(buffer, MAX_DPATH, "default_controller3=%s\n", amiberry_options.default_controller3);
fputs(buffer, f);
write_string_option("default_controller3", amiberry_options.default_controller3);
// Controller4
snprintf(buffer, MAX_DPATH, "default_controller4=%s\n", amiberry_options.default_controller4);
fputs(buffer, f);
write_string_option("default_controller4", amiberry_options.default_controller4);
// Mouse1
snprintf(buffer, MAX_DPATH, "default_mouse1=%s\n", amiberry_options.default_mouse1);
fputs(buffer, f);
write_string_option("default_mouse1", amiberry_options.default_mouse1);
// Mouse2
snprintf(buffer, MAX_DPATH, "default_mouse2=%s\n", amiberry_options.default_mouse2);
fputs(buffer, f);
write_string_option("default_mouse2", amiberry_options.default_mouse2);
// WHDLoad ButtonWait
snprintf(buffer, MAX_DPATH, "default_whd_buttonwait=%s\n", amiberry_options.default_whd_buttonwait ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_whd_buttonwait", amiberry_options.default_whd_buttonwait);
// WHDLoad Show Splash screen
snprintf(buffer, MAX_DPATH, "default_whd_showsplash=%s\n", amiberry_options.default_whd_showsplash ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_whd_showsplash", amiberry_options.default_whd_showsplash);
// WHDLoad Config Delay
snprintf(buffer, MAX_DPATH, "default_whd_configdelay=%d\n", amiberry_options.default_whd_configdelay);
fputs(buffer, f);
write_int_option("default_whd_configdelay", amiberry_options.default_whd_configdelay);
// WHDLoad WriteCache
snprintf(buffer, MAX_DPATH, "default_whd_writecache=%s\n", amiberry_options.default_whd_writecache ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_whd_writecache", amiberry_options.default_whd_writecache);
// WHDLoad Quit emulator after game exits
snprintf(buffer, MAX_DPATH, "default_whd_quit_on_exit=%s\n", amiberry_options.default_whd_quit_on_exit ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_whd_quit_on_exit", amiberry_options.default_whd_quit_on_exit);
// Disable Shutdown button in GUI
snprintf(buffer, MAX_DPATH, "disable_shutdown_button=%s\n", amiberry_options.disable_shutdown_button ? "yes" : "no");
fputs(buffer, f);
write_bool_option("disable_shutdown_button", amiberry_options.disable_shutdown_button);
// Allow Display settings to be used from the WHDLoad XML (override amiberry.conf defaults)
snprintf(buffer, MAX_DPATH, "allow_display_settings_from_xml=%s\n", amiberry_options.allow_display_settings_from_xml ? "yes" : "no");
fputs(buffer, f);
write_bool_option("allow_display_settings_from_xml", amiberry_options.allow_display_settings_from_xml);
// Default Sound Card (0=default, first one available in the system)
snprintf(buffer, MAX_DPATH, "default_soundcard=%d\n", amiberry_options.default_soundcard);
fputs(buffer, f);
write_int_option("default_soundcard", amiberry_options.default_soundcard);
// Enable Virtual Keyboard by default
snprintf(buffer, MAX_DPATH, "default_vkbd_enabled=%s\n", amiberry_options.default_vkbd_enabled ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_vkbd_enabled", amiberry_options.default_vkbd_enabled);
// Show the High-res version of the Virtual Keyboard by default
snprintf(buffer, MAX_DPATH, "default_vkbd_hires=%s\n", amiberry_options.default_vkbd_hires ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_vkbd_hires", amiberry_options.default_vkbd_hires);
// Enable Quit functionality through Virtual Keyboard by default
snprintf(buffer, MAX_DPATH, "default_vkbd_exit=%s\n", amiberry_options.default_vkbd_exit ? "yes" : "no");
fputs(buffer, f);
write_bool_option("default_vkbd_exit", amiberry_options.default_vkbd_exit);
// Default Language for the Virtual Keyboard
snprintf(buffer, MAX_DPATH, "default_vkbd_language=%s\n", amiberry_options.default_vkbd_language);
fputs(buffer, f);
write_string_option("default_vkbd_language", amiberry_options.default_vkbd_language);
// Default Style for the Virtual Keyboard
snprintf(buffer, MAX_DPATH, "default_vkbd_style=%s\n", amiberry_options.default_vkbd_style);
fputs(buffer, f);
write_string_option("default_vkbd_style", amiberry_options.default_vkbd_style);
// Default transparency for the Virtual Keyboard
snprintf(buffer, MAX_DPATH, "default_vkbd_transparency=%d\n", amiberry_options.default_vkbd_transparency);
fputs(buffer, f);
write_int_option("default_vkbd_transparency", amiberry_options.default_vkbd_transparency);
// Default controller button for toggling the Virtual Keyboard
snprintf(buffer, MAX_DPATH, "default_vkbd_toggle=%s\n", amiberry_options.default_vkbd_toggle);
fputs(buffer, f);
write_string_option("default_vkbd_toggle", amiberry_options.default_vkbd_toggle);
// GUI Theme: Font name
snprintf(buffer, MAX_DPATH, "gui_theme_font_name=%s\n", amiberry_options.gui_theme_font_name);
fputs(buffer, f);
write_string_option("gui_theme_font_name", amiberry_options.gui_theme_font_name);
// GUI Theme: Font size
snprintf(buffer, MAX_DPATH, "gui_theme_font_size=%d\n", amiberry_options.gui_theme_font_size);
fputs(buffer, f);
write_int_option("gui_theme_font_size", amiberry_options.gui_theme_font_size);
// GUI Theme: Base color
snprintf(buffer, MAX_DPATH, "gui_theme_base_color=%s\n", amiberry_options.gui_theme_base_color);
fputs(buffer, f);
write_string_option("gui_theme_base_color", amiberry_options.gui_theme_base_color);
// GUI Theme: Selector Inactive color
snprintf(buffer, MAX_DPATH, "gui_theme_selector_inactive=%s\n", amiberry_options.gui_theme_selector_inactive);
fputs(buffer, f);
write_string_option("gui_theme_selector_inactive", amiberry_options.gui_theme_selector_inactive);
// GUI Theme: Selector Active color
snprintf(buffer, MAX_DPATH, "gui_theme_selector_active=%s\n", amiberry_options.gui_theme_selector_active);
fputs(buffer, f);
write_string_option("gui_theme_selector_active", amiberry_options.gui_theme_selector_active);
// GUI Theme: Textbox Background color
snprintf(buffer, MAX_DPATH, "gui_theme_textbox_background=%s\n", amiberry_options.gui_theme_textbox_background);
fputs(buffer, f);
write_string_option("gui_theme_textbox_background", amiberry_options.gui_theme_textbox_background);
// Paths
snprintf(buffer, MAX_DPATH, "path=%s\n", current_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "config_path=%s\n", config_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "controllers_path=%s\n", controllers_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "retroarch_config=%s\n", retroarch_file.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "whdboot_path=%s\n", whdboot_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "whdload_arch_path=%s\n", whdload_arch_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "logfile_path=%s\n", logfile_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "rom_path=%s\n", rom_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "rp9_path=%s\n", rp9_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "floppy_sounds_dir=%s\n", floppy_sounds_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "data_dir=%s\n", data_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "saveimage_dir=%s\n", saveimage_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "savestate_dir=%s\n", savestate_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "ripper_dir=%s\n", ripper_path.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "inputrecordings_dir=%s\n", input_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "screenshot_dir=%s\n", screenshot_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "nvram_dir=%s\n", nvram_dir.c_str());
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "video_dir=%s\n", video_dir.c_str());
fputs(buffer, f);
write_string_option("path", current_dir);
write_string_option("config_path", config_path);
write_string_option("controllers_path", controllers_path);
write_string_option("retroarch_config", retroarch_file);
write_string_option("whdboot_path", whdboot_path);
write_string_option("whdload_arch_path", whdload_arch_path);
write_string_option("logfile_path", logfile_path);
write_string_option("rom_path", rom_path);
write_string_option("rp9_path", rp9_path);
write_string_option("floppy_sounds_dir", floppy_sounds_dir);
write_string_option("data_dir", data_dir);
write_string_option("saveimage_dir", saveimage_dir);
write_string_option("savestate_dir", savestate_dir);
write_string_option("screenshot_dir", screenshot_dir);
write_string_option("ripper_path", ripper_path);
write_string_option("inputrecordings_dir", input_dir);
write_string_option("nvram_dir", nvram_dir);
write_string_option("video_dir", video_dir);
// The number of ROMs in the last scan
snprintf(buffer, MAX_DPATH, "ROMs=%zu\n", lstAvailableROMs.size());
@ -3419,12 +3344,9 @@ void save_amiberry_settings(void)
// The ROMs found in the last scan
for (auto& lstAvailableROM : lstAvailableROMs)
{
snprintf(buffer, MAX_DPATH, "ROMName=%s\n", lstAvailableROM->Name);
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "ROMPath=%s\n", lstAvailableROM->Path);
fputs(buffer, f);
snprintf(buffer, MAX_DPATH, "ROMType=%d\n", lstAvailableROM->ROMType);
fputs(buffer, f);
write_string_option("ROMName", lstAvailableROM->Name);
write_string_option("ROMPath", lstAvailableROM->Path);
write_int_option("ROMType", lstAvailableROM->ROMType);
}
// Recent disk entries (these are used in the dropdown controls)
@ -3432,8 +3354,7 @@ void save_amiberry_settings(void)
fputs(buffer, f);
for (auto& i : lstMRUDiskList)
{
snprintf(buffer, MAX_DPATH, "Diskfile=%s\n", i.c_str());
fputs(buffer, f);
write_string_option("Diskfile", i);
}
// Recent CD entries (these are used in the dropdown controls)
@ -3441,8 +3362,7 @@ void save_amiberry_settings(void)
fputs(buffer, f);
for (auto& i : lstMRUCDList)
{
snprintf(buffer, MAX_DPATH, "CDfile=%s\n", i.c_str());
fputs(buffer, f);
write_string_option("CDfile", i);
}
// Recent WHDLoad entries (these are used in the dropdown controls)
@ -3451,8 +3371,7 @@ void save_amiberry_settings(void)
fputs(buffer, f);
for (auto& i : lstMRUWhdloadList)
{
snprintf(buffer, MAX_DPATH, "WHDLoadfile=%s\n", i.c_str());
fputs(buffer, f);
write_string_option("WHDLoadfile", i);
}
fclose(f);
@ -3681,7 +3600,7 @@ static int get_env_dir( char * path, const char *path_template, const char *envn
return ret;
}
void init_macos_amiberry_folders(std::string macos_amiberry_directory)
void init_macos_amiberry_folders(const std::string& macos_amiberry_directory)
{
if (!my_existsdir(macos_amiberry_directory.c_str()))
my_mkdir(macos_amiberry_directory.c_str());
@ -4088,12 +4007,12 @@ int main(int argc, char* argv[])
sortdisplays();
enumerate_sound_devices();
for (int i = 0; i < MAX_SOUND_DEVICES && sound_devices[i]; i++) {
int type = sound_devices[i]->type;
const int type = sound_devices[i]->type;
write_log(_T("%d:%s: %s\n"), i, type == SOUND_DEVICE_SDL2 ? _T("SDL2") : (type == SOUND_DEVICE_DS ? _T("DS") : (type == SOUND_DEVICE_AL ? _T("AL") : (type == SOUND_DEVICE_WASAPI ? _T("WA") : (type == SOUND_DEVICE_WASAPI_EXCLUSIVE ? _T("WX") : _T("PA"))))), sound_devices[i]->name);
}
write_log(_T("Enumerating recording devices:\n"));
for (int i = 0; i < MAX_SOUND_DEVICES && record_devices[i]; i++) {
int type = record_devices[i]->type;
const int type = record_devices[i]->type;
write_log(_T("%d:%s: %s\n"), i, type == SOUND_DEVICE_SDL2 ? _T("SDL2") : (type == SOUND_DEVICE_DS ? _T("DS") : (type == SOUND_DEVICE_AL ? _T("AL") : (type == SOUND_DEVICE_WASAPI ? _T("WA") : (type == SOUND_DEVICE_WASAPI_EXCLUSIVE ? _T("WX") : _T("PA"))))), record_devices[i]->name);
}
write_log(_T("done\n"));
@ -4220,7 +4139,7 @@ bool get_plugin_path(TCHAR* out, int len, const TCHAR* path)
void drawbridge_update_profiles(uae_prefs* p)
{
#ifdef FLOPPYBRIDGE
unsigned int flags = (p->drawbridge_autocache ? 1 : 0) | (p->drawbridge_connected_drive_b & 1) << 1 | (p->drawbridge_serial_auto ? 4 : 0) | (p->drawbridge_smartspeed ? 8 : 0);
const unsigned int flags = (p->drawbridge_autocache ? 1 : 0) | (p->drawbridge_connected_drive_b & 1) << 1 | (p->drawbridge_serial_auto ? 4 : 0) | (p->drawbridge_smartspeed ? 8 : 0);
const std::string profile_name_fast = "Fast";
const std::string profile_name_comp = "Compatible";
@ -4269,3 +4188,17 @@ struct netdriverdata **target_ethernet_enumerate(void)
net_enumerated = 1;
return ndd;
}
void clear_whdload_prefs()
{
whdload_prefs.filename.clear();
whdload_prefs.game_name.clear();
whdload_prefs.sub_path.clear();
whdload_prefs.variant_uuid.clear();
whdload_prefs.slave_count = 0;
whdload_prefs.slave_default.clear();
whdload_prefs.slave_libraries = false;
whdload_prefs.slaves = {};
whdload_prefs.selected_slave = {};
whdload_prefs.custom.clear();
}

View File

@ -18,6 +18,7 @@
#include <filesystem>
#endif
#include <set>
#include <sys/mman.h>
#include "crc32.h"
@ -41,45 +42,44 @@ struct my_openfile_s {
void utf8_to_latin1_string(std::string& input, std::string& output)
{
std::vector<char> in_buf(input.begin(), input.end());
char* src_ptr = &in_buf[0];
char* src_ptr = in_buf.data();
size_t src_size = input.size();
std::vector<char> buf(1024);
std::string dst;
auto* iconv_ = iconv_open("ISO-8859-1//TRANSLIT", "UTF-8");
while (0 < src_size) {
char* dst_ptr = &buf[0];
while (src_size > 0) {
char* dst_ptr = buf.data();
size_t dst_size = buf.size();
size_t res = ::iconv(iconv_, &src_ptr, &src_size, &dst_ptr, &dst_size);
if (res == (size_t)-1) {
if (errno == E2BIG) {
// ignore this error
}
else {
if (errno != E2BIG) {
// skip character
++src_ptr;
--src_size;
}
}
dst.append(&buf[0], buf.size() - dst_size);
dst.append(buf.data(), buf.size() - dst_size);
}
dst.swap(output);
output = std::move(dst);
iconv_close(iconv_);
}
std::string iso_8859_1_to_utf8(std::string& str)
std::string iso_8859_1_to_utf8(const std::string& str)
{
string str_out;
for (auto it = str.begin(); it != str.end(); ++it)
std::string str_out;
str_out.reserve(str.size() * 2); // Reserve space to avoid reallocations
for (const auto& ch : str)
{
uint8_t ch = *it;
if (ch < 0x80) {
str_out.push_back(ch);
uint8_t byte = static_cast<uint8_t>(ch);
if (byte < 0x80) {
str_out.push_back(byte);
}
else {
str_out.push_back(0xc0 | ch >> 6);
str_out.push_back(0x80 | (ch & 0x3f));
str_out.push_back(0xc0 | byte >> 6);
str_out.push_back(0x80 | (byte & 0x3f));
}
}
return str_out;
@ -209,54 +209,50 @@ bool my_chmod(const TCHAR* name, uae_u32 mode)
{
// Note: only used to set or clear write protect on disk file
// get current state
struct stat st{};
auto input = string(name);
auto output = iso_8859_1_to_utf8(input);
// Convert input to UTF-8
auto output = iso_8859_1_to_utf8(string(name));
// Get current state
struct stat st {};
if (stat(output.c_str(), &st) == -1) {
write_log("my_chmod: stat on file %s failed\n", output.c_str());
return false;
}
// Prepare new mode
auto newmode = st.st_mode;
if (mode & FILEFLAG_WRITE)
// set write permission
st.st_mode |= S_IWUSR;
newmode |= S_IWUSR; // set write permission
else
// clear write permission
st.st_mode &= ~(S_IWUSR);
chmod(output.c_str(), st.st_mode);
newmode &= ~S_IWUSR; // clear write permission
stat(output.c_str(), &st);
auto newmode = 0;
if (st.st_mode & S_IRUSR) {
newmode |= FILEFLAG_READ;
}
if (st.st_mode & S_IWUSR) {
newmode |= FILEFLAG_WRITE;
// Change mode
if (chmod(output.c_str(), newmode) == -1) {
write_log("my_chmod: chmod on file %s failed\n", output.c_str());
return false;
}
return (mode == newmode);
return true;
}
bool my_stat(const TCHAR* name, struct mystat* statbuf)
{
struct stat st{};
if (!name || !statbuf) {
write_log("my_stat: null arguments provided\n");
return false;
}
struct stat st {};
auto output = iso_8859_1_to_utf8(string(name));
auto input = string(name);
auto output = iso_8859_1_to_utf8(input);
if (stat(output.c_str(), &st) == -1) {
write_log("my_stat: stat on file %s failed\n", output.c_str());
return false;
}
statbuf->size = st.st_size;
statbuf->mode = 0;
if (st.st_mode & S_IRUSR) {
statbuf->mode |= FILEFLAG_READ;
}
if (st.st_mode & S_IWUSR) {
statbuf->mode |= FILEFLAG_WRITE;
}
statbuf->mode = ((st.st_mode & S_IRUSR) ? FILEFLAG_READ : 0) |
((st.st_mode & S_IWUSR) ? FILEFLAG_WRITE : 0);
statbuf->mtime.tv_sec = st.st_mtime;
statbuf->mtime.tv_usec = 0;
@ -265,29 +261,42 @@ bool my_stat(const TCHAR* name, struct mystat* statbuf)
bool compare_nocase(const std::string& first, const std::string& second)
{
unsigned int i = 0;
while ((i < first.length()) && (i < second.length()))
const auto len = std::min(first.length(), second.length());
for (unsigned int i = 0; i < len; ++i)
{
if (tolower(first[i]) < tolower(second[i])) return true;
else if (tolower(first[i]) > tolower(second[i])) return false;
++i;
const auto first_ch = std::tolower(first[i]);
const auto second_ch = std::tolower(second[i]);
if (first_ch != second_ch)
return first_ch < second_ch;
}
return (first.length() < second.length());
return first.length() < second.length();
}
struct my_opendir_s* my_opendir(const TCHAR* name, const TCHAR* mask)
{
auto* mod = xmalloc(struct my_opendir_s, 1);
if (!mod)
return NULL;
auto input = string(name);
auto output = iso_8859_1_to_utf8(input);
mod->dir = opendir(output.c_str());
if (!mod->dir) {
write_log("my_opendir %s failed\n", name);
xfree(mod);
if (!name) {
write_log("my_opendir: null directory name provided\n");
return NULL;
}
auto* mod = new my_opendir_s;
if (!mod) {
write_log("my_opendir: memory allocation failed\n");
return NULL;
}
auto output = iso_8859_1_to_utf8(string(name));
mod->dir = opendir(output.c_str());
if (!mod->dir) {
write_log("my_opendir: opendir on directory %s failed\n", name);
delete mod;
return NULL;
}
return mod;
}
@ -305,99 +314,77 @@ void my_closedir(struct my_opendir_s* mod)
int my_readdir(struct my_opendir_s* mod, TCHAR* name)
{
if (!mod)
if (!mod || !name)
return 0;
const set<std::string> ignoreList = { "_UAEFSDB.___", "Thumbs.db", ".DS_Store", "UAEFS.ini" };
while (true)
{
auto* entry = readdir(mod->dir);
if (entry == NULL)
return 0;
auto* result = entry->d_name;
const int len = strlen(result);
if (strcasecmp(result, "_UAEFSDB.___") == 0) {
continue;
}
if (strcasecmp(result, "Thumbs.db") == 0) {
continue;
}
if (strcasecmp(result, ".DS_Store") == 0) {
continue;
}
if (strcasecmp(result, "UAEFS.ini") == 0) {
continue;
}
if (len > 5 && strncmp(result + len - 5, ".uaem", 5) == 0) {
// ignore metadata / attribute files, obviously
if (ignoreList.find(result) != ignoreList.end() ||
(len > 5 && strncmp(result + len - 5, ".uaem", 5) == 0)) {
continue;
}
auto string_input = string(result);
string string_output;
utf8_to_latin1_string(string_input, string_output);
//write_log("Original: %s - Converted: %s\n", string_input.c_str(), string_output.c_str());
_tcscpy(name, string_output.c_str());
return 1;
}
}
int my_existslink(const char* name)
bool my_existslink(const char* name)
{
struct stat st {};
if (lstat(name, &st) == -1)
{
return 0;
if (!name) {
write_log("my_existslink: null file name provided\n");
return false;
}
if (S_ISLNK(st.st_mode))
return 1;
return 0;
struct stat st {};
if (lstat(name, &st) == -1) {
write_log("my_existslink: lstat on file %s failed\n", name);
return false;
}
return S_ISLNK(st.st_mode);
}
int my_existsfile2(const char* name)
bool my_existsfile2(const char* name)
{
struct stat st {};
if (lstat(name, &st) == -1)
{
return 0;
}
if (!S_ISDIR(st.st_mode))
return 1;
return 0;
return lstat(name, &st) != -1 && !S_ISDIR(st.st_mode);
}
int my_existsfile(const char* name)
bool my_existsfile(const char* name)
{
struct stat st {};
auto input = string(name);
auto output = iso_8859_1_to_utf8(input);
if (lstat(output.c_str(), &st) == -1)
{
return 0;
}
if (!S_ISDIR(st.st_mode))
return 1;
return 0;
auto output = iso_8859_1_to_utf8(string(name));
return lstat(output.c_str(), &st) != -1 && !S_ISDIR(st.st_mode);
}
int my_existsdir(const char* name)
bool my_existsdir(const char* name)
{
struct stat st {};
auto input = string(name);
auto output = iso_8859_1_to_utf8(input);
if (lstat(output.c_str(), &st) == -1)
{
return 0;
}
if (S_ISDIR(st.st_mode))
return 1;
return 0;
auto output = iso_8859_1_to_utf8(string(name));
return lstat(output.c_str(), &st) != -1 && S_ISDIR(st.st_mode);
}
uae_s64 my_fsize(struct my_openfile_s* mos)
{
if (mos == nullptr) {
write_log("my_fsize: null pointer provided\n");
return -1;
}
struct stat st {};
if (fstat(mos->fd, &st) == -1) {
write_log("my_fsize: fstat on file %s failed\n", mos->path);
@ -408,48 +395,67 @@ uae_s64 my_fsize(struct my_openfile_s* mos)
int my_getvolumeinfo(const char* root)
{
if (root == nullptr) {
write_log("my_getvolumeinfo: null pointer provided\n");
return -1;
}
struct stat st {};
auto ret = 0;
if (lstat(root, &st) == -1)
if (lstat(root, &st) == -1) {
write_log("my_getvolumeinfo: lstat on file %s failed\n", root);
return -1;
if (!S_ISDIR(st.st_mode))
}
if (!S_ISDIR(st.st_mode)) {
write_log("my_getvolumeinfo: %s is not a directory\n", root);
return -2;
}
ret |= MYVOLUMEINFO_STREAMS;
return ret;
}
bool fs_path_exists(const std::string& s)
{
struct stat buffer{};
auto input = string(s);
auto output = iso_8859_1_to_utf8(input);
if (s.empty()) {
write_log("fs_path_exists: empty string provided\n");
return false;
}
struct stat buffer {};
auto output = iso_8859_1_to_utf8(s);
return stat(output.c_str(), &buffer) == 0;
}
struct my_openfile_s* my_open(const TCHAR* name, int flags)
{
struct my_openfile_s* mos;
mos = xmalloc(struct my_openfile_s, 1);
if (!mos)
if (name == nullptr) {
write_log("my_open: null pointer provided\n");
return NULL;
auto input = string(name);
auto output = iso_8859_1_to_utf8(input);
if (flags & O_CREAT)
{
}
auto* mos = xmalloc(struct my_openfile_s, 1);
if (!mos) {
write_log("my_open: memory allocation failed\n");
return NULL;
}
auto output = iso_8859_1_to_utf8(string(name));
if (flags & O_CREAT) {
mos->fd = open(output.c_str(), flags, 0660);
}
else
{
else {
mos->fd = open(output.c_str(), flags);
}
if (!mos->fd) {
if (mos->fd == -1) {
write_log("my_open: open on file %s failed\n", name);
xfree(mos);
mos = NULL;
return NULL;
}
return mos;
}
@ -462,35 +468,63 @@ void my_close(struct my_openfile_s* mos)
unsigned int my_read(struct my_openfile_s* mos, void* b, unsigned int size)
{
const auto bytes_read = read(mos->fd, b, size);
if (bytes_read == -1)
{
write_log("WARNING: my_read failed (-1)\n");
if (mos == nullptr) {
write_log("my_read: null file pointer provided\n");
return 0;
}
if (b == nullptr) {
write_log("my_read: null buffer pointer provided\n");
return 0;
}
const auto bytes_read = read(mos->fd, b, size);
if (bytes_read == -1) {
write_log("my_read: read on file %s failed with error %s\n", mos->path, strerror(errno));
return 0;
}
else if (bytes_read < size) {
write_log("my_read: read on file %s returned less bytes than requested\n", mos->path);
}
return static_cast<unsigned int>(bytes_read);
}
unsigned int my_write(struct my_openfile_s* mos, void* b, unsigned int size)
{
const auto bytes_written = write(mos->fd, b, size);
if (bytes_written == -1)
{
write_log("WARNING: my_write failed (-1) fd=%d buffer=%p size=%d\n",
mos->fd, b, size);
write_log("errno %d\n", errno);
write_log(" mos %p -> h=%d\n", mos, mos->fd);
if (mos == nullptr) {
write_log("my_write: null file pointer provided\n");
return 0;
}
if (b == nullptr) {
write_log("my_write: null buffer pointer provided\n");
return 0;
}
const auto bytes_written = write(mos->fd, b, size);
if (bytes_written == -1) {
write_log("my_write: write on file %s failed with error %s\n", mos->path, strerror(errno));
return 0;
}
else if (bytes_written < size) {
write_log("my_write: write on file %s wrote less bytes than requested\n", mos->path);
}
return static_cast<unsigned int>(bytes_written);
}
int my_mkdir(const TCHAR* path)
{
auto input = string(path);
auto output = iso_8859_1_to_utf8(input);
if (path == nullptr) {
write_log("my_mkdir: null pointer provided\n");
return -1;
}
auto output = iso_8859_1_to_utf8(string(path));
int error = mkdir(output.c_str(), 0755);
if (error) {
write_log("my_mkdir: mkdir on path %s failed with error %s\n", path, strerror(errno));
return -1;
}
return 0;
@ -498,87 +532,192 @@ int my_mkdir(const TCHAR* path)
int my_truncate(const TCHAR* name, uae_u64 len)
{
int int_len = (int)len;
struct my_openfile_s* mos = my_open(name, O_WRONLY);
if (mos == NULL) {
write_log("WARNING: opening file for truncation failed\n");
if (name == nullptr) {
write_log("my_truncate: null pointer provided\n");
return -1;
}
struct my_openfile_s* mos = my_open(name, O_WRONLY);
if (mos == NULL) {
write_log("my_truncate: opening file %s for truncation failed\n", name);
return -1;
}
int result;
#ifdef WINDOWS
int result = _chsize(mos->fd, int_len);
if (len > INT_MAX) {
write_log("my_truncate: length %llu is too large for _chsize\n", len);
result = -1;
}
else {
result = _chsize(mos->fd, static_cast<int>(len));
}
#else
int result = ftruncate(mos->fd, int_len);
result = ftruncate(mos->fd, len);
#endif
if (result == -1) {
write_log("my_truncate: truncating file %s failed with error %s\n", name, strerror(errno));
}
my_close(mos);
return result;
}
static void remove_extra_file(const char* path, const char* name)
{
auto* p = (TCHAR*)malloc(MAX_DPATH);
_tcscpy(p, path);
fix_trailing(p);
strcat(p, name);
unlink(p);
xfree(p);
std::string p(path);
p = fix_trailing(p);
p += name;
unlink(p.c_str());
}
bool my_isfilehidden (const TCHAR *path)
bool my_isfilehidden(const char* path)
{
return false;
if (path == nullptr)
{
return false;
}
std::string filename(path);
return filename[0] == '.';
}
void my_setfilehidden (const TCHAR *path, bool hidden)
void my_setfilehidden(const TCHAR* path, bool hidden)
{
if (path == nullptr)
{
return;
}
std::string filename(path);
#ifdef _WIN32
DWORD attrs = GetFileAttributes(path);
if (hidden)
{
attrs |= FILE_ATTRIBUTE_HIDDEN;
}
else
{
attrs &= ~FILE_ATTRIBUTE_HIDDEN;
}
SetFileAttributes(path, attrs);
#else
std::string newname;
if (hidden)
{
if (filename[0] != '.')
{
newname = "." + filename;
rename(filename.c_str(), newname.c_str());
}
}
else
{
if (filename[0] == '.')
{
newname = filename.substr(1);
rename(filename.c_str(), newname.c_str());
}
}
#endif
}
int my_rmdir(const TCHAR* path)
{
if (path == nullptr) {
write_log("my_rmdir: null directory path provided\n");
return -1;
}
remove_extra_file(path, "Thumbs.db");
remove_extra_file(path, ".DS_Store");
errno = 0;
auto input = string(path);
auto output = iso_8859_1_to_utf8(input);
auto output = iso_8859_1_to_utf8(string(path));
int result = rmdir(output.c_str());
if (result != 0) {
write_log("my_rmdir: rmdir on directory %s failed with error %d\n", path, errno);
}
return result;
}
int my_unlink(const TCHAR* path)
{
if (path == nullptr) {
write_log("my_unlink: null file path provided\n");
return -1;
}
errno = 0;
auto input = string(path);
auto output = iso_8859_1_to_utf8(input);
auto output = iso_8859_1_to_utf8(string(path));
int result = unlink(output.c_str());
if (result != 0) {
write_log("my_unlink: unlink on file %s failed with error %d\n", path, errno);
}
return result;
}
int my_rename(const TCHAR* oldname, const TCHAR* newname)
{
errno = 0;
auto old_input = string(oldname);
auto old_output = iso_8859_1_to_utf8(old_input);
auto new_input = string(newname);
auto new_output = iso_8859_1_to_utf8(new_input);
if (oldname == nullptr || newname == nullptr) {
write_log("my_rename: null file name provided\n");
return -1;
}
return rename(old_output.c_str(), new_output.c_str());
errno = 0;
auto old_output = iso_8859_1_to_utf8(string(oldname));
auto new_output = iso_8859_1_to_utf8(string(newname));
int result = rename(old_output.c_str(), new_output.c_str());
if (result != 0) {
write_log("my_rename: rename from %s to %s failed with error %d\n", oldname, newname, errno);
}
return result;
}
uae_s64 my_lseek(struct my_openfile_s* mos, uae_s64 offset, int whence)
{
if (mos == nullptr) {
write_log("my_lseek: null file descriptor provided\n");
return -1;
}
errno = 0;
return lseek(mos->fd, offset, whence);
auto result = lseek(mos->fd, offset, whence);
if (result == -1) {
write_log("my_lseek: lseek on file %s failed with error %d\n", mos->path, errno);
}
return result;
}
FILE* my_opentext(const TCHAR* name)
{
auto input = string(name);
auto output = iso_8859_1_to_utf8(input);
return fopen(output.c_str(), "rb");
if (name == nullptr) {
write_log("my_opentext: null file name provided\n");
return nullptr;
}
auto output = iso_8859_1_to_utf8(string(name));
FILE* file = fopen(output.c_str(), "rb");
if (file == nullptr) {
write_log("my_opentext: fopen on file %s failed\n", name);
}
return file;
}
bool my_createshortcut(const char* source, const char* target, const char* description)
@ -648,37 +787,55 @@ int host_errno_to_dos_errno(int err)
void my_canonicalize_path(const TCHAR* path, TCHAR* out, int size)
{
_tcsncpy(out, path, size);
out[size - 1] = 0;
return;
if (path == nullptr || out == nullptr) {
write_log("my_canonicalize_path: null arguments provided\n");
return;
}
_tcsncpy(out, path, size - 1);
out[size - 1] = '\0';
}
bool my_issamepath(const TCHAR* path1, const TCHAR* path2)
{
if (path1 == nullptr || path2 == nullptr) {
write_log("my_issamepath: null path provided\n");
return false;
}
return _tcsicmp(path1, path2) == 0;
}
int my_issamevolume(const TCHAR* path1, const TCHAR* path2, TCHAR* path)
{
if (path1 == nullptr || path2 == nullptr || path == nullptr) {
write_log("my_issamevolume: null arguments provided\n");
return 0;
}
TCHAR p1[MAX_DPATH];
TCHAR p2[MAX_DPATH];
unsigned int len, cnt;
my_canonicalize_path(path1, p1, sizeof p1 / sizeof(TCHAR));
my_canonicalize_path(path2, p2, sizeof p2 / sizeof(TCHAR));
len = _tcslen(p1);
unsigned int len = _tcslen(p1);
if (len > _tcslen(p2))
len = _tcslen(p2);
if (_tcsnicmp(p1, p2, len))
return 0;
_tcscpy(path, p2 + len);
cnt = 0;
unsigned int cnt = 0;
for (unsigned int i = 0; i < _tcslen(path); i++) {
if (path[i] == '\\' || path[i] == '/') {
path[i] = '/';
cnt++;
}
}
write_log(_T("'%s' (%s) matched with '%s' (%s), extra = '%s'\n"), path1, p1, path2, p2, path);
return cnt;
}
@ -709,7 +866,7 @@ int dos_errno(void)
#endif
default:
write_log(("Unimplemented error %s\n", strerror(e)));
write_log(_T("Unimplemented error %s\n"), strerror(e));
return ERROR_NOT_IMPLEMENTED;
}
}
@ -729,13 +886,13 @@ int target_get_volume_name(struct uaedev_mount_info* mtinf, struct uaedev_config
// If replace is false, copyfile will fail if file already exists
bool copyfile(const char* target, const char* source, const bool replace)
{
#ifdef USE_OLDGCC
#ifdef USE_OLDGCC
std::experimental::filesystem::copy_options options = {};
options = replace ? experimental::filesystem::copy_options::overwrite_existing : experimental::filesystem::copy_options::none;
#else
#else
std::filesystem::copy_options options = {};
options = replace ? filesystem::copy_options::overwrite_existing : filesystem::copy_options::none;
#endif
#endif
return copy_file(source, target, options);
}
@ -744,32 +901,37 @@ void filesys_addexternals(void)
// this would mount system drives on Windows
}
const std::string my_get_sha1_of_file(const char* filepath)
std::string my_get_sha1_of_file(const char* filepath)
{
void* mem;
struct stat sb;
int fd = -1;
int ret = 0;
int len;
if ((fd = open((char*)filepath, O_RDONLY)) < 0) ret = (-3);
if (ret == 0 && fstat(fd, &sb) < 0) ret = (-2);
if (ret == 0) {
if ((mem = mmap((caddr_t)0, (int)sb.st_size,
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) != MAP_FAILED) {
len = (int)sb.st_size;
}
else ret = (-1);
if (filepath == nullptr) {
write_log("my_get_sha1_of_file: null file path provided\n");
return "";
}
if (ret > (-3)) close(fd);
int fd = open(filepath, O_RDONLY);
if (fd < 0) {
write_log("my_get_sha1_of_file: open on file %s failed\n", filepath);
return "";
}
if (ret < 0) return NULL;
struct stat sb;
if (fstat(fd, &sb) < 0) {
write_log("my_get_sha1_of_file: fstat on file %s failed\n", filepath);
close(fd);
return "";
}
const TCHAR* sha1 = get_sha1_txt(mem, len);
void* mem = mmap(nullptr, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (mem == MAP_FAILED) {
write_log("my_get_sha1_of_file: mmap on file %s failed\n", filepath);
close(fd);
return "";
}
munmap((caddr_t)mem, (size_t)len);
const TCHAR* sha1 = get_sha1_txt(mem, sb.st_size);
munmap(mem, sb.st_size);
close(fd);
return string(sha1);
}

View File

@ -4,6 +4,9 @@
#include <cstdlib>
#include <cstdarg>
#include <fstream>
#include <algorithm>
#include <vector>
#include <string>
#include <guisan.hpp>
#include <guisan/sdl.hpp>
@ -94,83 +97,25 @@ std::string get_full_path_from_disk_list(std::string element)
return full_path;
}
void AddFileToDiskList(const char *file, int moveToTop)
void add_file_to_mru_list(std::vector<std::string>& vec, const std::string& file)
{
unsigned int i;
for (i = 0; i < lstMRUDiskList.size(); ++i)
{
if (!stricmp(lstMRUDiskList[i].c_str(), file))
{
if (moveToTop)
{
lstMRUDiskList.erase(lstMRUDiskList.begin() + i);
lstMRUDiskList.insert(lstMRUDiskList.begin(), file);
}
break;
}
// Check if the string already exists in the vector
if (std::find(vec.begin(), vec.end(), file) == vec.end()) {
// The string does not exist in the vector, so add it at the first position
vec.insert(vec.begin(), file);
}
if (i >= lstMRUDiskList.size())
lstMRUDiskList.insert(lstMRUDiskList.begin(), file);
while (lstMRUDiskList.size() > MAX_MRU_DISKLIST)
lstMRUDiskList.pop_back();
}
void AddFileToCDList(const char *file, int moveToTop)
{
unsigned int i;
for (i = 0; i < lstMRUCDList.size(); ++i)
{
if (!stricmp(lstMRUCDList[i].c_str(), file))
{
if (moveToTop)
{
lstMRUCDList.erase(lstMRUCDList.begin() + i);
lstMRUCDList.insert(lstMRUCDList.begin(), file);
}
break;
}
}
if (i >= lstMRUCDList.size())
lstMRUCDList.insert(lstMRUCDList.begin(), file);
while (lstMRUCDList.size() > MAX_MRU_CDLIST)
lstMRUCDList.pop_back();
}
void AddFileToWHDLoadList(const char* file, int moveToTop)
{
unsigned int i;
for (i = 0; i < lstMRUWhdloadList.size(); ++i)
{
if (!stricmp(lstMRUWhdloadList[i].c_str(), file))
{
if (moveToTop)
{
lstMRUWhdloadList.erase(lstMRUWhdloadList.begin() + i);
lstMRUWhdloadList.insert(lstMRUWhdloadList.begin(), file);
}
break;
}
}
if (i >= lstMRUWhdloadList.size())
lstMRUWhdloadList.insert(lstMRUWhdloadList.begin(), file);
while (lstMRUWhdloadList.size() > MAX_MRU_WHDLOADLIST)
lstMRUWhdloadList.pop_back();
while (vec.size() > MAX_MRU_LIST)
vec.pop_back();
}
void ClearAvailableROMList()
{
while (!lstAvailableROMs.empty())
for (const auto* rom : lstAvailableROMs)
{
auto* const tmp = lstAvailableROMs[0];
lstAvailableROMs.erase(lstAvailableROMs.begin());
delete tmp;
delete rom;
}
lstAvailableROMs.clear();
}
static void addrom(struct romdata* rd, const char* path)
@ -321,7 +266,7 @@ void RescanROMs()
if (dir != "..")
{
std::string full_path = std::string(path).append(dir);
read_directory(full_path.c_str(), nullptr, &files);
read_directory(full_path, nullptr, &files);
for (auto & file : files)
{
std::string tmp_path = full_path;
@ -346,12 +291,11 @@ void RescanROMs()
static void ClearConfigFileList()
{
while (!ConfigFilesList.empty())
for (const auto* config : ConfigFilesList)
{
auto* const tmp = ConfigFilesList[0];
ConfigFilesList.erase(ConfigFilesList.begin());
delete tmp;
delete config;
}
ConfigFilesList.clear();
}
void ReadConfigFileList(void)
@ -404,7 +348,7 @@ void ReadConfigFileList(void)
ConfigFileInfo* SearchConfigInList(const char* name)
{
for (auto & i : ConfigFilesList)
for (const auto & i : ConfigFilesList)
{
if (!SDL_strncasecmp(i->Name, name, MAX_DPATH))
return i;
@ -426,7 +370,7 @@ void disk_selection(const int drive, uae_prefs* prefs)
{
strncpy(prefs->floppyslots[drive].df, tmp.c_str(), MAX_DPATH);
disk_insert(drive, tmp.c_str());
AddFileToDiskList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUDiskList, tmp);
current_dir = extract_path(tmp);
}
}
@ -543,68 +487,11 @@ int gui_update()
remove_file_extension(savestate_fname);
remove_file_extension(screenshot_filename);
switch(currentStateNum)
{
case 1:
strncat(savestate_fname,"-1.uss", MAX_DPATH - 1);
screenshot_filename.append("-1.png");
break;
case 2:
strncat(savestate_fname,"-2.uss", MAX_DPATH - 1);
screenshot_filename.append("-2.png");
break;
case 3:
strncat(savestate_fname,"-3.uss", MAX_DPATH - 1);
screenshot_filename.append("-3.png");
break;
case 4:
strncat(savestate_fname, "-4.uss", MAX_DPATH - 1);
screenshot_filename.append("-4.png");
break;
case 5:
strncat(savestate_fname, "-5.uss", MAX_DPATH - 1);
screenshot_filename.append("-5.png");
break;
case 6:
strncat(savestate_fname, "-6.uss", MAX_DPATH - 1);
screenshot_filename.append("-6.png");
break;
case 7:
strncat(savestate_fname, "-7.uss", MAX_DPATH - 1);
screenshot_filename.append("-7.png");
break;
case 8:
strncat(savestate_fname, "-8.uss", MAX_DPATH - 1);
screenshot_filename.append("-8.png");
break;
case 9:
strncat(savestate_fname, "-9.uss", MAX_DPATH - 1);
screenshot_filename.append("-9.png");
break;
case 10:
strncat(savestate_fname, "-10.uss", MAX_DPATH - 1);
screenshot_filename.append("-10.png");
break;
case 11:
strncat(savestate_fname, "-11.uss", MAX_DPATH - 1);
screenshot_filename.append("-11.png");
break;
case 12:
strncat(savestate_fname, "-12.uss", MAX_DPATH - 1);
screenshot_filename.append("-12.png");
break;
case 13:
strncat(savestate_fname, "-13.uss", MAX_DPATH - 1);
screenshot_filename.append("-13.png");
break;
case 14:
strncat(savestate_fname, "-14.uss", MAX_DPATH - 1);
screenshot_filename.append("-14.png");
break;
default:
strncat(savestate_fname,".uss", MAX_DPATH - 1);
screenshot_filename.append(".png");
}
std::string suffix = (currentStateNum >= 1 && currentStateNum <= 14) ?
"-" + std::to_string(currentStateNum) : "";
strncat(savestate_fname, (suffix + ".uss").c_str(), MAX_DPATH - 1);
screenshot_filename.append(suffix + ".png");
return 0;
}
@ -648,7 +535,7 @@ void gui_display(int shortcut)
inputdevice_copyconfig(&changed_prefs, &currprefs);
inputdevice_config_change_test();
clearallkeys ();
update_display(&changed_prefs);
if (resumepaused(7)) {
inputdevice_acquire(TRUE);
setmouseactive(0, 1);
@ -1125,30 +1012,30 @@ void DisplayDiskInfo(int num)
snprintf(title, MAX_DPATH - 1, "Info for %s", nameonly);
snprintf(linebuffer, sizeof(linebuffer) - 1, "Disk readable: %s", di.unreadable ? _T("No") : _T("Yes"));
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
snprintf(linebuffer, sizeof(linebuffer) - 1, "Disk CRC32: %08X", di.imagecrc32);
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
snprintf(linebuffer, sizeof(linebuffer) - 1, "Boot block CRC32: %08X", di.bootblockcrc32);
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
snprintf(linebuffer, sizeof(linebuffer) - 1, "Boot block checksum valid: %s", di.bb_crc_valid ? _T("Yes") : _T("No"));
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
snprintf(linebuffer, sizeof(linebuffer) - 1, "Boot block type: %s", di.bootblocktype == 0 ? _T("Custom") : (di.bootblocktype == 1 ? _T("Standard 1.x") : _T("Standard 2.x+")));
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
if (di.diskname[0]) {
snprintf(linebuffer, sizeof(linebuffer) - 1, "Label: '%s'", di.diskname);
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
}
infotext.push_back("");
infotext.emplace_back("");
if (di.bootblockinfo[0]) {
infotext.push_back("Amiga Bootblock Reader database detected:");
infotext.emplace_back("Amiga Bootblock Reader database detected:");
snprintf(linebuffer, sizeof(linebuffer) - 1, "Name: '%s'", di.bootblockinfo);
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
if (di.bootblockclass[0]) {
snprintf(linebuffer, sizeof(linebuffer) - 1, "Class: '%s'", di.bootblockclass);
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
}
infotext.push_back("");
infotext.emplace_back("");
}
int w = 16;
@ -1163,13 +1050,13 @@ void DisplayDiskInfo(int num)
}
linebuffer[w * 3] = ' ';
linebuffer[w * 3 + 1 + w] = 0;
infotext.push_back(linebuffer);
infotext.emplace_back(linebuffer);
}
ShowDiskInfo(title, infotext);
}
void save_mapping_to_file(std::string mapping)
void save_mapping_to_file(const std::string& mapping)
{
std::string filename = get_controllers_path();
filename.append("gamecontrollerdb_user.txt");
@ -1178,7 +1065,7 @@ void save_mapping_to_file(std::string mapping)
file_output.open(filename, ios::app);
if (file_output.is_open())
{
file_output << std::endl << mapping << std::endl;
file_output << '\n' << mapping << '\n';
file_output.close();
}
}

View File

@ -1081,7 +1081,7 @@ static const TCHAR* get_joystick_friendlyname(const int joy)
static const TCHAR* get_joystick_uniquename(const int joy)
{
TCHAR tmp[MAX_DPATH];
_stprintf(tmp, _T("JOY%d"), joy);
_sntprintf(tmp, MAX_DPATH, _T("JOY%d"), joy);
return my_strdup(tmp);
}

View File

@ -31,7 +31,7 @@ enum
A1200_CONFIG = 2 // 8MB fast ram
};
struct game_options
struct game_hardware_options
{
std::string port0 = "nul";
std::string port1 = "nul";
@ -71,12 +71,6 @@ TCHAR uae_config[255];
TCHAR whd_config[255];
TCHAR whd_startup[255];
TCHAR game_name[MAX_DPATH];
TCHAR selected_slave[MAX_DPATH];
TCHAR sub_path[MAX_DPATH];
TCHAR data_path[MAX_DPATH];
TCHAR use_slave_libs = false;
static TCHAR* parse_text(const TCHAR* s)
{
if (*s == '"' || *s == '\'')
@ -147,11 +141,11 @@ void parse_cfg_line(uae_prefs* prefs, const std::string& line_string)
xfree(line);
}
void parse_custom_settings(uae_prefs* p, const char* settings)
void parse_custom_settings(uae_prefs* p, const std::string& settings)
{
const std::string lf = "\n";
const std::string check = "amiberry_custom";
auto full_line = trim_full_line(string(settings));
auto full_line = trim_full_line(settings);
auto lf_found = full_line.find(lf);
while (lf_found != std::string::npos)
@ -173,38 +167,38 @@ void parse_custom_settings(uae_prefs* p, const char* settings)
}
}
std::string find_whdload_game_option(const TCHAR* find_setting, const char* whd_options)
std::string find_whdload_game_option(const std::string& find_setting, const std::string& whd_options)
{
return find_substring(string(find_setting), string(whd_options));
return find_substring(find_setting, whd_options);
}
game_options get_game_settings(const char* HW)
game_hardware_options get_game_hardware_settings(const std::string& hardware)
{
game_options output_detail;
output_detail.port0 = find_whdload_game_option("PORT0", HW);
output_detail.port1 = find_whdload_game_option("PORT1", HW);
output_detail.control = find_whdload_game_option("PRIMARY_CONTROL", HW);
output_detail.control2 = find_whdload_game_option("SECONDARY_CONTROL", HW);
output_detail.cpu = find_whdload_game_option("CPU", HW);
output_detail.blitter = find_whdload_game_option("BLITTER", HW);
output_detail.clock = find_whdload_game_option("CLOCK", HW);
output_detail.chipset = find_whdload_game_option("CHIPSET", HW);
output_detail.jit = find_whdload_game_option("JIT", HW);
output_detail.cpu_24bit = find_whdload_game_option("CPU_24BITADDRESSING", HW);
output_detail.cpu_comp = find_whdload_game_option("CPU_COMPATIBLE", HW);
output_detail.sprites = find_whdload_game_option("SPRITES", HW);
output_detail.scr_height = find_whdload_game_option("SCREEN_HEIGHT", HW);
output_detail.scr_width = find_whdload_game_option("SCREEN_WIDTH", HW);
output_detail.scr_autoheight = find_whdload_game_option("SCREEN_AUTOHEIGHT", HW);
output_detail.scr_centerh = find_whdload_game_option("SCREEN_CENTERH", HW);
output_detail.scr_centerv = find_whdload_game_option("SCREEN_CENTERV", HW);
output_detail.scr_offseth = find_whdload_game_option("SCREEN_OFFSETH", HW);
output_detail.scr_offsetv = find_whdload_game_option("SCREEN_OFFSETV", HW);
output_detail.ntsc = find_whdload_game_option("NTSC", HW);
output_detail.fast = find_whdload_game_option("FAST_RAM", HW);
output_detail.z3 = find_whdload_game_option("Z3_RAM", HW);
output_detail.cpu_exact = find_whdload_game_option("CPU_EXACT", HW);
output_detail.fastcopper = find_whdload_game_option("FAST_COPPER", HW);
game_hardware_options output_detail;
output_detail.port0 = find_whdload_game_option("PORT0", hardware);
output_detail.port1 = find_whdload_game_option("PORT1", hardware);
output_detail.control = find_whdload_game_option("PRIMARY_CONTROL", hardware);
output_detail.control2 = find_whdload_game_option("SECONDARY_CONTROL", hardware);
output_detail.cpu = find_whdload_game_option("CPU", hardware);
output_detail.blitter = find_whdload_game_option("BLITTER", hardware);
output_detail.clock = find_whdload_game_option("CLOCK", hardware);
output_detail.chipset = find_whdload_game_option("CHIPSET", hardware);
output_detail.jit = find_whdload_game_option("JIT", hardware);
output_detail.cpu_24bit = find_whdload_game_option("CPU_24BITADDRESSING", hardware);
output_detail.cpu_comp = find_whdload_game_option("CPU_COMPATIBLE", hardware);
output_detail.sprites = find_whdload_game_option("SPRITES", hardware);
output_detail.scr_height = find_whdload_game_option("SCREEN_HEIGHT", hardware);
output_detail.scr_width = find_whdload_game_option("SCREEN_WIDTH", hardware);
output_detail.scr_autoheight = find_whdload_game_option("SCREEN_AUTOHEIGHT", hardware);
output_detail.scr_centerh = find_whdload_game_option("SCREEN_CENTERH", hardware);
output_detail.scr_centerv = find_whdload_game_option("SCREEN_CENTERV", hardware);
output_detail.scr_offseth = find_whdload_game_option("SCREEN_OFFSETH", hardware);
output_detail.scr_offsetv = find_whdload_game_option("SCREEN_OFFSETV", hardware);
output_detail.ntsc = find_whdload_game_option("NTSC", hardware);
output_detail.fast = find_whdload_game_option("FAST_RAM", hardware);
output_detail.z3 = find_whdload_game_option("Z3_RAM", hardware);
output_detail.cpu_exact = find_whdload_game_option("CPU_EXACT", hardware);
output_detail.fastcopper = find_whdload_game_option("FAST_COPPER", hardware);
return output_detail;
}
@ -289,11 +283,11 @@ void symlink_roms(struct uae_prefs* prefs)
}
}
void get_game_name(char* filepath)
std::string get_game_filename(const char* filepath)
{
extract_filename(filepath, last_loaded_config);
extract_filename(filepath, game_name);
remove_file_extension(game_name);
const std::string game_name = extract_filename(filepath);
return remove_file_extension(game_name);
}
void set_jport_modes(uae_prefs* prefs, const bool is_cd32)
@ -322,10 +316,10 @@ void clear_jports(uae_prefs* prefs)
}
}
void build_uae_config_filename()
void build_uae_config_filename(const std::string& game_name)
{
_tcscpy(uae_config, conf_path);
_tcscat(uae_config, game_name);
_tcscat(uae_config, game_name.c_str());
_tcscat(uae_config, ".uae");
}
@ -336,11 +330,11 @@ void cd_auto_prefs(uae_prefs* prefs, char* filepath)
write_log("\nCD Autoload: %s \n\n", filepath);
get_configuration_path(conf_path, MAX_DPATH);
get_game_name(filepath);
whdload_prefs.filename = get_game_filename(filepath);
// LOAD GAME SPECIFICS FOR EXISTING .UAE - USE SHA1 IF AVAILABLE
// CONFIG LOAD IF .UAE IS IN CONFIG PATH
build_uae_config_filename();
build_uae_config_filename(whdload_prefs.filename);
if (my_existsfile2(uae_config))
{
@ -374,11 +368,11 @@ void cd_auto_prefs(uae_prefs* prefs, char* filepath)
}
// enable CD
_stprintf(tmp, "cd32cd=1");
_sntprintf(tmp, MAX_DPATH, "cd32cd=1");
cfgfile_parse_line(prefs, parse_text(tmp), 0);
// mount the image
_stprintf(tmp, "cdimage0=%s,image", filepath);
_sntprintf(tmp, MAX_DPATH, "cdimage0=%s,image", filepath);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
//APPLY THE SETTINGS FOR MOUSE/JOYSTICK ETC
@ -422,7 +416,7 @@ void cd_auto_prefs(uae_prefs* prefs, char* filepath)
}
}
void set_input_settings(uae_prefs* prefs, const game_options& game_detail, const bool is_cd32)
void set_input_settings(uae_prefs* prefs, const game_hardware_options& game_detail, const bool is_cd32)
{
// APPLY SPECIAL CONFIG E.G. MOUSE OR ALT. JOYSTICK SETTINGS
clear_jports(prefs);
@ -503,7 +497,7 @@ void set_input_settings(uae_prefs* prefs, const game_options& game_detail, const
}
}
void parse_gfx_settings(uae_prefs* prefs, const game_options& game_detail)
void set_gfx_settings(uae_prefs* prefs, const game_hardware_options& game_detail)
{
std::string line_string;
// SCREEN AUTO-HEIGHT
@ -680,7 +674,7 @@ void parse_gfx_settings(uae_prefs* prefs, const game_options& game_detail)
}
}
void set_compatibility_settings(uae_prefs* prefs, const game_options& game_detail, const bool a600_available, const bool use_aga)
void set_compatibility_settings(uae_prefs* prefs, const game_hardware_options& game_detail, const bool a600_available, const bool use_aga)
{
std::string line_string;
// CPU 68020/040 or no A600 ROM available
@ -835,17 +829,170 @@ void set_compatibility_settings(uae_prefs* prefs, const game_options& game_detai
// Screen settings, only if allowed to override the defaults from amiberry.conf
if (amiberry_options.allow_display_settings_from_xml)
{
parse_gfx_settings(prefs, game_detail);
set_gfx_settings(prefs, game_detail);
}
}
game_options parse_settings_from_xml(uae_prefs* prefs, const char* filepath)
void parse_slave_custom_fields(whdload_slave& slave, const std::string& custom)
{
game_options game_detail{};
std::istringstream stream(custom);
std::string line;
while (std::getline(stream, line)) {
if (line.find("C1") != std::string::npos || line.find("C2") != std::string::npos ||
line.find("C3") != std::string::npos || line.find("C4") != std::string::npos ||
line.find("C5") != std::string::npos) {
std::istringstream lineStream(line);
std::string segment;
std::vector<std::string> seglist;
while (std::getline(lineStream, segment, ':')) {
segment.erase(std::remove(segment.begin(), segment.end(), '\t'), segment.end());
seglist.push_back(segment);
}
// Process seglist as needed
if (seglist[0] == "C1")
{
if (seglist[1] == "B")
{
slave.custom1.type = bool_type;
slave.custom1.caption = seglist[2];
slave.custom1.value = 0;
}
else if (seglist[1] == "X")
{
slave.custom1.type = bit_type;
slave.custom1.value = 0;
slave.custom1.label_bit_pairs.insert(slave.custom1.label_bit_pairs.end(), { seglist[2], stoi(seglist[3]) });
}
else if (seglist[1] == "L")
{
slave.custom1.type = list_type;
slave.custom1.caption = seglist[2];
slave.custom1.value = 0;
std::string token;
std::istringstream token_stream(seglist[3]);
while (std::getline(token_stream, token, ',')) {
slave.custom1.labels.push_back(token);
}
}
}
else if (seglist[0] == "C2")
{
if (seglist[1] == "B")
{
slave.custom2.type = bool_type;
slave.custom2.caption = seglist[2];
slave.custom2.value = 0;
}
else if (seglist[1] == "X")
{
slave.custom2.type = bit_type;
slave.custom2.value = 0;
slave.custom2.label_bit_pairs.insert(slave.custom2.label_bit_pairs.end(), { seglist[2], stoi(seglist[3]) });
}
else if (seglist[1] == "L")
{
slave.custom2.type = list_type;
slave.custom2.caption = seglist[2];
slave.custom2.value = 0;
std::string token;
std::istringstream token_stream(seglist[3]);
while (std::getline(token_stream, token, ',')) {
slave.custom2.labels.push_back(token);
}
}
}
else if (seglist[0] == "C3")
{
if (seglist[1] == "B")
{
slave.custom3.type = bool_type;
slave.custom3.caption = seglist[2];
slave.custom3.value = 0;
}
else if (seglist[1] == "X")
{
slave.custom3.type = bit_type;
slave.custom3.value = 0;
slave.custom3.label_bit_pairs.insert(slave.custom3.label_bit_pairs.end(), { seglist[2], stoi(seglist[3]) });
}
else if (seglist[1] == "L")
{
slave.custom3.type = list_type;
slave.custom3.caption = seglist[2];
slave.custom3.value = 0;
std::string token;
std::istringstream token_stream(seglist[3]);
while (std::getline(token_stream, token, ',')) {
slave.custom3.labels.push_back(token);
}
}
}
else if (seglist[0] == "C4")
{
if (seglist[1] == "B")
{
slave.custom4.type = bool_type;
slave.custom4.caption = seglist[2];
slave.custom4.value = 0;
}
else if (seglist[1] == "X")
{
slave.custom4.type = bit_type;
slave.custom4.value = 0;
slave.custom4.label_bit_pairs.insert(slave.custom4.label_bit_pairs.end(), { seglist[2], stoi(seglist[3]) });
}
else if (seglist[1] == "L")
{
slave.custom4.type = list_type;
slave.custom4.caption = seglist[2];
slave.custom4.value = 0;
std::string token;
std::istringstream token_stream(seglist[3]);
while (std::getline(token_stream, token, ',')) {
slave.custom4.labels.push_back(token);
}
}
}
else if (seglist[0] == "C5")
{
if (seglist[1] == "B")
{
slave.custom5.type = bool_type;
slave.custom5.caption = seglist[2];
slave.custom5.value = 0;
}
else if (seglist[1] == "X")
{
slave.custom5.type = bit_type;
slave.custom5.value = 0;
slave.custom5.label_bit_pairs.insert(slave.custom5.label_bit_pairs.end(), { seglist[2], stoi(seglist[3]) });
}
else if (seglist[1] == "L")
{
slave.custom5.type = list_type;
slave.custom5.caption = seglist[2];
slave.custom5.value = 0;
std::string token;
std::istringstream token_stream(seglist[3]);
while (std::getline(token_stream, token, ',')) {
slave.custom5.labels.push_back(token);
}
}
}
}
}
}
game_hardware_options parse_settings_from_xml(uae_prefs* prefs, const char* filepath)
{
game_hardware_options game_detail{};
tinyxml2::XMLDocument doc;
auto error = false;
write_log("WHDBooter - Loading whdload_db.xml\n");
write_log("WHDBooter - Searching whdload_db.xml for %s\n", game_name);
write_log(_T("WHDBooter - Searching whdload_db.xml for %s\n"), whdload_prefs.filename.c_str());
auto* f = fopen(whd_config, _T("rb"));
if (f)
@ -875,85 +1022,117 @@ game_options parse_settings_from_xml(uae_prefs* prefs, const char* filepath)
// then fall back to sha1 if a user has renamed the file!
//
int found = 0;
if (game_node->Attribute("filename", game_name))
{
found = 1;
}
if (game_node->Attribute("sha1", sha1.c_str()))
if (game_node->Attribute("filename", whdload_prefs.filename.c_str()) ||
game_node->Attribute("sha1", sha1.c_str()))
{
found = 1;
}
if (found)
{
// now get the <hardware> and <custom_controls> items
// Name
auto xml_element = game_node->FirstChildElement("name");
if (xml_element)
{
whdload_prefs.game_name.assign(xml_element->GetText());
}
// Sub Path
xml_element = game_node->FirstChildElement("subpath");
if (xml_element)
{
whdload_prefs.sub_path.assign(xml_element->GetText());
}
// Variant UUID
xml_element = game_node->FirstChildElement("variant_uuid");
if (xml_element)
{
whdload_prefs.variant_uuid.assign(xml_element->GetText());
}
// Slave count
xml_element = game_node->FirstChildElement("slave_count");
if (xml_element)
{
whdload_prefs.slave_count = xml_element->IntText(0);
}
// Default slave
xml_element = game_node->FirstChildElement("slave_default");
if (xml_element)
{
whdload_prefs.slave_default.assign(xml_element->GetText());
write_log("WHDBooter - Selected Slave: %s \n", whdload_prefs.slave_default.c_str());
}
// Slave_libraries
xml_element = game_node->FirstChildElement("slave_libraries");
if (xml_element->GetText() != nullptr)
{
if (strcmpi(xml_element->GetText(), "true") == 0)
whdload_prefs.slave_libraries = true;
}
// Get slaves and settings
xml_element = game_node->FirstChildElement("slave");
whdload_prefs.slaves.clear();
for (int i = 0; i < whdload_prefs.slave_count && xml_element; ++i)
{
whdload_slave slave;
const char* slave_text = nullptr;
slave_text = xml_element->FirstChildElement("filename")->GetText();
if (slave_text)
slave.filename.assign(slave_text);
slave_text = xml_element->FirstChildElement("datapath")->GetText();
if (slave_text)
slave.data_path.assign(slave_text);
auto customElement = xml_element->FirstChildElement("custom");
if (customElement && ((slave_text = customElement->GetText())))
{
auto custom = std::string(slave_text);
parse_slave_custom_fields(slave, custom);
}
whdload_prefs.slaves.emplace_back(slave);
// Set the default slave as the selected one
if (slave.filename == whdload_prefs.slave_default)
whdload_prefs.selected_slave = slave;
xml_element = xml_element->NextSiblingElement("slave");
}
// get hardware
const auto* temp_node = game_node->FirstChildElement("hardware");
if (temp_node)
xml_element = game_node->FirstChildElement("hardware");
if (xml_element)
{
const auto* hardware = temp_node->GetText();
if (hardware)
std::string hardware;
hardware.assign(xml_element->GetText());
if (!hardware.empty())
{
game_detail = get_game_settings(hardware);
write_log("WHDBooter - Game H/W Settings: \n%s\n", hardware);
game_detail = get_game_hardware_settings(hardware);
write_log("WHDBooter - Game H/W Settings: \n%s\n", hardware.c_str());
}
}
// get custom controls
temp_node = game_node->FirstChildElement("custom_controls");
if (temp_node)
xml_element = game_node->FirstChildElement("custom_controls");
if (xml_element)
{
const auto* custom_settings = temp_node->GetText();
if (custom_settings)
std::string custom_settings;
custom_settings.assign(xml_element->GetText());
if (!custom_settings.empty())
{
write_log("WHDBooter - Game Custom Settings: \n%s\n", custom_settings);
parse_custom_settings(prefs, custom_settings);
write_log("WHDBooter - Game Custom Settings: \n%s\n", custom_settings.c_str());
}
}
if (strlen(selected_slave) == 0)
{
temp_node = game_node->FirstChildElement("slave_default");
// use a selected slave if we have one
if (strlen(prefs->whdbootprefs.slave) != 0)
{
_tcscpy(selected_slave, prefs->whdbootprefs.slave);
write_log("WHDBooter - Config Selected Slave: %s \n", selected_slave);
}
// otherwise use the XML default
else if (temp_node->GetText() != nullptr)
{
_stprintf(selected_slave, "%s", temp_node->GetText());
write_log("WHDBooter - Default Slave: %s\n", selected_slave);
}
temp_node = game_node->FirstChildElement("subpath");
if (temp_node->GetText() != nullptr)
{
_stprintf(sub_path, "%s", temp_node->GetText());
write_log("WHDBooter - SubPath: %s\n", sub_path);
}
}
// get slave_libraries
temp_node = game_node->FirstChildElement("slave_libraries");
if (temp_node->GetText() != nullptr)
{
if (strcmpi(temp_node->GetText(), "true") == 0)
use_slave_libs = true;
write_log("WHDBooter - Libraries: %s\n", sub_path);
}
// get data path
temp_node = game_node->FirstChildElement("slave")->FirstChildElement("datapath");
if (temp_node && temp_node->GetText() != nullptr)
{
_stprintf(data_path, "%s", temp_node->GetText());
write_log("WHDBooter - Data Path: %s\n", data_path);
}
break;
}
game_node = game_node->NextSiblingElement();
@ -962,12 +1141,12 @@ game_options parse_settings_from_xml(uae_prefs* prefs, const char* filepath)
return game_detail;
}
void create_startup_sequence(uae_prefs* prefs)
void create_startup_sequence()
{
std::ostringstream whd_bootscript;
whd_bootscript << "FAILAT 999\n";
if (use_slave_libs)
if (whdload_prefs.slave_libraries)
{
whd_bootscript << "DH3:C/Assign LIBS: DH3:LIBS/ ADD\n";
}
@ -976,74 +1155,57 @@ void create_startup_sequence(uae_prefs* prefs)
whd_bootscript << "DH3:C/Assign C: DH3:C/ ADD\n";
whd_bootscript << "ENDIF\n";
whd_bootscript << "CD \"Games:" << sub_path << "\"\n";
whd_bootscript << "WHDLoad SLAVE=\"Games:" << sub_path << "/" << selected_slave << "\"";
whd_bootscript << "CD \"Games:" << whdload_prefs.sub_path << "\"\n";
whd_bootscript << "WHDLoad SLAVE=\"Games:" << whdload_prefs.sub_path << "/" << whdload_prefs.selected_slave.filename << "\"";
// Write Cache
if (prefs->whdbootprefs.writecache)
whd_bootscript << " PRELOAD NOREQ";
if (!whdload_prefs.write_cache)
{
whd_bootscript << " PRELOAD NOREQ";
}
else
{
whd_bootscript << " PRELOAD NOREQ NOWRITECACHE";
whd_bootscript << " NOWRITECACHE";
}
// CUSTOM options
if (prefs->whdbootprefs.custom1 > 0)
{
whd_bootscript << " CUSTOM1=" << prefs->whdbootprefs.custom1;
for (int i = 1; i <= 5; ++i) {
auto& custom = whdload_prefs.selected_slave.get_custom(i);
if (custom.type != none && custom.value != 0) {
whd_bootscript << " CUSTOM" << i << "=" << custom.value;
}
}
if (prefs->whdbootprefs.custom2 > 0)
if (!whdload_prefs.custom.empty())
{
whd_bootscript << " CUSTOM2=" << prefs->whdbootprefs.custom2;
}
if (prefs->whdbootprefs.custom3 > 0)
{
whd_bootscript << " CUSTOM3=" << prefs->whdbootprefs.custom3;
}
if (prefs->whdbootprefs.custom4 > 0)
{
whd_bootscript << " CUSTOM4=" << prefs->whdbootprefs.custom4;
}
if (prefs->whdbootprefs.custom5 > 0)
{
whd_bootscript << " CUSTOM5=" << prefs->whdbootprefs.custom5;
}
if (strlen(prefs->whdbootprefs.custom) != 0)
{
whd_bootscript << " CUSTOM=\"" << prefs->whdbootprefs.custom << "\"";
whd_bootscript << " CUSTOM=\"" << whdload_prefs.custom << "\"";
}
// BUTTONWAIT
if (prefs->whdbootprefs.buttonwait)
if (whdload_prefs.button_wait)
{
whd_bootscript << " BUTTONWAIT";
}
// SPLASH
if (!prefs->whdbootprefs.showsplash)
if (!whdload_prefs.show_splash)
{
whd_bootscript << " SPLASHDELAY=0";
}
// CONFIGDELAY
if (prefs->whdbootprefs.configdelay != 0)
if (whdload_prefs.config_delay != 0)
{
whd_bootscript << " CONFIGDELAY=" << prefs->whdbootprefs.configdelay;
whd_bootscript << " CONFIGDELAY=" << whdload_prefs.config_delay;
}
// SPECIAL SAVE PATH
whd_bootscript << " SAVEPATH=Saves:Savegames/ SAVEDIR=\"" << sub_path << "\"";
whd_bootscript << " SAVEPATH=Saves:Savegames/ SAVEDIR=\"" << whdload_prefs.sub_path << "\"";
// DATA PATH
if (data_path[0])
whd_bootscript << "DATA=\"" << data_path << "\"";
if (!whdload_prefs.selected_slave.data_path.empty())
whd_bootscript << " DATA=\"" << whdload_prefs.selected_slave.data_path << "\"";
whd_bootscript << '\n';
// Launches utility program to quit the emulator (via a UAE trap in RTAREA)
if (prefs->whdbootprefs.quit_on_exit)
if (whdload_prefs.quit_on_exit)
{
whd_bootscript << "DH0:C/AmiQuit\n";
}
@ -1066,28 +1228,28 @@ bool is_a600_available(uae_prefs* prefs)
return rom_test == 1;
}
void set_booter_drives(uae_prefs* prefs, char* filepath)
void set_booter_drives(uae_prefs* prefs, const char* filepath)
{
TCHAR tmp[MAX_DPATH];
if (strlen(selected_slave) != 0) // new booter solution
if (!whdload_prefs.selected_slave.filename.empty()) // new booter solution
{
_sntprintf(boot_path, MAX_DPATH, "/tmp/amiberry/");
_stprintf(tmp, _T("filesystem2=rw,DH0:DH0:%s,10"), boot_path);
_sntprintf(tmp, MAX_DPATH, _T("filesystem2=rw,DH0:DH0:%s,10"), boot_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
_stprintf(tmp, _T("uaehf0=dir,rw,DH0:DH0::%s,10"), boot_path);
_sntprintf(tmp, MAX_DPATH, _T("uaehf0=dir,rw,DH0:DH0::%s,10"), boot_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
_sntprintf(boot_path, MAX_DPATH, "%sboot-data.zip", whdbooter_path.c_str());
if (!my_existsfile2(boot_path))
_sntprintf(boot_path, MAX_DPATH, "%sboot-data/", whdbooter_path.c_str());
_stprintf(tmp, _T("filesystem2=rw,DH3:DH3:%s,-10"), boot_path);
_sntprintf(tmp, MAX_DPATH, _T("filesystem2=rw,DH3:DH3:%s,-10"), boot_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
_stprintf(tmp, _T("uaehf0=dir,rw,DH3:DH3::%s,-10"), boot_path);
_sntprintf(tmp, MAX_DPATH, _T("uaehf0=dir,rw,DH3:DH3::%s,-10"), boot_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
}
else // revert to original booter is no slave was set
@ -1096,18 +1258,18 @@ void set_booter_drives(uae_prefs* prefs, char* filepath)
if (!my_existsfile2(boot_path))
_sntprintf(boot_path, MAX_DPATH, "%sboot-data/", whdbooter_path.c_str());
_stprintf(tmp, _T("filesystem2=rw,DH0:DH0:%s,10"), boot_path);
_sntprintf(tmp, MAX_DPATH, _T("filesystem2=rw,DH0:DH0:%s,10"), boot_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
_stprintf(tmp, _T("uaehf0=dir,rw,DH0:DH0::%s,10"), boot_path);
_sntprintf(tmp, MAX_DPATH, _T("uaehf0=dir,rw,DH0:DH0::%s,10"), boot_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
}
//set the Second (game data) drive
_stprintf(tmp, "filesystem2=rw,DH1:Games:\"%s\",0", filepath);
_sntprintf(tmp, MAX_DPATH, "filesystem2=rw,DH1:Games:\"%s\",0", filepath);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
_stprintf(tmp, "uaehf1=dir,rw,DH1:Games:\"%s\",0", filepath);
_sntprintf(tmp, MAX_DPATH, "uaehf1=dir,rw,DH1:Games:\"%s\",0", filepath);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
//set the third (save data) drive
@ -1115,18 +1277,17 @@ void set_booter_drives(uae_prefs* prefs, char* filepath)
if (my_existsdir(save_path))
{
_stprintf(tmp, "filesystem2=rw,DH2:Saves:%s,0", save_path);
_sntprintf(tmp, MAX_DPATH, "filesystem2=rw,DH2:Saves:%s,0", save_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
_stprintf(tmp, "uaehf2=dir,rw,DH2:Saves:%s,0", save_path);
_sntprintf(tmp, MAX_DPATH, "uaehf2=dir,rw,DH2:Saves:%s,0", save_path);
cfgfile_parse_line(prefs, parse_text(tmp), 0);
}
}
void whdload_auto_prefs(uae_prefs* prefs, char* filepath)
void whdload_auto_prefs(uae_prefs* prefs, const char* filepath)
{
write_log("WHDBooter Launched\n");
_tcscpy(selected_slave, "");
get_configuration_path(conf_path, MAX_DPATH);
whdbooter_path = get_whdbootpath();
@ -1147,11 +1308,12 @@ void whdload_auto_prefs(uae_prefs* prefs, char* filepath)
// REMOVE THE FILE PATH AND EXTENSION
const auto* filename = my_getfilepart(filepath);
get_game_name(filepath);
const std::string filename_no_extension = get_game_filename(filepath);
whdload_prefs.filename = filename_no_extension;
// LOAD GAME SPECIFICS FOR EXISTING .UAE - USE SHA1 IF AVAILABLE
// CONFIG LOAD IF .UAE IS IN CONFIG PATH
build_uae_config_filename();
build_uae_config_filename(whdload_prefs.filename);
// If we have a config file, we will use it.
// We will need it for the WHDLoad options too.
@ -1177,7 +1339,7 @@ void whdload_auto_prefs(uae_prefs* prefs, char* filepath)
// LOAD GAME SPECIFICS
_sntprintf(whd_path, MAX_DPATH, "%sgame-data/", whdbooter_path.c_str());
game_options game_detail;
game_hardware_options game_detail;
_tcscpy(whd_config, whd_path);
_tcscat(whd_config, "whdload_db.xml");
@ -1192,9 +1354,9 @@ void whdload_auto_prefs(uae_prefs* prefs, char* filepath)
}
// If we have a slave, create a startup-sequence
if (strlen(selected_slave) != 0)
if (!whdload_prefs.selected_slave.filename.empty())
{
create_startup_sequence(prefs);
create_startup_sequence();
}
// now we should have a startup-sequence file (if we don't, we are going to use the original booter)

View File

@ -29,8 +29,8 @@ struct fs_stat {
};
extern bool fs_path_exists(const std::string& s);
extern std::string iso_8859_1_to_utf8(std::string& str);
extern std::string iso_8859_1_to_utf8(const std::string& str);
extern void utf8_to_latin1_string(std::string& input, std::string& output);
extern std::string prefix_with_application_directory_path(std::string currentpath);
extern std::string prefix_with_data_path(std::string filename);
extern std::string prefix_with_whdboot_path(std::string filename);
extern std::string prefix_with_whdboot_path(std::string filename);

View File

@ -40,13 +40,14 @@ static NavigationMap navMap[] =
{"Miscellaneous", "chkMouseUntrap", "chkMouseUntrap", "Disk swapper", "Priority"},
{"Priority", "cboInactiveRunAtPrio", "cboActiveRunAtPrio", "Miscellaneous", "Savestates" },
{"Savestates", "State0", "State0", "Priority", "Virtual Keyboard"},
{"Virtual Keyboard", "chkVkEnabled", "chkVkEnabled", "Savestates", "Quit"},
{"Shutdown", "Start", "Quit", "Virtual Keyboard", "About"},
{"Quit", "Shutdown", "Restart", "Virtual Keyboard", "About"},
{"Restart", "Quit", "Help", "Virtual Keyboard", "About"},
{"Help", "Restart", "Reset", "Virtual Keyboard", "About"},
{"Reset", "Help", "Start", "Virtual Keyboard", "About"},
{"Start", "Reset", "Shutdown", "Virtual Keyboard", "About"},
{"Virtual Keyboard", "chkVkEnabled", "chkVkEnabled", "Savestates", "WHDLoad"},
{"WHDLoad", "", "", "Virtual Keyboard", "Quit"},
{"Shutdown", "Start", "Quit", "WHDLoad", "About"},
{"Quit", "Shutdown", "Restart", "WHDLoad", "About"},
{"Restart", "Quit", "Help", "WHDLoad", "About"},
{"Help", "Restart", "Reset", "WHDLoad", "About"},
{"Reset", "Help", "Start", "WHDLoad", "About"},
{"Start", "Reset", "Shutdown", "WHDLoad", "About"},
// PanelPaths
{"cmdSystemROMs", "Paths", "Paths", "cmdRescanROMs", "cmdConfigPath"},

View File

@ -334,7 +334,7 @@ void InitPanelCustom(const config_category& category)
posY = txtPortInput->getY() + txtPortInput->getHeight() + DISTANCE_NEXT_Y;
// Column 1
const auto column1 = 5;
constexpr auto column1 = 5;
for (i = 0; i < SDL_CONTROLLER_BUTTON_MAX / 2; i++)
{
category.panel->add(lblCustomButtonAction[i], column1, posY);

View File

@ -150,7 +150,7 @@ public:
if (strncmp(changed_prefs.dfxlist[i], tmp.c_str(), MAX_DPATH) != 0)
{
strncpy(changed_prefs.dfxlist[i], tmp.c_str(), MAX_DPATH);
AddFileToDiskList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUDiskList, tmp);
}
}
cmdDiskSwapperListAdd[i]->requestFocus();
@ -212,7 +212,7 @@ public:
{
disk_swap(row, 1);
AddFileToDiskList(changed_prefs.dfxlist[row], 1);
add_file_to_mru_list(lstMRUDiskList, std::string(changed_prefs.dfxlist[row]));
RefreshPanelDiskSwapper();
RefreshPanelFloppy();
RefreshPanelQuickstart();

View File

@ -388,8 +388,8 @@ void InitPanelDisplay(const config_category& category)
lblHOffset = new gcn::Label("H. Offset:");
lblHOffset->setAlignment(gcn::Graphics::LEFT);
sldHOffset = new gcn::Slider(-60, 60);
sldHOffset->setSize(135, SLIDER_HEIGHT);
sldHOffset = new gcn::Slider(-80, 80);
sldHOffset->setSize(200, SLIDER_HEIGHT);
sldHOffset->setBaseColor(gui_baseCol);
sldHOffset->setMarkerLength(20);
sldHOffset->setStepLength(1);
@ -400,8 +400,8 @@ void InitPanelDisplay(const config_category& category)
lblVOffset = new gcn::Label("V. Offset:");
lblVOffset->setAlignment(gcn::Graphics::LEFT);
sldVOffset = new gcn::Slider(-60, 60);
sldVOffset->setSize(135, SLIDER_HEIGHT);
sldVOffset = new gcn::Slider(-80, 80);
sldVOffset->setSize(200, SLIDER_HEIGHT);
sldVOffset->setBaseColor(gui_baseCol);
sldVOffset->setMarkerLength(20);
sldVOffset->setStepLength(1);
@ -700,9 +700,8 @@ void RefreshPanelDisplay()
sldBrightness->setValue(changed_prefs.gfx_luminance);
lblBrightnessValue->setCaption(std::to_string(changed_prefs.gfx_luminance));
lblBrightnessValue->adjustSize();
int i;
int i;
for (i = 0; i < AMIGAWIDTH_COUNT; ++i)
{
if (changed_prefs.gfx_monitor[0].gfx_size_win.width == amigawidth_values[i])

View File

@ -211,7 +211,7 @@ public:
{
strncpy(changed_prefs.floppyslots[i].df, tmp.c_str(), MAX_DPATH);
disk_insert(i, tmp.c_str());
AddFileToDiskList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUDiskList, tmp);
RefreshDiskListModel();
current_dir = extract_path(tmp);
@ -334,7 +334,7 @@ public:
diskname[31] = '\0';
disk_creatediskfile(&changed_prefs, tmp.c_str(), 0, DRV_35_DD, -1, diskname, false, false, nullptr);
DISK_history_add (tmp.c_str(), -1, HISTORY_FLOPPY, 0);
AddFileToDiskList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUDiskList, tmp);
RefreshDiskListModel();
current_dir = extract_path(tmp);
}
@ -351,7 +351,7 @@ public:
diskname[31] = '\0';
disk_creatediskfile(&changed_prefs, tmp.c_str(), 0, DRV_35_HD, -1, diskname, false, false, nullptr);
DISK_history_add (tmp.c_str(), -1, HISTORY_FLOPPY, 0);
AddFileToDiskList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUDiskList, tmp);
RefreshDiskListModel();
current_dir = extract_path(tmp);
}

View File

@ -252,7 +252,7 @@ public:
strncpy(changed_prefs.cdslots[0].name, tmp.c_str(), sizeof changed_prefs.cdslots[0].name);
changed_prefs.cdslots[0].inuse = true;
changed_prefs.cdslots[0].type = SCSI_UNIT_DEFAULT;
AddFileToCDList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUCDList, tmp);
current_dir = extract_path(tmp);
RefreshCDListModel();

View File

@ -136,7 +136,6 @@ static amigamodels amodels[] = {
static const int numModels = 10;
static int numModelConfigs = 0;
static bool bIgnoreListChange = true;
static char whdload_file[MAX_DPATH];
static gcn::StringListModel amigaModelList;
static gcn::StringListModel amigaConfigList;
@ -144,6 +143,8 @@ static gcn::StringListModel diskfileList;
static gcn::StringListModel cdfileList;
static gcn::StringListModel whdloadFileList;
std::string whdload_filename;
static void AdjustDropDownControls();
static void CountModelConfigs()
@ -317,7 +318,7 @@ public:
strncpy(changed_prefs.cdslots[0].name, tmp.c_str(), MAX_DPATH);
changed_prefs.cdslots[0].inuse = true;
changed_prefs.cdslots[0].type = SCSI_UNIT_DEFAULT;
AddFileToCDList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUCDList, tmp);
current_dir = extract_path(tmp);
RefreshCDListModel();
@ -394,21 +395,21 @@ public:
if (idx < 0)
{
strncpy(whdload_file, "", MAX_DPATH);
whdload_filename = "";
}
else
{
const auto element = get_full_path_from_disk_list(whdloadFileList.getElementAt(idx));
if (element != whdload_file)
if (element != whdload_filename)
{
strncpy(whdload_file, element.c_str(), MAX_DPATH);
whdload_filename.assign(element);
lstMRUWhdloadList.erase(lstMRUWhdloadList.begin() + idx);
lstMRUWhdloadList.insert(lstMRUWhdloadList.begin(), whdload_file);
lstMRUWhdloadList.insert(lstMRUWhdloadList.begin(), whdload_filename);
bIgnoreListChange = true;
cboWhdload->setSelected(0);
bIgnoreListChange = false;
}
whdload_auto_prefs(&changed_prefs, whdload_file);
whdload_auto_prefs(&changed_prefs, whdload_filename.c_str());
}
refresh_all_panels();
}
@ -428,23 +429,22 @@ public:
//---------------------------------------
// Eject WHDLoad file
//---------------------------------------
strncpy(whdload_file, "", MAX_DPATH);
AdjustPrefs();
whdload_filename = "";
}
else if (actionEvent.getSource() == cmdWhdloadSelect)
{
std::string tmp;
if (strlen(whdload_file) > 0)
tmp = std::string(whdload_file);
if (!whdload_filename.empty())
tmp = whdload_filename;
else
tmp = get_whdload_arch_path();
tmp = SelectFile("Select WHDLoad LHA file", tmp, whdload_filter);
{
strncpy(whdload_file, tmp.c_str(), MAX_DPATH);
AddFileToWHDLoadList(whdload_file, 1);
whdload_filename = tmp;
add_file_to_mru_list(lstMRUWhdloadList, whdload_filename);
RefreshWhdListModel();
whdload_auto_prefs(&changed_prefs, whdload_file);
whdload_auto_prefs(&changed_prefs, whdload_filename.c_str());
AdjustDropDownControls();
}
@ -642,7 +642,7 @@ public:
{
strncpy(changed_prefs.floppyslots[i].df, tmp.c_str(), MAX_DPATH);
disk_insert(i, tmp.c_str());
AddFileToDiskList(tmp.c_str(), 1);
add_file_to_mru_list(lstMRUDiskList, tmp);
current_dir = extract_path(tmp);
RefreshDiskListModel();
current_dir = extract_path(tmp);
@ -1027,11 +1027,11 @@ static void AdjustDropDownControls()
}
cboWhdload->clearSelected();
if (strlen(whdload_file) > 0)
if (!whdload_filename.empty())
{
for (auto i = 0; i < static_cast<int>(lstMRUWhdloadList.size()); ++i)
{
if (lstMRUWhdloadList[i].c_str() != whdload_file)
if (lstMRUWhdloadList[i] == whdload_filename)
{
cboWhdload->setSelected(i);
break;
@ -1048,6 +1048,7 @@ void RefreshPanelQuickstart()
chkNTSC->setSelected(changed_prefs.ntscmode);
RefreshWhdListModel();
AdjustDropDownControls();
changed_prefs.nr_floppies = 0;

View File

@ -0,0 +1,455 @@
#include <cstring>
#include <cstdio>
#include <vector>
#include <guisan.hpp>
#include <guisan/sdl.hpp>
#include "SelectorEntry.hpp"
#include "sysdeps.h"
#include "options.h"
#include "gui_handling.h"
#include "StringListModel.h"
static gcn::Label* lblWhdload;
static gcn::DropDown* cboWhdload;
static gcn::Button* cmdWhdloadEject;
static gcn::Button* cmdWhdloadSelect;
// WHDLoad game options
static gcn::Label* lblGameName;
static gcn::TextField* txtGameName;
static gcn::Label* lblVariantUuid;
static gcn::TextField* txtVariantUuid;
static gcn::Label* lblSlaveDefault;
static gcn::TextField* txtSlaveDefault;
static gcn::CheckBox* chkSlaveLibraries;
static gcn::Label* lblSlaves;
static gcn::DropDown* cboSlaves;
// WHDLoad global options
static gcn::Window* grpWHDLoadGlobal;
static gcn::Label* lblCustomText;
static gcn::TextField* txtCustomText;
static gcn::CheckBox* chkButtonWait;
static gcn::CheckBox* chkShowSplash;
static gcn::Label* lblConfigDelay;
static gcn::TextField* txtConfigDelay;
static gcn::CheckBox* chkWriteCache;
static gcn::CheckBox* chkQuitOnExit;
// Selected Slave options
static gcn::Label* lblSlaveDataPath;
static gcn::TextField* txtSlaveDataPath;
// Selected Slave Custom options
static gcn::Button* cmdCustomFields;
static gcn::StringListModel whdloadFileList;
static gcn::StringListModel slaves_list;
static bool bIgnoreListChange = true;
static void RefreshWhdListModel()
{
whdloadFileList.clear();
for (const auto& i : lstMRUWhdloadList)
{
const std::string full_path = i;
const std::string filename = full_path.substr(full_path.find_last_of("/\\") + 1);
whdloadFileList.add(std::string(filename).append(" { ").append(full_path).append(" }"));
}
}
static void AdjustDropDownControls()
{
bIgnoreListChange = true;
cboWhdload->clearSelected();
if (!whdload_filename.empty())
{
for (auto i = 0; i < static_cast<int>(lstMRUWhdloadList.size()); ++i)
{
if (lstMRUWhdloadList[i] == whdload_filename)
{
cboWhdload->setSelected(i);
break;
}
}
}
bIgnoreListChange = false;
}
class WHDLoadActionListener : public gcn::ActionListener
{
public:
void action(const gcn::ActionEvent& actionEvent) override
{
const auto source = actionEvent.getSource();
if (source == cboWhdload)
{
//---------------------------------------
// WHDLoad file from list selected
//---------------------------------------
if (!bIgnoreListChange)
{
const auto idx = cboWhdload->getSelected();
if (idx < 0)
{
whdload_filename = "";
}
else
{
const auto element = get_full_path_from_disk_list(whdloadFileList.getElementAt(idx));
if (element != whdload_filename)
{
whdload_filename.assign(element);
lstMRUWhdloadList.erase(lstMRUWhdloadList.begin() + idx);
lstMRUWhdloadList.insert(lstMRUWhdloadList.begin(), whdload_filename);
bIgnoreListChange = true;
cboWhdload->setSelected(0);
bIgnoreListChange = false;
}
whdload_auto_prefs(&changed_prefs, whdload_filename.c_str());
}
refresh_all_panels();
}
}
else if (source == cmdWhdloadEject)
{
//---------------------------------------
// Eject WHDLoad file
//---------------------------------------
whdload_filename = "";
refresh_all_panels();
}
else if (source == cmdWhdloadSelect)
{
std::string tmp;
if (!whdload_filename.empty())
tmp = whdload_filename;
else
tmp = get_whdload_arch_path();
tmp = SelectFile("Select WHDLoad LHA file", tmp, whdload_filter);
{
whdload_filename.assign(tmp);
add_file_to_mru_list(lstMRUWhdloadList, whdload_filename);
RefreshWhdListModel();
whdload_auto_prefs(&changed_prefs, whdload_filename.c_str());
AdjustDropDownControls();
}
cmdWhdloadSelect->requestFocus();
refresh_all_panels();
}
else if (source == cboSlaves)
{
if (cboSlaves->getSelected() >= 0)
{
whdload_prefs.selected_slave = whdload_prefs.slaves[cboSlaves->getSelected()];
txtSlaveDataPath->setText(whdload_prefs.selected_slave.data_path.empty() ? "" : whdload_prefs.selected_slave.data_path);
create_startup_sequence();
}
}
else if (source == cmdCustomFields)
{
ShowCustomFields();
}
else if (source == chkButtonWait)
{
whdload_prefs.button_wait = chkButtonWait->isSelected();
create_startup_sequence();
}
else if (source == chkShowSplash)
{
whdload_prefs.show_splash = chkShowSplash->isSelected();
create_startup_sequence();
}
else if (source == chkWriteCache)
{
whdload_prefs.write_cache = chkWriteCache->isSelected();
create_startup_sequence();
}
else if (source == chkQuitOnExit)
{
whdload_prefs.quit_on_exit = chkQuitOnExit->isSelected();
create_startup_sequence();
}
}
};
static WHDLoadActionListener* whdloadActionListener;
void InitPanelWHDLoad(const struct config_category& category)
{
slaves_list.clear();
constexpr int textfield_width = 350;
whdloadActionListener = new WHDLoadActionListener();
lblWhdload = new gcn::Label("WHDLoad auto-config:");
cboWhdload = new gcn::DropDown(&whdloadFileList);
cboWhdload->setSize(category.panel->getWidth() - 2 * DISTANCE_BORDER, cboWhdload->getHeight());
cboWhdload->setBaseColor(gui_baseCol);
cboWhdload->setBackgroundColor(colTextboxBackground);
cboWhdload->setId("cboWhdload");
cboWhdload->addActionListener(whdloadActionListener);
cmdWhdloadEject = new gcn::Button("Eject");
cmdWhdloadEject->setSize(SMALL_BUTTON_WIDTH * 2, SMALL_BUTTON_HEIGHT);
cmdWhdloadEject->setBaseColor(gui_baseCol);
cmdWhdloadEject->setId("cmdWhdloadEject");
cmdWhdloadEject->addActionListener(whdloadActionListener);
cmdWhdloadSelect = new gcn::Button("Select file");
cmdWhdloadSelect->setSize(BUTTON_WIDTH + 10, SMALL_BUTTON_HEIGHT);
cmdWhdloadSelect->setBaseColor(gui_baseCol);
cmdWhdloadSelect->setId("cmdWhdloadSelect");
cmdWhdloadSelect->addActionListener(whdloadActionListener);
// WHDLoad options
lblGameName = new gcn::Label("Game Name:");
txtGameName = new gcn::TextField();
txtGameName->setSize(textfield_width, TEXTFIELD_HEIGHT);
txtGameName->setBackgroundColor(colTextboxBackground);
lblVariantUuid = new gcn::Label("UUID:");
txtVariantUuid = new gcn::TextField();
txtVariantUuid->setSize(textfield_width, TEXTFIELD_HEIGHT);
txtVariantUuid->setBackgroundColor(colTextboxBackground);
lblSlaveDefault = new gcn::Label("Slave Default:");
txtSlaveDefault = new gcn::TextField();
txtSlaveDefault->setSize(textfield_width, TEXTFIELD_HEIGHT);
txtSlaveDefault->setBackgroundColor(colTextboxBackground);
chkSlaveLibraries = new gcn::CheckBox("Slave Libraries");
lblSlaves = new gcn::Label("Slaves:");
cboSlaves = new gcn::DropDown(&slaves_list);
cboSlaves->setSize(textfield_width, cboSlaves->getHeight());
cboSlaves->setBaseColor(gui_baseCol);
cboSlaves->setBackgroundColor(colTextboxBackground);
cboSlaves->addActionListener(whdloadActionListener);
lblSlaveDataPath = new gcn::Label("Slave Data path:");
txtSlaveDataPath = new gcn::TextField();
txtSlaveDataPath->setSize(textfield_width, TEXTFIELD_HEIGHT);
txtSlaveDataPath->setBackgroundColor(colTextboxBackground);
cmdCustomFields = new gcn::Button("Custom Fields");
cmdCustomFields->setSize(BUTTON_WIDTH * 2, BUTTON_HEIGHT);
cmdCustomFields->setBaseColor(gui_baseCol);
cmdCustomFields->setId("cmdCustomFields");
cmdCustomFields->addActionListener(whdloadActionListener);
lblCustomText = new gcn::Label("Custom:");
txtCustomText = new gcn::TextField();
txtCustomText->setSize(textfield_width, TEXTFIELD_HEIGHT);
txtCustomText->setBackgroundColor(colTextboxBackground);
chkButtonWait = new gcn::CheckBox("Button Wait");
chkButtonWait->addActionListener(whdloadActionListener);
chkShowSplash = new gcn::CheckBox("Show Splash");
chkShowSplash->addActionListener(whdloadActionListener);
lblConfigDelay = new gcn::Label("Config Delay:");
txtConfigDelay = new gcn::TextField();
txtConfigDelay->setSize(textfield_width, TEXTFIELD_HEIGHT);
txtConfigDelay->setBackgroundColor(colTextboxBackground);
chkWriteCache = new gcn::CheckBox("Write Cache");
chkWriteCache->addActionListener(whdloadActionListener);
chkQuitOnExit = new gcn::CheckBox("Quit on Exit");
chkQuitOnExit->addActionListener(whdloadActionListener);
constexpr int pos_x1 = DISTANCE_BORDER;
const int pos_x2 = chkSlaveLibraries->getWidth() + 8;
int pos_y = DISTANCE_BORDER;
category.panel->add(lblWhdload, DISTANCE_BORDER, pos_y);
category.panel->add(cmdWhdloadEject, lblWhdload->getX() + lblWhdload->getWidth() + DISTANCE_NEXT_X * 16, pos_y);
category.panel->add(cmdWhdloadSelect, cmdWhdloadEject->getX() + cmdWhdloadEject->getWidth() + DISTANCE_NEXT_X, pos_y);
pos_y += cmdWhdloadSelect->getHeight() + 8;
category.panel->add(cboWhdload, DISTANCE_BORDER, pos_y);
pos_y += cboWhdload->getHeight() + DISTANCE_NEXT_Y;
category.panel->add(lblGameName, pos_x1, pos_y);
category.panel->add(txtGameName, pos_x2, pos_y);
pos_y += lblGameName->getHeight() + 8;
category.panel->add(lblVariantUuid, pos_x1, pos_y);
category.panel->add(txtVariantUuid, pos_x2, pos_y);
pos_y += lblVariantUuid->getHeight() + 8;
category.panel->add(lblSlaveDefault, pos_x1, pos_y);
category.panel->add(txtSlaveDefault, pos_x2, pos_y);
pos_y += lblSlaveDefault->getHeight() + 8;
category.panel->add(chkSlaveLibraries, pos_x1, pos_y);
pos_y += chkSlaveLibraries->getHeight() + 8;
category.panel->add(lblSlaves, pos_x1, pos_y);
category.panel->add(cboSlaves, pos_x2, pos_y);
pos_y += lblSlaves->getHeight() + 8;
category.panel->add(lblSlaveDataPath, pos_x1, pos_y);
category.panel->add(txtSlaveDataPath, pos_x2, pos_y);
pos_y += lblSlaveDataPath->getHeight() + 8;
category.panel->add(lblCustomText, pos_x1, pos_y);
category.panel->add(txtCustomText, pos_x2, pos_y);
pos_y += lblCustomText->getHeight() + DISTANCE_NEXT_Y;
category.panel->add(cmdCustomFields, pos_x2, pos_y);
grpWHDLoadGlobal = new gcn::Window("Global options");
grpWHDLoadGlobal->setMovable(false);
grpWHDLoadGlobal->setTitleBarHeight(TITLEBAR_HEIGHT);
grpWHDLoadGlobal->setBaseColor(gui_baseCol);
pos_y = 10;
grpWHDLoadGlobal->add(chkButtonWait, pos_x1, pos_y);
pos_y += chkButtonWait->getHeight() + 8;
grpWHDLoadGlobal->add(chkShowSplash, pos_x1, pos_y);
pos_y += chkShowSplash->getHeight() + 8;
grpWHDLoadGlobal->add(lblConfigDelay, pos_x1, pos_y);
grpWHDLoadGlobal->add(txtConfigDelay, pos_x2, pos_y);
pos_y += txtConfigDelay->getHeight() + 8;
grpWHDLoadGlobal->add(chkWriteCache, pos_x1, pos_y);
pos_y += chkWriteCache->getHeight() + 8;
grpWHDLoadGlobal->add(chkQuitOnExit, pos_x1, pos_y);
grpWHDLoadGlobal->setSize(category.panel->getWidth() - DISTANCE_BORDER * 2,
chkQuitOnExit->getY() + chkQuitOnExit->getHeight() + DISTANCE_NEXT_Y + TITLEBAR_HEIGHT);
grpWHDLoadGlobal->setPosition(pos_x1, category.panel->getHeight() - grpWHDLoadGlobal->getHeight() - DISTANCE_NEXT_Y);
category.panel->add(grpWHDLoadGlobal);
bIgnoreListChange = false;
RefreshPanelWHDLoad();
}
void ExitPanelWHDLoad()
{
delete lblWhdload;
delete cboWhdload;
delete cmdWhdloadEject;
delete cmdWhdloadSelect;
// WHDLoad options
delete lblGameName;
delete txtGameName;
delete lblVariantUuid;
delete txtVariantUuid;
delete lblSlaveDefault;
delete txtSlaveDefault;
delete chkSlaveLibraries;
delete lblSlaves;
delete cboSlaves;
delete lblCustomText;
delete txtCustomText;
delete chkButtonWait;
delete chkShowSplash;
delete lblConfigDelay;
delete txtConfigDelay;
delete chkWriteCache;
delete chkQuitOnExit;
// Selected Slave options
delete lblSlaveDataPath;
delete txtSlaveDataPath;
// Selected Slave Custom options
delete cmdCustomFields;
delete grpWHDLoadGlobal;
delete whdloadActionListener;
}
void update_slaves_list(const std::vector<whdload_slave>& slaves)
{
slaves_list.clear();
for (auto& slave : slaves)
{
slaves_list.add(slave.filename);
}
}
void update_selected_slave(const whdload_slave& selected_slave)
{
int selected = 0;
for (int i = 0; i < slaves_list.getNumberOfElements(); i++)
{
if (slaves_list.getElementAt(i) == selected_slave.filename)
{
selected = i;
break;
}
}
cboSlaves->setSelected(selected);
}
void RefreshPanelWHDLoad()
{
RefreshWhdListModel();
AdjustDropDownControls();
cmdCustomFields->setEnabled(!whdload_filename.empty());
if (whdload_filename.empty())
{
clear_whdload_prefs();
slaves_list.clear();
}
else
{
update_slaves_list(whdload_prefs.slaves);
update_selected_slave(whdload_prefs.selected_slave);
txtSlaveDataPath->setText(whdload_prefs.selected_slave.data_path.empty() ? "" : whdload_prefs.selected_slave.data_path);
}
txtGameName->setText(whdload_prefs.game_name.empty() ? "" : whdload_prefs.game_name);
txtVariantUuid->setText(whdload_prefs.variant_uuid.empty() ? "" : whdload_prefs.variant_uuid);
txtSlaveDefault->setText(whdload_prefs.slave_default.empty() ? "" : whdload_prefs.slave_default);
chkSlaveLibraries->setSelected(whdload_prefs.slave_libraries);
txtCustomText->setText(whdload_prefs.custom.empty() ? "" : whdload_prefs.custom);
// These are global
chkButtonWait->setSelected(whdload_prefs.button_wait);
chkShowSplash->setSelected(whdload_prefs.show_splash);
txtConfigDelay->setText(std::to_string(whdload_prefs.config_delay));
chkWriteCache->setSelected(whdload_prefs.write_cache);
chkQuitOnExit->setSelected(whdload_prefs.quit_on_exit);
}
bool HelpPanelWHDLoad(std::vector<std::string>& helptext)
{
helptext.clear();
//TODO
return true;
}

View File

@ -44,40 +44,41 @@ static gcn::TextField* txtFilename;
class SelectFileListModel : public gcn::ListModel
{
std::vector<std::string> dirs{};
std::vector<std::string> files{};
std::vector<std::string> dirs;
std::vector<std::string> files;
public:
explicit SelectFileListModel(const char* path)
explicit SelectFileListModel(const std::string& path)
{
changeDir(path);
}
int getNumberOfElements() override
{
return static_cast<int>(dirs.size() + files.size());
return dirs.size() + files.size();
}
void add(const std::string& elem) override
{
dirs.emplace_back(elem);
dirs.push_back(elem);
}
void clear() override
{
dirs.clear();
files.clear();
}
std::string getElementAt(const int i) override
std::string getElementAt(int i) override
{
if (i >= static_cast<int>(dirs.size() + files.size()) || i < 0)
if (i < 0 || i >= getNumberOfElements())
return "---";
if (i < static_cast<int>(dirs.size()))
if (i < dirs.size())
return dirs[i];
return files[i - dirs.size()];
}
void changeDir(const char* path)
void changeDir(const std::string& path)
{
read_directory(path, &dirs, &files);
if (dirs.empty())
@ -85,7 +86,7 @@ public:
FilterFiles(&files, filefilter);
}
[[nodiscard]] bool isDir(const unsigned int i) const
bool isDir(unsigned int i) const
{
return (i < dirs.size());
}

View File

@ -49,13 +49,11 @@ public:
dialogFinished = true;
}
};
static FolderRequesterButtonActionListener* folderButtonActionListener;
class SelectDirListModel : public gcn::ListModel
{
std::vector<std::string> dirs{};
std::vector<std::string> dirs;
public:
SelectDirListModel(const std::string& path)
@ -70,7 +68,7 @@ public:
void add(const std::string& elem) override
{
dirs.emplace_back(elem);
dirs.push_back(elem);
}
void clear() override
@ -78,9 +76,9 @@ public:
dirs.clear();
}
std::string getElementAt(const int i) override
std::string getElementAt(int i) override
{
if (i >= static_cast<int>(dirs.size()) || i < 0)
if (i < 0 || i >= getNumberOfElements())
return "---";
return dirs[i];
}

View File

@ -1,5 +1,4 @@
#ifndef GCN_SELECTORENTRY_HPP
#define GCN_SELECTORENTRY_HPP
#pragma once
#include <guisan/basiccontainer.hpp>
#include <guisan/platform.hpp>
@ -31,7 +30,7 @@ namespace gcn
void setInactiveColor(const Color& color);
void setActiveColor(const Color& color);
void setActive(bool active);
[[nodiscard]] bool getActive() const;
bool getActive() const;
void widgetResized(const Event& event) override;
@ -48,4 +47,3 @@ namespace gcn
};
}
#endif // end GCN_SELECTORENTRY_HPP

View File

@ -0,0 +1,434 @@
#include <cstdio>
#include <cstring>
#include <guisan.hpp>
#include <guisan/sdl.hpp>
#include "SelectorEntry.hpp"
#include "StringListModel.h"
#include "sysdeps.h"
#include "config.h"
#include "gui_handling.h"
#include "options.h"
#include "amiberry_input.h"
enum
{
DIALOG_WIDTH = 600,
DIALOG_HEIGHT = 600
};
static bool dialog_finished = false;
static int custom_number[5];
static gcn::StringListModel custom_list[5];
static gcn::Window* wndShowCustomFields;
static gcn::Button* cmdOK;
struct custom_widget {
std::vector<gcn::Label*> lbl;
std::vector<gcn::CheckBox*> boolean;
std::vector<gcn::CheckBox*> bit;
std::vector<gcn::DropDown*> list;
};
custom_widget customWidget1;
custom_widget customWidget2;
custom_widget customWidget3;
custom_widget customWidget4;
custom_widget customWidget5;
constexpr std::array<custom_widget*, 5> customWidgets = { &customWidget1, &customWidget2, &customWidget3, &customWidget4, &customWidget5 };
constexpr std::array<whdload_custom*, 5> customFields = { &whdload_prefs.selected_slave.custom1, &whdload_prefs.selected_slave.custom2, &whdload_prefs.selected_slave.custom3, &whdload_prefs.selected_slave.custom4, &whdload_prefs.selected_slave.custom5 };
static int set_bit(const int value, const int bit_position) {
return value | (1 << bit_position);
}
static int clear_bit(const int value, const int bit_position) {
return value & ~(1 << bit_position);
}
static bool is_bit_set(const int num, const int bit) {
return (num & (1 << bit)) != 0;
}
class ShowCustomFieldsActionListener : public gcn::ActionListener
{
public:
void action(const gcn::ActionEvent& actionEvent) override
{
const auto source = actionEvent.getSource();
if (source == cmdOK)
dialog_finished = true;
else
{
for (int j = 0; j < 5; ++j)
{
for (int i = 0; i < custom_number[j]; i++)
{
if (!customWidgets[j]->list.empty() && customFields[j]->type == list_type)
{
if (source == customWidgets[j]->list[i])
{
customFields[j]->value = customWidgets[j]->list[i]->getSelected();
write_log("Custom field %d value updated to: %d\n", i, customFields[j]->value);
}
}
else if (!customWidgets[j]->boolean.empty() && customFields[j]->type == bool_type)
{
if (source == customWidgets[j]->boolean[i])
{
customFields[j]->value = customWidgets[j]->boolean[i]->isSelected();
write_log("Custom field %d value updated to: %d\n", i, customFields[j]->value);
}
}
else if (!customWidgets[j]->bit.empty() && customFields[j]->type == bit_type)
{
if (source == customWidgets[j]->bit[i])
{
customFields[j]->value = customWidgets[j]->bit[i]->isSelected()
? set_bit(customFields[j]->value, customFields[j]->label_bit_pairs[i].second)
: clear_bit(customFields[j]->value, customFields[j]->label_bit_pairs[i].second);
write_log("Custom field %d value updated to: %d\n", i, customFields[j]->value);
}
}
}
}
}
}
};
static ShowCustomFieldsActionListener* showCustomFieldsActionListener;
void create_custom_field(custom_widget& widget, const int number, const std::string& caption, const whdload_custom& custom_field, int& pos_y, const int custom_list_index)
{
constexpr int textfield_width = 350;
constexpr int pos_x1 = DISTANCE_BORDER;
constexpr int pos_x2 = 150;
for (int i = 0; i < number; i++) {
std::string id;
auto label = new gcn::Label(caption + ":");
label->setPosition(pos_x1, pos_y);
widget.lbl.emplace_back(label);
wndShowCustomFields->add(label);
switch (custom_field.type) {
case bit_type: {
auto checkbox = new gcn::CheckBox(custom_field.label_bit_pairs[i].first);
checkbox->setSelected(is_bit_set(custom_field.value, custom_field.label_bit_pairs[i].second));
checkbox->addActionListener(showCustomFieldsActionListener);
checkbox->setId("chkCustomFieldBit_" + std::to_string(i));
checkbox->setPosition(pos_x2, pos_y);
widget.bit.emplace_back(checkbox);
wndShowCustomFields->add(checkbox);
pos_y += checkbox->getHeight() + 8;
break;
}
case bool_type: {
auto checkbox = new gcn::CheckBox(custom_field.caption);
checkbox->setSelected(custom_field.value);
checkbox->addActionListener(showCustomFieldsActionListener);
checkbox->setId("chkCustomFieldBool_" + std::to_string(i));
checkbox->setPosition(pos_x2, pos_y);
widget.boolean.emplace_back(checkbox);
wndShowCustomFields->add(checkbox);
pos_y += checkbox->getHeight() + 8;
break;
}
case list_type: {
label->setCaption(custom_field.caption);
label->adjustSize();
for (const auto& item : custom_field.labels)
{
custom_list[custom_list_index].add(item);
}
auto dropdown = new gcn::DropDown(&custom_list[custom_list_index]);
dropdown->setId("cboCustomFieldList_" + std::to_string(i));
dropdown->setSize(textfield_width, dropdown->getHeight());
dropdown->setBaseColor(gui_baseCol);
dropdown->setBackgroundColor(colTextboxBackground);
dropdown->addActionListener(showCustomFieldsActionListener);
dropdown->setPosition(pos_x2, pos_y);
widget.list.emplace_back(dropdown);
wndShowCustomFields->add(dropdown);
pos_y += dropdown->getHeight() + 8;
break;
}
default:
pos_y += label->getHeight() + 8;
break;
}
}
}
void delete_custom_field(custom_widget& customField) {
for (const auto& lbl : customField.lbl) {
delete lbl;
}
customField.lbl.clear();
for (const auto& chk : customField.boolean) {
delete chk;
}
customField.boolean.clear();
for (const auto& chk : customField.bit) {
delete chk;
}
customField.bit.clear();
for (const auto& cbo : customField.list) {
delete cbo;
}
customField.list.clear();
}
static void InitShowCustomFields()
{
wndShowCustomFields = new gcn::Window("Custom Fields");
wndShowCustomFields->setSize(DIALOG_WIDTH, DIALOG_HEIGHT);
wndShowCustomFields->setPosition((GUI_WIDTH - DIALOG_WIDTH) / 2, (GUI_HEIGHT - DIALOG_HEIGHT) / 2);
wndShowCustomFields->setBaseColor(gui_baseCol);
wndShowCustomFields->setTitleBarHeight(TITLEBAR_HEIGHT);
showCustomFieldsActionListener = new ShowCustomFieldsActionListener();
int pos_y = DISTANCE_BORDER;
for (auto& i : custom_list)
{
i.clear();
}
for (int i = 0; i < 5; ++i) {
create_custom_field(*customWidgets[i], custom_number[i], "Custom" + std::to_string(i + 1), *customFields[i], pos_y, i);
}
cmdOK = new gcn::Button("Ok");
cmdOK->setSize(BUTTON_WIDTH, BUTTON_HEIGHT);
cmdOK->setPosition(DIALOG_WIDTH - DISTANCE_BORDER - BUTTON_WIDTH,
DIALOG_HEIGHT - 2 * DISTANCE_BORDER - BUTTON_HEIGHT - 10);
cmdOK->setBaseColor(gui_baseCol);
cmdOK->addActionListener(showCustomFieldsActionListener);
wndShowCustomFields->add(cmdOK);
gui_top->add(wndShowCustomFields);
wndShowCustomFields->requestModalFocus();
focus_bug_workaround(wndShowCustomFields);
cmdOK->requestFocus();
}
static void ExitShowCustomFields()
{
wndShowCustomFields->releaseModalFocus();
gui_top->remove(wndShowCustomFields);
delete cmdOK;
delete_custom_field(customWidget1);
delete_custom_field(customWidget2);
delete_custom_field(customWidget3);
delete_custom_field(customWidget4);
delete_custom_field(customWidget5);
delete showCustomFieldsActionListener;
delete wndShowCustomFields;
}
static void ShowCustomFieldsLoop()
{
const AmigaMonitor* mon = &AMonitors[0];
auto got_event = 0;
SDL_Event event;
SDL_Event touch_event;
didata* did = &di_joystick[0];
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_KEYDOWN:
got_event = 1;
switch (event.key.keysym.sym)
{
case VK_ESCAPE:
dialog_finished = true;
break;
case VK_Blue:
case VK_Green:
case SDLK_RETURN:
event.key.keysym.sym = SDLK_RETURN;
gui_input->pushInput(event); // Fire key down
event.type = SDL_KEYUP; // and the key up
break;
default:
break;
}
break;
case SDL_JOYBUTTONDOWN:
if (gui_joystick)
{
got_event = 1;
if (SDL_JoystickGetButton(gui_joystick, did->mapping.button[SDL_CONTROLLER_BUTTON_A]) ||
SDL_JoystickGetButton(gui_joystick, did->mapping.button[SDL_CONTROLLER_BUTTON_B]))
{
PushFakeKey(SDLK_RETURN);
break;
}
if (SDL_JoystickGetButton(gui_joystick, did->mapping.button[SDL_CONTROLLER_BUTTON_X]) ||
SDL_JoystickGetButton(gui_joystick, did->mapping.button[SDL_CONTROLLER_BUTTON_Y]) ||
SDL_JoystickGetButton(gui_joystick, did->mapping.button[SDL_CONTROLLER_BUTTON_START]))
{
dialog_finished = true;
break;
}
}
break;
case SDL_FINGERDOWN:
got_event = 1;
memcpy(&touch_event, &event, sizeof event);
touch_event.type = SDL_MOUSEBUTTONDOWN;
touch_event.button.which = 0;
touch_event.button.button = SDL_BUTTON_LEFT;
touch_event.button.state = SDL_PRESSED;
touch_event.button.x = gui_graphics->getTarget()->w * static_cast<int>(event.tfinger.x);
touch_event.button.y = gui_graphics->getTarget()->h * static_cast<int>(event.tfinger.y);
gui_input->pushInput(touch_event);
break;
case SDL_FINGERUP:
got_event = 1;
memcpy(&touch_event, &event, sizeof event);
touch_event.type = SDL_MOUSEBUTTONUP;
touch_event.button.which = 0;
touch_event.button.button = SDL_BUTTON_LEFT;
touch_event.button.state = SDL_RELEASED;
touch_event.button.x = gui_graphics->getTarget()->w * static_cast<int>(event.tfinger.x);
touch_event.button.y = gui_graphics->getTarget()->h * static_cast<int>(event.tfinger.y);
gui_input->pushInput(touch_event);
break;
case SDL_FINGERMOTION:
got_event = 1;
memcpy(&touch_event, &event, sizeof event);
touch_event.type = SDL_MOUSEMOTION;
touch_event.motion.which = 0;
touch_event.motion.state = 0;
touch_event.motion.x = gui_graphics->getTarget()->w * static_cast<int>(event.tfinger.x);
touch_event.motion.y = gui_graphics->getTarget()->h * static_cast<int>(event.tfinger.y);
gui_input->pushInput(touch_event);
break;
case SDL_MOUSEWHEEL:
got_event = 1;
if (event.wheel.y > 0)
{
for (auto z = 0; z < event.wheel.y; ++z)
{
PushFakeKey(SDLK_UP);
}
}
else if (event.wheel.y < 0)
{
for (auto z = 0; z > event.wheel.y; --z)
{
PushFakeKey(SDLK_DOWN);
}
}
break;
case SDL_KEYUP:
case SDL_JOYBUTTONUP:
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
case SDL_MOUSEMOTION:
case SDL_RENDER_TARGETS_RESET:
case SDL_RENDER_DEVICE_RESET:
case SDL_WINDOWEVENT:
case SDL_DISPLAYEVENT:
case SDL_SYSWMEVENT:
got_event = 1;
break;
default:
break;
}
//-------------------------------------------------
// Send event to guisan-controls
//-------------------------------------------------
gui_input->pushInput(event);
}
if (got_event)
{
// Now we let the Gui object perform its logic.
uae_gui->logic();
SDL_RenderClear(mon->sdl_renderer);
// Now we let the Gui object draw itself.
uae_gui->draw();
// Finally we update the screen.
update_gui_screen();
}
}
void ShowCustomFields()
{
const AmigaMonitor* mon = &AMonitors[0];
dialog_finished = false;
// Initialize custom_number to 1
std::fill(std::begin(custom_number), std::end(custom_number), 1);
// If the custom field is a bit field, set the custom_number to the number of pairs
if (whdload_prefs.selected_slave.custom1.type == bit_type)
custom_number[0] = static_cast<int>(whdload_prefs.selected_slave.custom1.label_bit_pairs.size());
if (whdload_prefs.selected_slave.custom2.type == bit_type)
custom_number[1] = static_cast<int>(whdload_prefs.selected_slave.custom2.label_bit_pairs.size());
if (whdload_prefs.selected_slave.custom3.type == bit_type)
custom_number[2] = static_cast<int>(whdload_prefs.selected_slave.custom3.label_bit_pairs.size());
if (whdload_prefs.selected_slave.custom4.type == bit_type)
custom_number[3] = static_cast<int>(whdload_prefs.selected_slave.custom4.label_bit_pairs.size());
if (whdload_prefs.selected_slave.custom5.type == bit_type)
custom_number[4] = static_cast<int>(whdload_prefs.selected_slave.custom5.label_bit_pairs.size());
InitShowCustomFields();
wndShowCustomFields->setCaption("Custom Fields");
cmdOK->setCaption("Ok");
// Prepare the screen once
uae_gui->logic();
SDL_RenderClear(mon->sdl_renderer);
uae_gui->draw();
update_gui_screen();
while (!dialog_finished)
{
const auto start = SDL_GetPerformanceCounter();
ShowCustomFieldsLoop();
cap_fps(start);
}
create_startup_sequence();
ExitShowCustomFields();
}

View File

@ -322,6 +322,11 @@ void ExitPanelVirtualKeyboard();
void RefreshPanelVirtualKeyboard();
bool HelpPanelVirtualKeyboard(std::vector<std::string>& helptext);
void InitPanelWHDLoad(const struct config_category& category);
void ExitPanelWHDLoad();
void RefreshPanelWHDLoad();
bool HelpPanelWHDLoad(std::vector<std::string>& helptext);
void refresh_all_panels();
void register_refresh_func(void (*func)());
void focus_bug_workaround(gcn::Window* wnd);
@ -340,9 +345,10 @@ bool EditFilesysHardDrive(int unit_no);
bool CreateFilesysHardfile();
void ShowHelp(const char* title, const std::vector<std::string>& text);
void ShowDiskInfo(const char* title, const std::vector<std::string>& text);
void ShowCustomFields();
std::string show_controller_map(int device, bool map_touchpad);
extern void read_directory(std::string path, vector<string>* dirs, vector<string>* files);
extern void read_directory(const std::string& path, vector<string>* dirs, vector<string>* files);
extern void FilterFiles(vector<string>* files, const char* filter[]);
enum
@ -371,6 +377,7 @@ STATIC_INLINE bool is_hdf_rdb()
return current_hfdlg.ci.sectors == 0 && current_hfdlg.ci.surfaces == 0 && current_hfdlg.ci.reserved == 0;
}
extern std::string whdload_filename;
extern std::string screenshot_filename;
extern int currentStateNum;
extern int delay_savestate_frame;
@ -390,6 +397,8 @@ extern int todfxtype(int num, int dfx, int* subtype);
extern void DisplayDiskInfo(int num);
extern std::string get_full_path_from_disk_list(std::string element);
extern amiberry_hotkey get_hotkey_from_config(std::string config_option);
extern void save_mapping_to_file(std::string mapping);
extern void save_mapping_to_file(const std::string& mapping);
extern void clear_whdload_prefs();
extern void create_startup_sequence();
#endif // GUI_HANDLING_H

View File

@ -2,6 +2,7 @@
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <guisan.hpp>
#include <SDL_image.h>
@ -91,6 +92,7 @@ ConfigCategory categories[] = {
{"Virtual Keyboard", "keyboard.png", nullptr, nullptr, InitPanelVirtualKeyboard,
ExitPanelVirtualKeyboard, RefreshPanelVirtualKeyboard, HelpPanelVirtualKeyboard
},
{"WHDLoad", "drive.ico", nullptr, nullptr, InitPanelWHDLoad, ExitPanelWHDLoad, RefreshPanelWHDLoad, HelpPanelWHDLoad},
{nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}
};
@ -248,28 +250,23 @@ static void show_help_requested()
void cap_fps(Uint64 start)
{
int refresh_rate;
const auto end = SDL_GetPerformanceCounter();
const auto elapsed_ms = static_cast<float>(end - start) / static_cast<float>(SDL_GetPerformanceFrequency()) * 1000.0f;
#ifdef USE_DISPMANX
refresh_rate = 60;
#else
refresh_rate = sdl_mode.refresh_rate;
if (refresh_rate < 50) refresh_rate = 50;
if (refresh_rate > 60) refresh_rate = 60;
const int refresh_rate = std::clamp(sdl_mode.refresh_rate, 50, 60);
#endif
float d = 0.0f;
if (refresh_rate == 60)
d = floor(16.666f - elapsed_ms);
else
d = floor(20.000f - elapsed_ms);
const float frame_time = 1000.0f / refresh_rate;
const float delay_time = frame_time - elapsed_ms;
if( d > 0.0f ) SDL_Delay( Uint32(d) );
if (delay_time > 0.0f)
SDL_Delay(static_cast<Uint32>(delay_time));
}
void update_gui_screen()
{
AmigaMonitor* mon = &AMonitors[0];
const AmigaMonitor* mon = &AMonitors[0];
#ifdef USE_DISPMANX
vc_dispmanx_resource_write_data(gui_resource, rgb_mode, gui_screen->pitch, gui_screen->pixels, &blit_rect);
updateHandle = vc_dispmanx_update_start(0);
@ -557,7 +554,7 @@ void amiberry_gui_halt()
void check_input()
{
AmigaMonitor* mon = &AMonitors[0];
const AmigaMonitor* mon = &AMonitors[0];
auto got_event = 0;
didata* did = &di_joystick[0];
@ -928,11 +925,7 @@ void check_input()
//-------------------------------------------------
// Send event to gui-controls
//-------------------------------------------------
#ifdef ANDROID
androidsdl_event(gui_event, gui_input);
#else
gui_input->pushInput(gui_event);
#endif
}
if (got_event)
@ -950,7 +943,7 @@ void check_input()
void amiberry_gui_run()
{
AmigaMonitor* mon = &AMonitors[0];
const AmigaMonitor* mon = &AMonitors[0];
if (amiberry_options.gui_joystick_control)
{
@ -1010,72 +1003,84 @@ class MainButtonActionListener : public gcn::ActionListener
public:
void action(const gcn::ActionEvent& actionEvent) override
{
if (actionEvent.getSource() == cmdShutdown)
const auto source = actionEvent.getSource();
if (source == cmdShutdown)
{
// ------------------------------------------------
// Shutdown the host (power off)
// ------------------------------------------------
uae_quit();
gui_running = false;
host_poweroff = true;
shutdown_host();
}
else if (source == cmdQuit)
{
quit_program();
}
else if (source == cmdReset)
{
reset_amiga();
}
else if (source == cmdRestart)
{
restart_emulator();
}
else if (source == cmdStart)
{
start_emulation();
}
else if (source == cmdHelp)
{
show_help();
}
}
private:
static void shutdown_host()
{
uae_quit();
gui_running = false;
host_poweroff = true;
}
if (actionEvent.getSource() == cmdQuit)
static void quit_program()
{
uae_quit();
gui_running = false;
}
static void reset_amiga()
{
uae_reset(1, 1);
gui_running = false;
}
static void restart_emulator()
{
char tmp[MAX_DPATH];
get_configuration_path(tmp, sizeof tmp);
if (strlen(last_loaded_config) > 0)
strncat(tmp, last_loaded_config, MAX_DPATH - 1);
else
{
strncat(tmp, OPTIONSFILENAME, MAX_DPATH - 1);
strncat(tmp, ".uae", MAX_DPATH - 10);
}
uae_restart(&changed_prefs, -1, tmp);
gui_running = false;
}
static void start_emulation()
{
if (emulating && cmdStart->isEnabled())
{
//-------------------------------------------------
// Quit entire program via click on Quit-button
//-------------------------------------------------
uae_quit();
gui_running = false;
}
else if (actionEvent.getSource() == cmdReset)
else
{
//-------------------------------------------------
// Reset Amiga via click on Reset-button
//-------------------------------------------------
uae_reset(1, 1);
uae_reset(0, 1);
gui_running = false;
}
else if (actionEvent.getSource() == cmdRestart)
{
//-------------------------------------------------
// Restart emulator
//-------------------------------------------------
char tmp[MAX_DPATH];
get_configuration_path(tmp, sizeof tmp);
if (strlen(last_loaded_config) > 0)
strncat(tmp, last_loaded_config, MAX_DPATH - 1);
else
{
strncat(tmp, OPTIONSFILENAME, MAX_DPATH - 1);
strncat(tmp, ".uae", MAX_DPATH - 10);
}
uae_restart(&changed_prefs, -1, tmp);
gui_running = false;
}
else if (actionEvent.getSource() == cmdStart)
{
if (emulating && cmdStart->isEnabled())
{
//------------------------------------------------
// Continue emulation
//------------------------------------------------
gui_running = false;
}
else
{
//------------------------------------------------
// First start of emulator -> reset Amiga
//------------------------------------------------
uae_reset(0, 1);
gui_running = false;
}
}
else if (actionEvent.getSource() == cmdHelp)
{
show_help_requested();
cmdHelp->requestFocus();
}
}
static void show_help()
{
show_help_requested();
cmdHelp->requestFocus();
}
};

View File

@ -20,8 +20,8 @@
#define GETBDM(x) (((x) - (((x) / 10000) * 10000)) / 100)
#define GETBDD(x) ((x) % 100)
#define AMIBERRYVERSION _T("Amiberry v5.6.9 (2024-09-09)")
#define AMIBERRYDATE MAKEBD(2024, 3, 9)
#define AMIBERRYVERSION _T("Amiberry v5.6.9 (2024-03-17)")
#define AMIBERRYDATE MAKEBD(2024, 3, 17)
#define COPYRIGHT _T("Copyright (C) 2016-2024 Dimitris Panokostas")
#define IHF_WINDOWHIDDEN 6
@ -129,6 +129,7 @@ extern void get_rp9_path(char* out, int size);
extern std::string get_screenshot_path();
extern void extract_filename(const char* str, char* buffer);
extern std::string extract_filename(const std::string& path);
extern void extract_path(char* str, char* buffer);
extern std::string extract_path(const std::string& filename);
extern void remove_file_extension(char* filename);
@ -158,17 +159,13 @@ typedef struct
extern std::vector<AvailableROM*> lstAvailableROMs;
#define MAX_MRU_DISKLIST 40
#define MAX_MRU_LIST 40
extern std::vector<std::string> lstMRUDiskList;
extern void AddFileToDiskList(const char* file, int moveToTop);
#define MAX_MRU_CDLIST 10
extern std::vector<std::string> lstMRUCDList;
extern void AddFileToCDList(const char* file, int moveToTop);
#define MAX_MRU_WHDLOADLIST 10
extern std::vector<std::string> lstMRUWhdloadList;
extern void AddFileToWHDLoadList(const char* file, int moveToTop);
extern void add_file_to_mru_list(std::vector<std::string>& vec, const std::string& file);
int count_HDs(struct uae_prefs* p);
extern void gui_force_rtarea_hdchange(void);