1480 implement missing features in expansion gui panel (#1492)

* fixed vertical alignment of checkbox

* Fixed bug with string list model

* refactored functions in Expansion panel

Changed order of functions, to match WinUAE's mess closer

* Added Accelerator board RAM slider

* Fixed CPU board sub items dropdown list

* clear more lists when refreshing accelerator dropdowns

* Fixed StrngListModel clear

* Enable multiple RTG boards in cfgfile

* Added registry file, refactor things to use that for storing ROMs

Instead of storing the detected ROMs in the amiberry.conf file, we will switch to using the available functionality of registry -> ini file, that WinUAE already has.
This has become necessary, in order to use the same logic when storying the ROM entries (with their ID and type, not just the filename), which is used from the Expansions panel for custom board roms.

It also means changing the existing ROMs functionality to match, so it's likely some things will need fixing after this as well.

* Fixed rom scanning

* Create XDG dirs on startup, if they don't exist

This happened at least once in WSL2 + Debian, so let's make sure

* Fixed rom scanning again, ensure slash in path when needed
This commit is contained in:
Dimitris Panokostas 2024-10-27 17:17:29 +01:00 committed by GitHub
parent 99fc80b0fb
commit 9dc7dec4f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
16 changed files with 1778 additions and 645 deletions

View File

@ -225,6 +225,7 @@ set(SOURCE_FILES
src/osdep/ioport.cpp
src/osdep/sigsegv_handler.cpp
src/osdep/socket.cpp
src/osdep/registry.cpp
src/osdep/retroarch.cpp
src/osdep/vpar.cpp
src/pcem/386.cpp

View File

@ -94,7 +94,7 @@ namespace gcn
virtual std::string getElementAt(int i) = 0;
// Add a new element
virtual void add(std::string str) { }
virtual void add(const std::string& str) { }
// Clear all elements
virtual void clear_elements() { }

View File

@ -6629,7 +6629,6 @@ void cfgfile_compatibility_rtg(struct uae_prefs *p)
}
}
}
#ifndef AMIBERRY // Only 1 RTG board in Amiberry for now
int rtgs[MAX_RTG_BOARDS] = { 0 };
for (int i = 0; i < MAX_RTG_BOARDS; i++) {
if (p->rtgboards[i].rtgmem_size && !rtgs[i]) {
@ -6666,7 +6665,6 @@ void cfgfile_compatibility_rtg(struct uae_prefs *p)
}
}
}
#endif
}
void cfgfile_compatibility_romtype(struct uae_prefs *p)

View File

@ -82,6 +82,7 @@ struct bstring {
extern TCHAR *colormodes[];
extern int saveimageoriginalpath;
extern std::string get_ini_file_path();
extern void get_saveimage_path(char* out, int size, int dir);
extern std::string get_configuration_path();
extern void get_nvram_path(TCHAR* out, int size);

View File

@ -92,7 +92,7 @@ void ini_addnewstring(struct ini_data *ini, const TCHAR *section, const TCHAR *k
if (!il)
return;
il->section = my_strdup(section);
if (!_tcsicmp(section, _T("WinUAE")))
if (!_tcsicmp(section, _T("Amiberry")))
il->section_order = 1;
if (key == NULL) {
il->key = my_strdup(_T(""));

View File

@ -53,6 +53,7 @@
#ifdef FLOPPYBRIDGE
#include "floppybridge_lib.h"
#endif
#include "registry.h"
#include "threaddep/thread.h"
#include "uae/uae.h"
#include "sana2.h"
@ -93,7 +94,9 @@ int log_vsync, debug_vsync_min_delay, debug_vsync_forced_delay;
int uaelib_debug;
int pissoff_value = 15000 * CYCLE_UNIT;
static TCHAR* inipath = NULL;
extern FILE* debugfile;
static int forceroms;
SDL_Cursor* normalcursor;
int paraport_mask;
@ -312,6 +315,7 @@ std::string plugins_dir;
std::string video_dir;
std::string themes_path;
std::string amiberry_conf_file;
std::string amiberry_ini_file;
char last_loaded_config[MAX_DPATH] = {'\0'};
@ -1852,6 +1856,7 @@ void logging_init()
first++;
write_log("%s Logfile\n\n", get_version_string().c_str());
write_log("%s\n", get_sdl2_version_string().c_str());
regstatus();
}
}
@ -3041,6 +3046,11 @@ std::string get_screenshot_path()
return fix_trailing(screenshot_dir);
}
std::string get_ini_file_path()
{
return amiberry_ini_file;
}
void get_video_path(char* out, int size)
{
_tcsncpy(out, fix_trailing(video_dir).c_str(), size - 1);
@ -3446,18 +3456,6 @@ void save_amiberry_settings(void)
write_string_option("video_dir", video_dir);
write_string_option("themes_path", themes_path);
// The number of ROMs in the last scan
snprintf(buffer, MAX_DPATH, "ROMs=%zu\n", lstAvailableROMs.size());
fputs(buffer, f);
// The ROMs found in the last scan
for (auto& lstAvailableROM : lstAvailableROMs)
{
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)
snprintf(buffer, MAX_DPATH, "MRUDiskList=%zu\n", lstMRUDiskList.size());
fputs(buffer, f);
@ -3518,24 +3516,7 @@ static int parse_amiberry_settings_line(const char *path, char *linea)
if (!cfgfile_separate_linea(path, linea, option, value))
return 0;
if (cfgfile_string(option, value, "ROMName", romName, sizeof romName)
|| cfgfile_string(option, value, "ROMPath", romPath, sizeof romPath)
|| cfgfile_intval(option, value, "ROMType", &romType, 1))
{
if (strlen(romName) > 0 && strlen(romPath) > 0 && romType != -1)
{
auto* tmp = new AvailableROM();
tmp->Name.assign(romName);
tmp->Path.assign(romPath);
tmp->ROMType = romType;
lstAvailableROMs.emplace_back(tmp);
strncpy(romName, "", sizeof romName);
strncpy(romPath, "", sizeof romPath);
romType = -1;
ret = 1;
}
}
else if (cfgfile_string(option, value, "Diskfile", tmpFile, sizeof tmpFile))
if (cfgfile_string(option, value, "Diskfile", tmpFile, sizeof tmpFile))
{
auto* const f = fopen(tmpFile, "rbe");
if (f != nullptr)
@ -3831,7 +3812,7 @@ std::string get_home_directory()
return {tmp};
}
// The location of .uae configurations and the global amiberry.conf file
// The location of .uae configurations
std::string get_config_directory()
{
#ifdef __MACH__
@ -4064,17 +4045,32 @@ static void init_amiberry_dirs()
plugins_dir = get_plugins_directory();
std::string xdg_data_home = get_xdg_data_home();
if (!my_existsdir(xdg_data_home.c_str()))
{
// Create the XDG_DATA_HOME directory if it doesn't exist
const auto user_home_dir = getenv("HOME");
if (user_home_dir != nullptr)
{
std::string destination = std::string(user_home_dir) + "/.local";
my_mkdir(destination.c_str());
destination += "/share";
my_mkdir(destination.c_str());
}
}
xdg_data_home += "/" + amiberry_dir;
if (!my_existsdir(xdg_data_home.c_str()))
my_mkdir(xdg_data_home.c_str());
std::string xdg_config_home = get_xdg_config_home();
if (!my_existsdir(xdg_config_home.c_str()))
my_mkdir(xdg_config_home.c_str());
xdg_config_home += "/" + amiberry_dir;
if (!my_existsdir(xdg_config_home.c_str()))
my_mkdir(xdg_config_home.c_str());
// The amiberry.conf file is always in the XDG_CONFIG_HOME/amiberry directory
amiberry_conf_file = xdg_config_home + "/amiberry.conf";
amiberry_ini_file = xdg_config_home + "/amiberry.ini";
themes_path = xdg_config_home;
// These paths are relative to the XDG_DATA_HOME directory
@ -4151,6 +4147,84 @@ void load_amiberry_settings(void)
}
}
static void romlist_add2(const TCHAR* path, struct romdata* rd)
{
if (getregmode()) {
int ok = 0;
TCHAR tmp[MAX_DPATH];
if (path[0] == '/' || path[0] == '\\')
ok = 1;
if (_tcslen(path) > 1 && path[1] == ':')
ok = 1;
if (!ok) {
_tcscpy(tmp, get_rom_path().c_str());
_tcscat(tmp, path);
romlist_add(tmp, rd);
return;
}
}
romlist_add(path, rd);
}
void read_rom_list(bool initial)
{
TCHAR tmp2[1000];
int idx, idx2;
UAEREG* fkey;
TCHAR tmp[1000];
int size, size2, exists;
romlist_clear();
exists = regexiststree(NULL, _T("DetectedROMs"));
fkey = regcreatetree(NULL, _T("DetectedROMs"));
if (fkey == NULL)
return;
if (!exists || forceroms) {
//if (initial) {
// scaleresource_init(NULL, 0);
//}
load_keyring(NULL, NULL);
scan_roms(forceroms ? 0 : 1);
}
forceroms = 0;
idx = 0;
for (;;) {
size = sizeof(tmp) / sizeof(TCHAR);
size2 = sizeof(tmp2) / sizeof(TCHAR);
if (!regenumstr(fkey, idx, tmp, &size, tmp2, &size2))
break;
if (_tcslen(tmp) == 7 || _tcslen(tmp) == 13) {
int group = 0;
int subitem = 0;
idx2 = _tstol(tmp + 4);
if (_tcslen(tmp) == 13) {
group = _tstol(tmp + 8);
subitem = _tstol(tmp + 11);
}
if (idx2 >= 0 && _tcslen(tmp2) > 0) {
struct romdata* rd = getromdatabyidgroup(idx2, group, subitem);
if (rd) {
TCHAR* s = _tcschr(tmp2, '\"');
if (s && _tcslen(s) > 1) {
TCHAR* s2 = my_strdup(s + 1);
s = _tcschr(s2, '\"');
if (s)
*s = 0;
romlist_add2(s2, rd);
xfree(s2);
}
else {
romlist_add2(tmp2, rd);
}
}
}
}
idx++;
}
romlist_add(NULL, NULL);
regclosetree(fkey);
}
void target_getdate(int* y, int* m, int* d)
{
*y = GETBDY(AMIBERRYDATE);
@ -4287,6 +4361,23 @@ int main(int argc, char* argv[])
}
snprintf(savestate_fname, sizeof savestate_fname, "%s/default.ads", fix_trailing(savestate_dir).c_str());
reginitializeinit(&inipath);
if (getregmode() == NULL)
{
TCHAR* path;
std::string ini_file_path = get_ini_file_path();
_tcscpy(path, ini_file_path.c_str());
auto f = fopen(path, _T("r"));
if (!f)
f = fopen(path, _T("w"));
if (f) {
fclose(f);
reginitializeinit(&path);
}
xfree(path);
}
logging_init();
#if defined (CPU_arm)
memset(&action, 0, sizeof action);
@ -4321,8 +4412,6 @@ int main(int argc, char* argv[])
abort();
}
#endif
if (lstAvailableROMs.empty())
RescanROMs();
if (!init_mmtimer())
return 0;
@ -4339,6 +4428,9 @@ int main(int argc, char* argv[])
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, 0);
#endif
(void)atexit(SDL_Quit);
read_rom_list(true);
load_keyring(NULL, NULL);
write_log(_T("Enumerating display devices.. \n"));
enumeratedisplays();
write_log(_T("Sorting devices and modes...\n"));
@ -4432,7 +4524,6 @@ int main(int argc, char* argv[])
// Unsolved for OS X
#endif
ClearAvailableROMList();
romlist_clear();
free_keyring();
@ -4521,18 +4612,6 @@ bool is_mainthread()
return uae_thread_get_id(nullptr) == mainthreadid;
}
static struct netdriverdata *ndd[MAX_TOTAL_NET_DEVICES + 1];
static int net_enumerated;
struct netdriverdata **target_ethernet_enumerate(void)
{
if (net_enumerated)
return ndd;
ethernet_enumerate(ndd, 0);
net_enumerated = 1;
return ndd;
}
void clear_whdload_prefs()
{
whdload_prefs.filename.clear();

View File

@ -39,6 +39,7 @@
#include "fsdb.h"
#include "gayle.h"
#include "parser.h"
#include "registry.h"
#include "scsi.h"
#include "target.h"
@ -52,6 +53,7 @@
int emulating = 0;
bool config_loaded = false;
int gui_active;
int recursiveromscan = 2;
std::vector<std::string> serial_ports;
std::vector<std::string> midi_in_ports;
@ -91,7 +93,6 @@ struct gui_msg gui_msglist[] = {
};
std::vector<ConfigFileInfo*> ConfigFilesList;
std::vector<AvailableROM*> lstAvailableROMs;
std::vector<std::string> lstMRUDiskList;
std::vector<std::string> lstMRUCDList;
std::vector<std::string> lstMRUWhdloadList;
@ -117,33 +118,184 @@ void add_file_to_mru_list(std::vector<std::string>& vec, const std::string& file
vec.pop_back();
}
void ClearAvailableROMList()
struct romdataentry
{
for (const auto* rom : lstAvailableROMs)
{
delete rom;
TCHAR* name;
int priority;
};
void addromfiles(UAEREG* fkey, gcn::DropDown* d, const TCHAR* path, int type1, int type2)
{
int idx;
TCHAR tmp[MAX_DPATH];
TCHAR tmp2[MAX_DPATH];
TCHAR seltmp[MAX_DPATH];
struct romdata* rdx = NULL;
struct romdataentry* rde = xcalloc(struct romdataentry, MAX_ROMMGR_ROMS);
int ridx = 0;
if (path)
rdx = scan_single_rom(path);
idx = 0;
seltmp[0] = 0;
for (; fkey;) {
int size = sizeof(tmp) / sizeof(TCHAR);
int size2 = sizeof(tmp2) / sizeof(TCHAR);
if (!regenumstr(fkey, idx, tmp, &size, tmp2, &size2))
break;
if (_tcslen(tmp) == 7 || _tcslen(tmp) == 13) {
int group = 0;
int subitem = 0;
int idx2 = _tstol(tmp + 4);
if (_tcslen(tmp) == 13) {
group = _tstol(tmp + 8);
subitem = _tstol(tmp + 11);
}
if (idx2 >= 0) {
struct romdata* rd = getromdatabyidgroup(idx2, group, subitem);
for (int i = 0; i < 2; i++) {
int type = i ? type2 : type1;
if (type) {
if (rd && ((((rd->type & ROMTYPE_GROUP_MASK) & (type & ROMTYPE_GROUP_MASK)) && ((rd->type & ROMTYPE_SUB_MASK) == (type & ROMTYPE_SUB_MASK) || !(type & ROMTYPE_SUB_MASK))) ||
(rd->type & type) == ROMTYPE_NONE || (rd->type & type) == ROMTYPE_NOT)) {
getromname(rd, tmp);
int j;
for (j = 0; j < ridx; j++) {
if (!_tcsicmp(rde[j].name, tmp)) {
break;
}
}
if (j >= ridx) {
rde[ridx].name = my_strdup(tmp);
rde[ridx].priority = rd->sortpriority;
ridx++;
}
if (rd == rdx)
_tcscpy(seltmp, tmp);
break;
}
}
}
}
}
idx++;
}
lstAvailableROMs.clear();
for (int i = 0; i < ridx; i++) {
for (int j = i + 1; j < ridx; j++) {
int ipri = rde[i].priority;
const TCHAR* iname = rde[i].name;
int jpri = rde[j].priority;
const TCHAR* jname = rde[j].name;
if ((ipri > jpri) || (ipri == jpri && _tcsicmp(iname, jname) > 0)) {
struct romdataentry rdet;
memcpy(&rdet, &rde[i], sizeof(struct romdataentry));
memcpy(&rde[i], &rde[j], sizeof(struct romdataentry));
memcpy(&rde[j], &rdet, sizeof(struct romdataentry));
}
}
}
auto listmodel = d->getListModel(); //xSendDlgItemMessage(hDlg, d, CB_RESETCONTENT, 0, 0);
listmodel->clear_elements();
listmodel->add(""); //xSendDlgItemMessage(hDlg, d, CB_ADDSTRING, 0, (LPARAM)_T(""));
for (int i = 0; i < ridx; i++) {
struct romdataentry* rdep = &rde[i];
listmodel->add(rdep->name); //xSendDlgItemMessage(hDlg, d, CB_ADDSTRING, 0, (LPARAM)rdep->name);
xfree(rdep->name);
}
if (seltmp[0])
{
//xSendDlgItemMessage(hDlg, d, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)seltmp);
for (int i = 0; i < listmodel->getNumberOfElements(); i++) {
if (!_tcsicmp(listmodel->getElementAt(i).c_str(), seltmp)) {
d->setSelected(i);
break;
}
}
}
else
{
//SetDlgItemText(hDlg, d, path);
if (path && path[0])
{
listmodel->add(path);
d->setSelected(listmodel->getNumberOfElements() - 1);
}
}
xfree(rde);
}
static int addrom(struct romdata* rd, const char* path)
static int extpri(const TCHAR* p, int size)
{
char tmpName[MAX_DPATH];
auto* const tmp = new AvailableROM();
getromname(rd, tmpName);
tmp->Name.assign(tmpName);
if (path != nullptr)
tmp->Path.assign(path);
tmp->ROMType = rd->type;
lstAvailableROMs.emplace_back(tmp);
romlist_add(path, rd);
const TCHAR* s = _tcsrchr(p, '.');
if (s == NULL)
return 80;
// if archive: lowest priority
if (!my_existsfile(p))
return 100;
int pri = 10;
// prefer matching size
struct mystat ms;
if (my_stat(p, &ms)) {
if (ms.size == size) {
pri--;
}
}
return pri;
}
static int addrom(UAEREG* fkey, struct romdata* rd, const TCHAR* name)
{
TCHAR tmp1[MAX_DPATH], tmp2[MAX_DPATH], tmp3[MAX_DPATH];
char pathname[MAX_DPATH];
_stprintf(tmp1, _T("ROM_%03d"), rd->id);
if (rd->group) {
TCHAR* p = tmp1 + _tcslen(tmp1);
_stprintf(p, _T("_%02d_%02d"), rd->group >> 16, rd->group & 65535);
}
getromname(rd, tmp2);
pathname[0] = 0;
if (name) {
_tcscpy(pathname, name);
}
if (rd->crc32 == 0xffffffff) {
if (rd->configname)
_stprintf(tmp2, _T(":%s"), rd->configname);
else
_stprintf(tmp2, _T(":ROM_%03d"), rd->id);
}
int size = sizeof tmp3 / sizeof(TCHAR);
if (regquerystr(fkey, tmp1, tmp3, &size)) {
TCHAR* s = _tcschr(tmp3, '\"');
if (s && _tcslen(s) > 1) {
TCHAR* s2 = s + 1;
s = _tcschr(s2, '\"');
if (s)
*s = 0;
int pri1 = extpri(s2, rd->size);
int pri2 = extpri(pathname, rd->size);
if (pri2 >= pri1)
return 1;
}
}
fullpath(pathname, sizeof(pathname) / sizeof(TCHAR));
if (pathname[0]) {
_tcscat(tmp2, _T(" / \""));
_tcscat(tmp2, pathname);
_tcscat(tmp2, _T("\""));
}
if (!regsetstr(fkey, tmp1, tmp2))
return 0;
return 1;
}
struct romscandata
{
uae_u8* keybuf;
int keysize;
struct romscandata {
UAEREG* fkey;
int got;
};
static struct romdata* scan_single_rom_2(struct zfile* f)
@ -219,7 +371,7 @@ struct romdata *scan_single_rom (const TCHAR *path)
return scan_single_rom_2 (z);
}
static int isromext(const std::string& path)
static int isromext(const std::string& path, bool deepscan)
{
if (path.empty())
return 0;
@ -234,7 +386,8 @@ static int isromext(const std::string& path)
if (ext.size() >= 2 && std::toupper(ext[0]) == 'U' && std::isdigit(ext[1]))
return 1;
if (!deepscan)
return 0;
for (auto i = 0; uae_archive_extensions[i]; i++)
{
if (strcasecmp(ext.c_str(), uae_archive_extensions[i]) == 0)
@ -243,26 +396,68 @@ static int isromext(const std::string& path)
return 0;
}
static int scan_rom_2(struct zfile* f, void* dummy)
static bool scan_rom_hook(const TCHAR* name, int line)
{
auto* const path = zfile_getname(f);
// TODO
return true;
//MSG msg;
//if (cdstate.status)
// return false;
//if (!cdstate.active)
// return true;
//if (name != NULL) {
// const TCHAR* s = NULL;
// if (line == 2) {
// s = _tcsrchr(name, '/');
// if (!s)
// s = _tcsrchr(name, '\\');
// if (s)
// s++;
// }
// SetWindowText(GetDlgItem(cdstate.hwnd, line == 1 ? IDC_INFOBOX_TEXT1 : (line == 2 ? IDC_INFOBOX_TEXT2 : IDC_INFOBOX_TEXT3)), s ? s : name);
//}
//while (PeekMessage(&msg, cdstate.hwnd, 0, 0, PM_REMOVE)) {
// if (!IsDialogMessage(cdstate.hwnd, &msg)) {
// TranslateMessage(&msg);
// DispatchMessage(&msg);
// }
//}
//return cdstate.active;
}
if (!isromext(path))
static int scan_rom_2(struct zfile* f, void* vrsd)
{
struct romscandata* rsd = (struct romscandata*)vrsd;
const TCHAR* path = zfile_getname(f);
const TCHAR* romkey = _T("rom.key");
struct romdata* rd;
if (!isromext(path, true))
return 0;
auto* const rd = scan_single_rom_2(f);
rd = scan_single_rom_2(f);
if (rd)
addrom(rd, path);
{
TCHAR name[MAX_DPATH];
getromname(rd, name);
addrom(rsd->fkey, rd, path);
if (rd->type & ROMTYPE_KEY)
addkeyfile(path);
rsd->got = 1;
} else if (_tcslen(path) > _tcslen(romkey) && !_tcsicmp(path + _tcslen(path) - _tcslen(romkey), romkey)) {
addkeyfile(path);
}
return 0;
}
static void scan_rom(const std::string& path)
static int scan_rom(const std::string& path, UAEREG* fkey, bool deepscan)
{
struct romscandata rsd = { fkey, 0 };
struct romdata* rd;
int cnt = 0;
if (!isromext(path)) {
if (!isromext(path, deepscan)) {
//write_log("ROMSCAN: skipping file '%s', unknown extension\n", path);
return;
return 0;
}
#ifdef ARCADIA
for (;;) {
@ -270,14 +465,15 @@ static void scan_rom(const std::string& path)
_tcscpy(tmp, path.c_str());
rd = scan_arcadia_rom(tmp, cnt++);
if (rd) {
if (!addrom(rd, tmp))
return;
if (!addrom(fkey, rd, tmp))
return 1;
continue;
}
break;
}
#endif
zfile_zopen(path, scan_rom_2, nullptr);
zfile_zopen(path, scan_rom_2, (void*)&rsd);
return rsd.got;
}
void SymlinkROMs()
@ -285,52 +481,247 @@ void SymlinkROMs()
symlink_roms(&changed_prefs);
}
void RescanROMs()
static int listrom(const int* roms)
{
std::vector<std::string> dirs;
std::vector<std::string> files;
char path[MAX_DPATH];
int i;
romlist_clear();
ClearAvailableROMList();
get_rom_path(path, MAX_DPATH);
load_keyring(&changed_prefs, path);
read_directory(path, &dirs, &files);
// Root level scan
for (const auto& file : files)
{
scan_rom(std::string(path) + file);
i = 0;
while (roms[i] >= 0) {
struct romdata* rd = getromdatabyid(roms[i]);
if (rd && romlist_get(rd))
return 1;
i++;
}
return 0;
}
// Recursive scan
for (const auto& dir : dirs)
{
if (dir != "..")
{
std::string full_path = std::string(path) + dir;
read_directory(full_path, nullptr, &files);
for (const auto& file : files)
{
scan_rom(full_path + "/" + file);
}
}
static void show_rom_list(void)
{
// TODO
//TCHAR* p;
//TCHAR* p1, * p2;
//const int* rp;
//bool first = true;
//const int romtable[] = {
// 5, 4, -1, -1, // A500 1.2
// 6, 32, -1, -1, // A500 1.3
// 7, -1, -1, // A500+
// 8, 9, 10, -1, -1, // A600
// 23, 24, -1, -1, // A1000
// 11, 31, 15, -1, -1, // A1200
// 59, 71, 61, -1, -1, // A3000
// 16, 46, 31, 13, 12, -1, -1, // A4000
// 17, -1, -1, // A4000T
// 18, -1, 19, -1, -1, // CD32
// 20, 21, 22, -1, 6, 32, -1, -1, // CDTV
// 9, 10, -1, 107, 108, -1, -1, // CDTV-CR
// 49, 50, 75, 51, 76, 77, -1, 5, 4, -1, -2, // ARCADIA
// 18, -1, 19, -1, 74, 23, -1, -1, // CD32 FMV
// 69, 67, 70, 115, -1, -1, // nordic power
// 65, 68, -1, -1, // x-power
// 62, 60, -1, -1, // action cartridge
// 116, -1, -1, // pro access
// 52, 25, -1, -1, // ar 1
// 26, 27, 28, -1, -1, // ar 2
// 29, 30, -1, -1, // ar 3
// 47, -1, -1, // action replay 1200
// 0, 0, 0
//};
//p1 = _T("A500 Boot ROM 1.2\0A500 Boot ROM 1.3\0A500+\0A600\0A1000\0A1200\0A3000\0A4000\0A4000T\0")
// _T("CD32\0CDTV\0CDTV-CR\0Arcadia Multi Select\0")
// _T("CD32 Full Motion Video\0")
// _T("Nordic Power\0X-Power Professional 500\0Action Cartridge Super IV Professional\0")
// _T("Pro Access\0")
// _T("Action Replay MK I\0Action Replay MK II\0Action Replay MK III\0")
// _T("Action Replay 1200\0")
// _T("\0");
//p = xmalloc(TCHAR, 100000);
//if (!p)
// return;
//WIN32GUI_LoadUIString(IDS_ROMSCANEND, p, 100);
//_tcscat(p, _T("\n\n"));
//rp = romtable;
//while (rp[0]) {
// int ok = 1;
// p2 = p1 + _tcslen(p1) + 1;
// while (*rp >= 0) {
// if (ok) {
// ok = 0;
// if (listrom(rp))
// ok = 1;
// }
// while (*rp++ >= 0);
// }
// if (ok) {
// if (!first)
// _tcscat(p, _T(", "));
// first = false;
// _tcscat(p, p1);
// }
// if (*rp == -2) {
// _tcscat(p, _T("\n\n"));
// first = true;
// }
// rp++;
// p1 = p2;
//}
//pre_gui_message(p);
//free(p);
}
static int scan_roms_2(UAEREG* fkey, const TCHAR* path, bool deepscan, int level)
{
struct dirent* entry;
struct stat statbuf;
DIR* dp;
int ret = 0;
if (!path)
return 0;
write_log(_T("ROM scan directory '%s'\n"), path);
dp = opendir(path);
if (dp == NULL)
return 0;
scan_rom_hook(path, 1);
while ((entry = readdir(dp)) != NULL) {
TCHAR tmppath[MAX_DPATH];
_stprintf(tmppath, _T("%s/%s"), path, entry->d_name);
if (stat(tmppath, &statbuf) == -1)
continue;
if (S_ISREG(statbuf.st_mode) && statbuf.st_size < 10000000) {
if (scan_rom(tmppath, fkey, deepscan))
ret = 1;
} else if (deepscan && S_ISDIR(statbuf.st_mode) && entry->d_name[0] != '.' && (recursiveromscan < 0 || recursiveromscan > level)) {
scan_roms_2(fkey, tmppath, deepscan, level + 1);
}
if (!scan_rom_hook(NULL, 0))
break;
}
closedir(dp);
return ret;
}
#define MAX_ROM_PATHS 10
static int scan_roms_3(UAEREG* fkey, TCHAR** paths, const TCHAR* path)
{
int i, ret;
TCHAR pathp[MAX_DPATH];
bool deepscan = true;
ret = 0;
scan_rom_hook(NULL, 0);
pathp[0] = 0;
realpath(path, pathp);
if (!pathp[0])
return ret;
if (_tcsicmp(pathp, get_rom_path().c_str()) == 0)
deepscan = false; // do not scan root dir archives
for (i = 0; i < MAX_ROM_PATHS; i++) {
if (paths[i] && !_tcsicmp(paths[i], pathp))
return ret;
}
for (int id = 1;; ++id)
{
auto* rd = getromdatabyid(id);
if (!rd)
ret = scan_roms_2(fkey, pathp, deepscan, 0);
for (i = 0; i < MAX_ROM_PATHS; i++) {
if (!paths[i]) {
paths[i] = my_strdup(pathp);
break;
if (rd->crc32 == 0xffffffff)
{
if (strncmp(rd->model, "AROS", 4) == 0)
addrom(rd, ":AROS");
else if (rd->id == 63)
addrom(rd, ":HRTMon");
}
}
return ret;
}
int scan_roms(int show)
{
TCHAR path[MAX_DPATH];
static int recursive;
int id, i, ret, keys, cnt;
UAEREG* fkey, * fkey2;
TCHAR* paths[MAX_ROM_PATHS];
if (recursive)
return 0;
recursive++;
ret = 0;
regdeletetree(NULL, _T("DetectedROMs"));
fkey = regcreatetree(NULL, _T("DetectedROMs"));
if (fkey == NULL)
goto end;
cnt = 0;
for (i = 0; i < MAX_ROM_PATHS; i++)
paths[i] = NULL;
scan_rom_hook(NULL, 0);
while (scan_rom_hook(NULL, 0)) {
keys = get_keyring();
get_rom_path(path, sizeof path / sizeof(TCHAR));
cnt += scan_roms_3(fkey, paths, path);
// We only have one ROM path, so no need to scan other paths
//if (1) {
// static pathtype pt[] = { PATH_TYPE_DEFAULT, PATH_TYPE_WINUAE, PATH_TYPE_NEWWINUAE, PATH_TYPE_NEWAF, PATH_TYPE_AMIGAFOREVERDATA, PATH_TYPE_END };
// for (i = 0; pt[i] != PATH_TYPE_END; i++) {
// ret = get_rom_path(path, pt[i]);
// if (ret < 0)
// break;
// cnt += scan_roms_3(fkey, paths, path);
// }
// if (get_keyring() > keys) { /* more keys detected in previous scan? */
// write_log(_T("ROM scan: more keys found, restarting..\n"));
// for (i = 0; i < MAX_ROM_PATHS; i++) {
// xfree(paths[i]);
// paths[i] = NULL;
// }
// continue;
// }
//}
break;
}
if (cnt == 0)
scan_roms_3(fkey, paths, changed_prefs.path_rom.path[0]);
for (i = 0; i < MAX_ROM_PATHS; i++)
xfree(paths[i]);
fkey2 = regcreatetree(NULL, _T("DetectedROMS"));
if (fkey2) {
id = 1;
for (;;) {
struct romdata* rd = getromdatabyid(id);
if (!rd)
break;
if (rd->crc32 == 0xffffffff)
addrom(fkey, rd, NULL);
id++;
}
regclosetree(fkey2);
}
end:
read_rom_list(false);
if (show)
show_rom_list();
regclosetree(fkey);
recursive--;
return ret;
}
static void ClearConfigFileList()
@ -490,8 +881,7 @@ int gui_init()
emulating = 0;
auto ret = 0;
if (lstAvailableROMs.empty())
RescanROMs();
read_rom_list(false);
prefs_to_gui();
run_gui();
@ -515,7 +905,6 @@ void gui_exit()
close_sound();
save_amiberry_settings();
ClearConfigFileList();
ClearAvailableROMList();
}
void gui_purge_events()

View File

@ -23,6 +23,7 @@
#include "xwin.h"
#include "drawing.h"
#include "midiemu.h"
#include "registry.h"
extern void SetLastActiveConfig(const char* filename);
extern std::string current_dir;
@ -339,9 +340,6 @@ void cd_auto_prefs(uae_prefs* prefs, char* filepath)
write_log("\nCD Autoload: %s \n\n", filepath);
if (lstAvailableROMs.empty())
RescanROMs();
conf_path = get_configuration_path();
whdload_prefs.filename = get_game_filename(filepath);
@ -1219,9 +1217,6 @@ void whdload_auto_prefs(uae_prefs* prefs, const char* filepath)
if (amiberry_options.use_jst_instead_of_whd)
write_log("WHDBooter - Using JST instead of WHDLoad\n");
if (lstAvailableROMs.empty())
RescanROMs();
conf_path = get_configuration_path();
whdbooter_path = get_whdbootpath();
save_path = get_savedatapath(false);

File diff suppressed because it is too large Load Diff

View File

@ -259,7 +259,7 @@ class RescanROMsButtonActionListener : public gcn::ActionListener
public:
void action(const gcn::ActionEvent& actionEvent) override
{
RescanROMs();
scan_roms(true);
SymlinkROMs();
import_joysticks();

View File

@ -9,6 +9,8 @@
#include "options.h"
#include "rommgr.h"
#include "gui_handling.h"
#include "memory.h"
#include "registry.h"
#include "uae.h"
static gcn::Label* lblMainROM;
@ -23,164 +25,85 @@ static gcn::Button* cmdCartROM;
static gcn::Label* lblUAEROM;
static gcn::DropDown* cboUAEROM;
static gcn::CheckBox* chkMapRom;
static gcn::CheckBox* chkShapeShifter;
static gcn::CheckBox* chkKickShifter;
class ROMListModel : public gcn::ListModel
{
std::vector<std::string> roms;
std::vector<int> idxToAvailableROMs;
int ROMType;
public:
explicit ROMListModel(const int romtype)
{
ROMType = romtype;
}
int getNumberOfElements() override
{
return int(roms.size());
}
void add(const std::string& elem)
{
roms.emplace_back(elem);
}
void clear()
{
roms.clear();
}
std::string getElementAt(const int i) override
{
if (i < 0 || i >= static_cast<int>(roms.size()))
return "---";
return roms[i];
}
AvailableROM* get_rom_at(const int i)
{
if (i >= 0 && i < static_cast<int>(idxToAvailableROMs.size()))
return idxToAvailableROMs[i] < 0 ? nullptr : lstAvailableROMs[idxToAvailableROMs[i]];
return nullptr;
}
int init_rom_list(char* current)
{
roms.clear();
idxToAvailableROMs.clear();
auto currIdx = -1;
if (ROMType & (ROMTYPE_ALL_EXT | ROMTYPE_ALL_CART))
{
roms.emplace_back(" ");
idxToAvailableROMs.push_back(-1);
currIdx = 0;
}
for (auto i = 0; i < static_cast<int>(lstAvailableROMs.size()); ++i)
{
if (lstAvailableROMs[i]->ROMType & ROMType)
{
if (!stricmp(lstAvailableROMs[i]->Path.c_str(), current))
currIdx = int(roms.size());
roms.emplace_back(lstAvailableROMs[i]->Name);
idxToAvailableROMs.push_back(i);
}
}
return currIdx;
}
};
static ROMListModel* mainROMList;
static ROMListModel* extROMList;
static ROMListModel* cartROMList;
static const std::vector<std::string> uaeValues = { "ROM disabled", "Original UAE (FS + F0 ROM)", "New UAE (64k + F0 ROM)", "New UAE (128k, ROM, Direct)", "New UAE (128k, ROM, Indirect)" };
static gcn::StringListModel uaeList(uaeValues);
class MainROMActionListener : public gcn::ActionListener
{
public:
void action(const gcn::ActionEvent& actionEvent) override
{
auto* const rom = mainROMList->get_rom_at(cboMainROM->getSelected());
if (rom != nullptr)
strncpy(changed_prefs.romfile, rom->Path.c_str(), sizeof changed_prefs.romfile);
}
};
static MainROMActionListener* mainROMActionListener;
class ExtROMActionListener : public gcn::ActionListener
{
public:
void action(const gcn::ActionEvent& actionEvent) override
{
auto* const rom = extROMList->get_rom_at(cboExtROM->getSelected());
if (rom != nullptr)
strncpy(changed_prefs.romextfile, rom->Path.c_str(), sizeof changed_prefs.romextfile);
else
strncpy(changed_prefs.romextfile, " ", sizeof changed_prefs.romextfile);
}
};
static ExtROMActionListener* extROMActionListener;
class CartROMActionListener : public gcn::ActionListener
{
public:
void action(const gcn::ActionEvent& actionEvent) override
{
auto* const rom = cartROMList->get_rom_at(cboCartROM->getSelected());
if (rom != nullptr)
strncpy(changed_prefs.cartfile, rom->Path.c_str(), sizeof changed_prefs.cartfile);
else
strncpy(changed_prefs.cartfile, "", sizeof changed_prefs.cartfile);
}
};
static CartROMActionListener* cartROMActionListener;
static gcn::StringListModel mainROMList;
static gcn::StringListModel extROMList;
static gcn::StringListModel cartROMList;
static gcn::StringListModel uaeboard_type_list;
// Helper function to reduce code duplication
void handleROMSelection(const gcn::ActionEvent& actionEvent, char* prefsFile, const int romType)
void handleROMSelection(const gcn::ActionEvent& actionEvent, char* prefs)
{
std::string tmp;
const char* filter[] = { ".rom", ".bin", "\0" };
tmp = SelectFile("Select ROM", get_rom_path(), filter);
if (!tmp.empty())
{
auto* const newrom = new AvailableROM();
newrom->Name = extract_filename(tmp);
newrom->Name = remove_file_extension(newrom->Name);
newrom->Path = tmp;
newrom->ROMType = romType;
lstAvailableROMs.push_back(newrom);
strncpy(prefsFile, tmp.c_str(), MAX_DPATH - 1);
strncpy(prefs, tmp.c_str(), MAX_DPATH);
fullpath(prefs, MAX_DPATH);
RefreshPanelROM();
}
actionEvent.getSource()->requestFocus();
}
class ROMButtonActionListener : public gcn::ActionListener
static void getromfile(gcn::DropDown* d, TCHAR* path, int size)
{
auto val = d->getSelected(); //LRESULT val = xSendDlgItemMessage(hDlg, d, CB_GETCURSEL, 0, 0L);
if (val == -1) {
//xSendDlgItemMessage(hDlg, d, WM_GETTEXT, (WPARAM)size, (LPARAM)path);
auto listmodel = d->getListModel();
listmodel->add(path);
val = listmodel->getNumberOfElements() - 1;
d->setSelected(val);
}
else {
struct romdata* rd;
auto listmodel = d->getListModel();
std::string tmp1 = listmodel->getElementAt(val);
path[0] = 0;
rd = getromdatabyname(tmp1.c_str());
if (rd) {
struct romlist* rl = getromlistbyromdata(rd);
if (rd->configname)
_stprintf(path, _T(":%s"), rd->configname);
else if (rl)
_tcsncpy(path, rl->path, size);
}
}
}
class ROMActionListener : public gcn::ActionListener
{
public:
void action(const gcn::ActionEvent& actionEvent) override
{
if (actionEvent.getSource() == cmdMainROM)
auto source = actionEvent.getSource();
if (source == cboMainROM)
{
handleROMSelection(actionEvent, changed_prefs.romfile, ROMTYPE_KICK);
getromfile(cboMainROM, changed_prefs.romfile, sizeof(changed_prefs.romfile) / sizeof(TCHAR));
}
else if (actionEvent.getSource() == cmdExtROM)
else if (source == cboExtROM)
{
handleROMSelection(actionEvent, changed_prefs.romextfile, ROMTYPE_EXTCDTV);
getromfile(cboExtROM, changed_prefs.romextfile, sizeof(changed_prefs.romextfile) / sizeof(TCHAR));
}
else if (actionEvent.getSource() == cmdCartROM)
else if (source == cboCartROM)
{
handleROMSelection(actionEvent, changed_prefs.cartfile, ROMTYPE_CD32CART);
getromfile(cboCartROM, changed_prefs.cartfile, sizeof(changed_prefs.cartfile) / sizeof(TCHAR));
}
else if (actionEvent.getSource() == cboUAEROM)
else if (source == cmdMainROM)
{
handleROMSelection(actionEvent, changed_prefs.romfile);
}
else if (source == cmdExtROM)
{
handleROMSelection(actionEvent, changed_prefs.romextfile);
}
else if (source == cmdCartROM)
{
handleROMSelection(actionEvent, changed_prefs.cartfile);
}
else if (source == cboUAEROM)
{
const auto v = cboUAEROM->getSelected();
if (v > 0) {
@ -192,102 +115,104 @@ public:
changed_prefs.boot_rom = 1; // disabled
}
}
else if (actionEvent.getSource() == chkMapRom)
else if (source == chkMapRom)
{
changed_prefs.maprom = chkMapRom->isSelected() ? 0x0f000000 : 0;
}
else if (actionEvent.getSource() == chkShapeShifter)
else if (source == chkKickShifter)
{
changed_prefs.kickshifter = chkShapeShifter->isSelected();
changed_prefs.kickshifter = chkKickShifter->isSelected();
}
read_kickstart_version(&changed_prefs);
}
};
static ROMButtonActionListener* romButtonActionListener;
static ROMActionListener* romActionListener;
void InitPanelROM(const config_category& category)
{
uaeboard_type_list.clear();
uaeboard_type_list.add("ROM disabled");
uaeboard_type_list.add("Original UAE (FS + F0 ROM)");
uaeboard_type_list.add("New UAE (64k + F0 ROM)");
uaeboard_type_list.add("New UAE (128k, ROM, Direct)");
uaeboard_type_list.add("New UAE (128k, ROM, Indirect)");
const auto textFieldWidth = category.panel->getWidth() - 2 * DISTANCE_BORDER - SMALL_BUTTON_WIDTH - DISTANCE_NEXT_X;
mainROMActionListener = new MainROMActionListener();
extROMActionListener = new ExtROMActionListener();
cartROMActionListener = new CartROMActionListener();
romButtonActionListener = new ROMButtonActionListener();
mainROMList = new ROMListModel(ROMTYPE_ALL_KICK);
extROMList = new ROMListModel(ROMTYPE_ALL_EXT);
cartROMList = new ROMListModel(ROMTYPE_ALL_CART);
romActionListener = new ROMActionListener();
lblMainROM = new gcn::Label("Main ROM File:");
cboMainROM = new gcn::DropDown(mainROMList);
cboMainROM = new gcn::DropDown(&mainROMList);
cboMainROM->setSize(textFieldWidth, cboMainROM->getHeight());
cboMainROM->setBaseColor(gui_base_color);
cboMainROM->setBackgroundColor(gui_background_color);
cboMainROM->setForegroundColor(gui_foreground_color);
cboMainROM->setSelectionColor(gui_selection_color);
cboMainROM->setId("cboMainROM");
cboMainROM->addActionListener(mainROMActionListener);
cboMainROM->addActionListener(romActionListener);
cmdMainROM = new gcn::Button("...");
cmdMainROM->setId("MainROM");
cmdMainROM->setSize(SMALL_BUTTON_WIDTH, SMALL_BUTTON_HEIGHT);
cmdMainROM->setBaseColor(gui_base_color);
cmdMainROM->setForegroundColor(gui_foreground_color);
cmdMainROM->addActionListener(romButtonActionListener);
cmdMainROM->addActionListener(romActionListener);
lblExtROM = new gcn::Label("Extended ROM File:");
cboExtROM = new gcn::DropDown(extROMList);
cboExtROM = new gcn::DropDown(&extROMList);
cboExtROM->setSize(textFieldWidth, cboExtROM->getHeight());
cboExtROM->setBaseColor(gui_base_color);
cboExtROM->setBackgroundColor(gui_background_color);
cboExtROM->setForegroundColor(gui_foreground_color);
cboExtROM->setSelectionColor(gui_selection_color);
cboExtROM->setId("cboExtROM");
cboExtROM->addActionListener(extROMActionListener);
cboExtROM->addActionListener(romActionListener);
cmdExtROM = new gcn::Button("...");
cmdExtROM->setId("ExtROM");
cmdExtROM->setSize(SMALL_BUTTON_WIDTH, SMALL_BUTTON_HEIGHT);
cmdExtROM->setBaseColor(gui_base_color);
cmdExtROM->setForegroundColor(gui_foreground_color);
cmdExtROM->addActionListener(romButtonActionListener);
cmdExtROM->addActionListener(romActionListener);
chkMapRom = new gcn::CheckBox("MapROM emulation");
chkMapRom->setId("chkMapRom");
chkMapRom->setBaseColor(gui_base_color);
chkMapRom->setBackgroundColor(gui_background_color);
chkMapRom->setForegroundColor(gui_foreground_color);
chkMapRom->addActionListener(romButtonActionListener);
chkMapRom->addActionListener(romActionListener);
chkShapeShifter = new gcn::CheckBox("ShapeShifter support");
chkShapeShifter->setId("chkShapeShifter");
chkShapeShifter->setBaseColor(gui_base_color);
chkShapeShifter->setBackgroundColor(gui_background_color);
chkShapeShifter->setForegroundColor(gui_foreground_color);
chkShapeShifter->addActionListener(romButtonActionListener);
chkKickShifter = new gcn::CheckBox("ShapeShifter support");
chkKickShifter->setId("chkKickShifter");
chkKickShifter->setBaseColor(gui_base_color);
chkKickShifter->setBackgroundColor(gui_background_color);
chkKickShifter->setForegroundColor(gui_foreground_color);
chkKickShifter->addActionListener(romActionListener);
lblCartROM = new gcn::Label("Cartridge ROM File:");
cboCartROM = new gcn::DropDown(cartROMList);
cboCartROM = new gcn::DropDown(&cartROMList);
cboCartROM->setSize(textFieldWidth, cboCartROM->getHeight());
cboCartROM->setBaseColor(gui_base_color);
cboCartROM->setBackgroundColor(gui_background_color);
cboCartROM->setForegroundColor(gui_foreground_color);
cboCartROM->setSelectionColor(gui_selection_color);
cboCartROM->setId("cboCartROM");
cboCartROM->addActionListener(cartROMActionListener);
cboCartROM->addActionListener(romActionListener);
cmdCartROM = new gcn::Button("...");
cmdCartROM->setId("CartROM");
cmdCartROM->setSize(SMALL_BUTTON_WIDTH, SMALL_BUTTON_HEIGHT);
cmdCartROM->setBaseColor(gui_base_color);
cmdCartROM->setForegroundColor(gui_foreground_color);
cmdCartROM->addActionListener(romButtonActionListener);
cmdCartROM->addActionListener(romActionListener);
lblUAEROM = new gcn::Label("Advanced UAE expansion board/Boot ROM:");
cboUAEROM = new gcn::DropDown(&uaeList);
cboUAEROM = new gcn::DropDown(&uaeboard_type_list);
cboUAEROM->setSize(textFieldWidth, cboUAEROM->getHeight());
cboUAEROM->setBaseColor(gui_base_color);
cboUAEROM->setBackgroundColor(gui_background_color);\
cboUAEROM->setForegroundColor(gui_foreground_color);
cboUAEROM->setSelectionColor(gui_selection_color);
cboUAEROM->setId("cboUAEROM");
cboUAEROM->addActionListener(romButtonActionListener);
cboUAEROM->addActionListener(romActionListener);
int posY = DISTANCE_BORDER;
category.panel->add(lblMainROM, DISTANCE_BORDER, posY);
@ -303,7 +228,7 @@ void InitPanelROM(const config_category& category)
posY += cboExtROM->getHeight() + DISTANCE_NEXT_Y;
category.panel->add(chkMapRom, DISTANCE_BORDER, posY);
category.panel->add(chkShapeShifter, chkMapRom->getX() + chkMapRom->getWidth() + DISTANCE_NEXT_X * 2, posY);
category.panel->add(chkKickShifter, chkMapRom->getX() + chkMapRom->getWidth() + DISTANCE_NEXT_X * 2, posY);
posY += chkMapRom->getHeight() + DISTANCE_NEXT_Y * 2;
category.panel->add(lblCartROM, DISTANCE_BORDER, posY);
@ -324,53 +249,41 @@ void ExitPanelROM()
delete lblMainROM;
delete cboMainROM;
delete cmdMainROM;
delete mainROMList;
delete mainROMActionListener;
delete romActionListener;
delete lblExtROM;
delete cboExtROM;
delete cmdExtROM;
delete extROMList;
delete extROMActionListener;
delete lblCartROM;
delete cboCartROM;
delete cmdCartROM;
delete cartROMList;
delete cartROMActionListener;
delete lblUAEROM;
delete cboUAEROM;
delete chkMapRom;
delete chkShapeShifter;
delete romButtonActionListener;
}
void refresh_rom_list(ROMListModel* rom_list, const gcn::DropDown* cboROM, char* prefsFile, const int romType)
{
const auto idx = rom_list->init_rom_list(prefsFile);
if (idx != -1)
{
cboROM->setSelected(idx);
}
else if (strlen(prefsFile) > 0)
{
// ROM file not in the list of known ROMs
auto* newrom = new AvailableROM();
newrom->Path = prefsFile;
newrom->Name = extract_filename(prefsFile);
newrom->Name = remove_file_extension(newrom->Name);
newrom->ROMType = romType;
lstAvailableROMs.push_back(newrom);
RefreshPanelROM();
}
delete chkKickShifter;
}
void RefreshPanelROM()
{
refresh_rom_list(mainROMList, cboMainROM, changed_prefs.romfile, ROMTYPE_KICK);
refresh_rom_list(extROMList, cboExtROM, changed_prefs.romextfile, ROMTYPE_EXTCDTV);
refresh_rom_list(cartROMList, cboCartROM, changed_prefs.cartfile, ROMTYPE_CD32CART);
UAEREG* fkey = regcreatetree(NULL, _T("DetectedROMs"));
load_keyring(&changed_prefs, NULL);
addromfiles(fkey, cboMainROM, changed_prefs.romfile,
ROMTYPE_KICK | ROMTYPE_KICKCD32, 0);
addromfiles(fkey, cboExtROM, changed_prefs.romextfile,
ROMTYPE_EXTCD32 | ROMTYPE_EXTCDTV | ROMTYPE_ARCADIABIOS | ROMTYPE_ALG, 0);
addromfiles(fkey, cboCartROM, changed_prefs.cartfile,
ROMTYPE_FREEZER | ROMTYPE_ARCADIAGAME | ROMTYPE_CD32CART, 0);
regclosetree(fkey);
//TODO add flashfile and rtcfile options
chkKickShifter->setSelected(changed_prefs.kickshifter);
chkMapRom->setSelected(changed_prefs.maprom);
if (changed_prefs.boot_rom == 1) {
cboUAEROM->setSelected(0);
@ -379,8 +292,6 @@ void RefreshPanelROM()
cboUAEROM->setSelected(changed_prefs.uaeboard + 1);
}
cboUAEROM->setEnabled(!emulating);
chkMapRom->setSelected(changed_prefs.maprom);
chkShapeShifter->setSelected(changed_prefs.kickshifter);
}
bool HelpPanelROM(std::vector<std::string>& helptext)

View File

@ -27,13 +27,17 @@ namespace gcn {
return mStrings.at(i);
}
void add(const std::string &str) {
void add(const std::string &str) override
{
mStrings.push_back(str);
}
void clear() {
mStrings.clear();
}
void clear_elements() override {
mStrings.clear();
}
void swap_first(const std::string &str) {
mStrings.erase(mStrings.begin());

View File

@ -6,6 +6,7 @@
#include "amiberry_input.h"
#include "filesys.h"
#include "options.h"
#include "registry.h"
enum
{
@ -438,4 +439,6 @@ extern void apply_theme_extras();
extern void SetLastActiveConfig(const char* filename);
extern void addromfiles(UAEREG* fkey, gcn::DropDown* d, const TCHAR* path, int type1, int type2);
#endif // GUI_HANDLING_H

555
src/osdep/registry.cpp Normal file
View File

@ -0,0 +1,555 @@
#include "sysconfig.h"
#include "sysdeps.h"
#ifdef _WIN32
#include <windows.h>
#include <shlwapi.h>
#include "win32.h"
#endif
#include "registry.h"
#include "ini.h"
#include "uae.h"
#include <filesystem>
#ifdef _WIN32
static int inimode = 0;
#else
static int inimode = 1;
#endif
static TCHAR* inipath;
#define ROOT_TREE _T("Amiberry")
static struct ini_data* inidata;
static HKEY gr(UAEREG* root)
{
#ifdef _WIN32
if (!root)
return hWinUAEKey;
#else
if (!root)
return NULL;
#endif
return root->fkey;
}
static const TCHAR* gs(UAEREG* root)
{
if (!root)
return ROOT_TREE;
return root->inipath;
}
static TCHAR* gsn(UAEREG* root, const TCHAR* name)
{
const TCHAR* r;
TCHAR* s;
if (!root)
return my_strdup(name);
r = gs(root);
s = xmalloc(TCHAR, _tcslen(r) + 1 + _tcslen(name) + 1);
_stprintf(s, _T("%s/%s"), r, name);
return s;
}
int regsetstr(UAEREG* root, const TCHAR* name, const TCHAR* str)
{
if (inimode) {
int ret = ini_addstring(inidata, gs(root), name, str);
return ret;
}
#ifdef _WIN32
else {
HKEY rk = gr(root);
if (!rk)
return 0;
return RegSetValueEx(rk, name, 0, REG_SZ, (CONST BYTE*)str, (uaetcslen(str) + 1) * sizeof(TCHAR)) == ERROR_SUCCESS;
}
#endif
}
int regsetint(UAEREG* root, const TCHAR* name, int val)
{
if (inimode) {
int ret;
TCHAR tmp[100];
_stprintf(tmp, _T("%d"), val);
ret = ini_addstring(inidata, gs(root), name, tmp);
return ret;
}
#ifdef _WIN32
else {
DWORD v = val;
HKEY rk = gr(root);
if (!rk)
return 0;
return RegSetValueEx(rk, name, 0, REG_DWORD, (CONST BYTE*) & v, sizeof(DWORD)) == ERROR_SUCCESS;
}
#endif
}
int regqueryint(UAEREG* root, const TCHAR* name, int* val)
{
if (inimode) {
int ret = 0;
TCHAR* tmp = NULL;
if (ini_getstring(inidata, gs(root), name, &tmp)) {
*val = _tstol(tmp);
ret = 1;
}
xfree(tmp);
return ret;
}
#ifdef _WIN32
else {
DWORD dwType = REG_DWORD;
DWORD size = sizeof(int);
HKEY rk = gr(root);
if (!rk)
return 0;
return RegQueryValueEx(rk, name, 0, &dwType, (LPBYTE)val, &size) == ERROR_SUCCESS;
}
#endif
}
int regsetlonglong(UAEREG* root, const TCHAR* name, unsigned long long val)
{
if (inimode) {
int ret;
TCHAR tmp[100];
_stprintf(tmp, _T("%I64d"), val);
ret = ini_addstring(inidata, gs(root), name, tmp);
return ret;
}
#ifdef _WIN32
else {
ULONGLONG v = val;
HKEY rk = gr(root);
if (!rk)
return 0;
return RegSetValueEx(rk, name, 0, REG_QWORD, (CONST BYTE*) & v, sizeof(ULONGLONG)) == ERROR_SUCCESS;
}
#endif
}
int regquerylonglong(UAEREG* root, const TCHAR* name, unsigned long long* val)
{
*val = 0;
if (inimode) {
int ret = 0;
TCHAR* tmp = NULL;
if (ini_getstring(inidata, gs(root), name, &tmp)) {
*val = _tstoi64(tmp);
ret = 1;
}
xfree(tmp);
return ret;
}
#ifdef _WIN32
else {
DWORD dwType = REG_QWORD;
DWORD size = sizeof(ULONGLONG);
HKEY rk = gr(root);
if (!rk)
return 0;
return RegQueryValueEx(rk, name, 0, &dwType, (LPBYTE)val, &size) == ERROR_SUCCESS;
}
#endif
}
int regquerystr(UAEREG* root, const TCHAR* name, TCHAR* str, int* size)
{
if (inimode) {
int ret = 0;
TCHAR* tmp = NULL;
if (ini_getstring(inidata, gs(root), name, &tmp)) {
if (_tcslen(tmp) >= *size)
tmp[(*size) - 1] = 0;
_tcscpy(str, tmp);
*size = uaetcslen(str);
ret = 1;
}
xfree(tmp);
return ret;
}
#ifdef _WIN32
else {
DWORD size2 = *size * sizeof(TCHAR);
HKEY rk = gr(root);
if (!rk)
return 0;
int v = RegQueryValueEx(rk, name, 0, NULL, (LPBYTE)str, &size2) == ERROR_SUCCESS;
*size = size2 / sizeof(TCHAR);
return v;
}
#endif
}
int regenumstr(UAEREG* root, int idx, TCHAR* name, int* nsize, TCHAR* str, int* size)
{
name[0] = 0;
str[0] = 0;
if (inimode) {
TCHAR* name2 = NULL;
TCHAR* str2 = NULL;
int ret = ini_getsectionstring(inidata, gs(root), idx, &name2, &str2);
if (ret) {
if (_tcslen(name2) >= *nsize) {
name2[(*nsize) - 1] = 0;
}
if (_tcslen(str2) >= *size) {
str2[(*size) - 1] = 0;
}
_tcscpy(name, name2);
_tcscpy(str, str2);
}
xfree(str2);
xfree(name2);
return ret;
}
#ifdef _WIN32
else {
DWORD nsize2 = *nsize;
DWORD size2 = *size;
HKEY rk = gr(root);
if (!rk)
return 0;
int v = RegEnumValue(rk, idx, name, &nsize2, NULL, NULL, (LPBYTE)str, &size2) == ERROR_SUCCESS;
*nsize = nsize2;
*size = size2;
return v;
}
#endif
}
int regquerydatasize(UAEREG* root, const TCHAR* name, int* size)
{
if (inimode) {
int ret = 0;
int csize = 65536;
TCHAR* tmp = xmalloc(TCHAR, csize);
if (regquerystr(root, name, tmp, &csize)) {
*size = uaetcslen(tmp) / 2;
ret = 1;
}
xfree(tmp);
return ret;
}
#ifdef _WIN32
else {
HKEY rk = gr(root);
if (!rk)
return 0;
DWORD size2 = *size;
int v = RegQueryValueEx(rk, name, 0, NULL, NULL, &size2) == ERROR_SUCCESS;
*size = size2;
return v;
}
#endif
}
int regsetdata(UAEREG* root, const TCHAR* name, const void* str, int size)
{
if (inimode) {
uae_u8* in = (uae_u8*)str;
int ret;
TCHAR* tmp = xmalloc(TCHAR, size * 2 + 1);
for (int i = 0; i < size; i++)
_stprintf(tmp + i * 2, _T("%02X"), in[i]);
ret = ini_addstring(inidata, gs(root), name, tmp);
xfree(tmp);
return ret;
}
#ifdef _WIN32
else {
HKEY rk = gr(root);
if (!rk)
return 0;
return RegSetValueEx(rk, name, 0, REG_BINARY, (BYTE*)str, size) == ERROR_SUCCESS;
}
#endif
}
int regquerydata(UAEREG* root, const TCHAR* name, void* str, int* size)
{
if (inimode) {
int csize = (*size) * 2 + 1;
int i, j;
int ret = 0;
TCHAR* tmp = xmalloc(TCHAR, csize);
uae_u8* out = (uae_u8*)str;
if (!regquerystr(root, name, tmp, &csize))
goto err;
j = 0;
for (i = 0; i < _tcslen(tmp); i += 2) {
TCHAR c1 = _totupper(tmp[i + 0]);
TCHAR c2 = _totupper(tmp[i + 1]);
if (c1 >= 'A')
c1 -= 'A' - 10;
else if (c1 >= '0')
c1 -= '0';
if (c1 > 15)
goto err;
if (c2 >= 'A')
c2 -= 'A' - 10;
else if (c2 >= '0')
c2 -= '0';
if (c2 > 15)
goto err;
out[j++] = c1 * 16 + c2;
}
ret = 1;
err:
xfree(tmp);
return ret;
}
#ifdef _WIN32
else {
HKEY rk = gr(root);
if (!rk)
return 0;
DWORD size2 = *size;
int v = RegQueryValueEx(rk, name, 0, NULL, (LPBYTE)str, &size2) == ERROR_SUCCESS;
*size = size2;
return v;
}
#endif
}
int regdelete(UAEREG* root, const TCHAR* name)
{
if (inimode) {
ini_delete(inidata, gs(root), name);
return 1;
}
#ifdef _WIN32
else {
HKEY rk = gr(root);
if (!rk)
return 0;
return RegDeleteValue(rk, name) == ERROR_SUCCESS;
}
#endif
}
int regexists(UAEREG* root, const TCHAR* name)
{
if (inimode) {
if (!inidata)
return 0;
int ret = ini_getstring(inidata, gs(root), name, NULL);
return ret;
}
#ifdef _WIN32
else {
HKEY rk = gr(root);
if (!rk)
return 0;
return RegQueryValueEx(rk, name, 0, NULL, NULL, NULL) == ERROR_SUCCESS;
}
#endif
}
void regdeletetree(UAEREG* root, const TCHAR* name)
{
if (inimode) {
TCHAR* s = gsn(root, name);
if (!s)
return;
ini_delete(inidata, s, NULL);
xfree(s);
}
#ifdef _WIN32
else {
HKEY rk = gr(root);
if (!rk)
return;
SHDeleteKey(rk, name);
}
#endif
}
int regexiststree(UAEREG* root, const TCHAR* name)
{
if (inimode) {
int ret = 0;
TCHAR* s = gsn(root, name);
if (!s)
return 0;
ret = ini_getstring(inidata, s, NULL, NULL);
xfree(s);
return ret;
}
#ifdef _WIN32
else {
int ret = 0;
HKEY k = NULL;
HKEY rk = gr(root);
if (!rk)
return 0;
if (RegOpenKeyEx(rk, name, 0, KEY_READ, &k) == ERROR_SUCCESS)
ret = 1;
if (k)
RegCloseKey(k);
return ret;
}
#endif
}
UAEREG* regcreatetree(UAEREG* root, const TCHAR* name)
{
UAEREG* fkey;
HKEY rkey;
if (inimode) {
TCHAR* ininame;
if (!root) {
if (!name)
ininame = my_strdup(gs(NULL));
else
ininame = my_strdup(name);
}
else {
ininame = xmalloc(TCHAR, _tcslen(root->inipath) + 1 + _tcslen(name) + 1);
_stprintf(ininame, _T("%s/%s"), root->inipath, name);
}
fkey = xcalloc(UAEREG, 1);
fkey->inipath = ininame;
}
#ifdef _WIN32
else {
DWORD err;
HKEY rk = gr(root);
if (!rk) {
rk = HKEY_CURRENT_USER;
name = _T("Software\\Arabuusimiehet\\WinUAE");
}
else if (!name) {
name = _T("");
}
err = RegCreateKeyEx(rk, name, 0, NULL, REG_OPTION_NON_VOLATILE,
KEY_READ | KEY_WRITE, NULL, &rkey, NULL);
if (err != ERROR_SUCCESS)
return 0;
fkey = xcalloc(UAEREG, 1);
fkey->fkey = rkey;
}
#endif
return fkey;
}
void regclosetree(UAEREG* key)
{
if (inimode) {
if (inidata->modified) {
ini_save(inidata, inipath);
}
}
if (!key)
return;
#ifdef _WIN32
if (key->fkey)
RegCloseKey(key->fkey);
#endif
xfree(key->inipath);
xfree(key);
}
int reginitializeinit(TCHAR** pppath)
{
UAEREG* r = NULL;
TCHAR path[MAX_DPATH], fpath[MAX_DPATH];
FILE* f;
TCHAR* ppath = *pppath;
inimode = 0;
if (!ppath) {
int ok = 0;
TCHAR* posn;
path[0] = 0;
#ifdef _WIN32
GetFullPathName(executable_path, sizeof path / sizeof(TCHAR), path, NULL);
if (_tcslen(path) > 4 && !_tcsicmp(path + _tcslen(path) - 4, _T(".exe"))) {
_tcscpy(path + _tcslen(path) - 3, _T("ini"));
if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
ok = 1;
}
if (!ok) {
path[0] = 0;
GetFullPathName(executable_path, sizeof path / sizeof(TCHAR), path, NULL);
if ((posn = _tcsrchr(path, '\\')))
posn[1] = 0;
_tcscat(path, _T("amiberry.ini"));
}
if (GetFileAttributes(path) == INVALID_FILE_ATTRIBUTES)
return 0;
#else
std::string ini_file_path = get_ini_file_path();
if (std::filesystem::exists(ini_file_path)) {
_tcscpy(path, ini_file_path.c_str());
ok = 1;
}
else
return 0;
#endif
}
else {
_tcscpy(path, ppath);
}
fpath[0] = 0;
#ifdef _WIN32
GetFullPathName(path, sizeof fpath / sizeof(TCHAR), fpath, NULL);
if (_tcslen(fpath) < 5 || _tcsicmp(fpath + _tcslen(fpath) - 4, _T(".ini")))
return 0;
#else
std::string ini_file_path = get_ini_file_path();
_tcscpy(fpath, ini_file_path.c_str());
#endif
inimode = 1;
inipath = my_strdup(fpath);
inidata = ini_load(inipath, true);
if (!regexists(NULL, _T("Version")))
goto fail;
return 1;
fail:
regclosetree(r);
#ifdef _WIN32
if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
DeleteFile(path);
if (GetFileAttributes(path) != INVALID_FILE_ATTRIBUTES)
goto end;
#else
if (std::filesystem::exists(path))
std::filesystem::remove(path);
if (std::filesystem::exists(path))
goto end;
#endif
f = fopen(path, _T("wb"));
if (f) {
uae_u8 bom[3] = { 0xef, 0xbb, 0xbf };
fwrite(bom, sizeof(bom), 1, f);
fclose(f);
}
if (*pppath == NULL)
*pppath = my_strdup(path);
return 1;
end:
inimode = 0;
xfree(inipath);
return 0;
}
void regstatus(void)
{
if (inimode)
write_log(_T("'%s' enabled\n"), inipath);
}
const TCHAR* getregmode(void)
{
if (!inimode)
return NULL;
return inipath;
}

31
src/osdep/registry.h Normal file
View File

@ -0,0 +1,31 @@
#pragma once
typedef struct UAEREG {
HKEY fkey;
TCHAR* inipath;
} UAEREG;
extern const TCHAR* getregmode(void);
extern int reginitializeinit(TCHAR** path);
extern void regstatus(void);
extern int regsetstr(UAEREG*, const TCHAR* name, const TCHAR* str);
extern int regsetint(UAEREG*, const TCHAR* name, int val);
extern int regqueryint(UAEREG*, const TCHAR* name, int* val);
extern int regquerystr(UAEREG*, const TCHAR* name, TCHAR* str, int* size);
extern int regsetlonglong(UAEREG* root, const TCHAR* name, unsigned long long val);
extern int regquerylonglong(UAEREG* root, const TCHAR* name, unsigned long long* val);
extern int regdelete(UAEREG*, const TCHAR* name);
extern void regdeletetree(UAEREG*, const TCHAR* name);
extern int regexists(UAEREG*, const TCHAR* name);
extern int regexiststree(UAEREG*, const TCHAR* name);
extern int regquerydatasize(UAEREG* root, const TCHAR* name, int* size);
extern int regsetdata(UAEREG*, const TCHAR* name, const void* str, int size);
extern int regquerydata(UAEREG* root, const TCHAR* name, void* str, int* size);
extern int regenumstr(UAEREG*, int idx, TCHAR* name, int* nsize, TCHAR* str, int* size);
extern UAEREG* regcreatetree(UAEREG*, const TCHAR* name);
extern void regclosetree(UAEREG* key);

View File

@ -140,9 +140,9 @@ extern std::string extract_path(const std::string& filename);
extern void remove_file_extension(char* filename);
extern std::string remove_file_extension(const std::string& filename);
extern void ReadConfigFileList(void);
extern void RescanROMs(void);
extern void read_rom_list(bool);
extern int scan_roms(int show);
extern void SymlinkROMs(void);
extern void ClearAvailableROMList(void);
extern bool resumepaused(int priority);
extern bool setpaused(int priority);
@ -155,15 +155,6 @@ void init_colors(int monid);
#include <vector>
#include <string>
typedef struct
{
std::string Name;
std::string Path;
int ROMType;
} AvailableROM;
extern std::vector<AvailableROM*> lstAvailableROMs;
#define MAX_MRU_LIST 40
extern std::vector<std::string> lstMRUDiskList;