WHDLoad and AutoBooter Update (#430)

* Bugfix for 2nd controller selection

* ignore netbeans project

* Add experimental `-autocd=` loading of files (.cue works very well - .iso should also)

* CD Autoloading adapted to include .uae file check and hostconf controller options

* Beginning of Booter Panel implentation

* Booter Panel development .. start on XML reading for picked LHA file

* New WHDLoad booter, included updated boot-data.zip, plus new hostprefs FIXED_HEIGHT= option and bugfixes for XML reading, and symlink ROM scan. Plus updated XML

* Upload of .RTB files that need to accompany the Symlinked Kickstarts, for WHDLoad compatibility.
This commit is contained in:
Horace And The Spider 2019-02-13 09:46:32 +00:00 committed by Dimitris Panokostas
parent 1ca35b4aee
commit 537781e6d3
15 changed files with 1793 additions and 278 deletions

4
.gitignore vendored
View file

@ -19,6 +19,10 @@ CodeDB
*.suo *.suo
*.old *.old
### NetBeans ###
nbproject*
### VSLinux ### ### VSLinux ###
VSLinux/obj VSLinux/obj
VSLinux/bin VSLinux/bin

View file

@ -101,7 +101,15 @@ struct joypad_map_layout {
int dpad_up_action = 0; int dpad_up_action = 0;
int dpad_down_action = 0; int dpad_down_action = 0;
int lstick_select_action = 0; int lstick_select_action = 0;
int lstick_left_action = 0;
int lstick_right_action = 0;
int lstick_up_action = 0;
int lstick_down_action = 0;
int rstick_select_action = 0; int rstick_select_action = 0;
int rstick_left_action = 0;
int rstick_right_action = 0;
int rstick_up_action = 0;
int rstick_down_action = 0;
}; };
#endif #endif
@ -853,6 +861,9 @@ struct uae_prefs {
bool use_retroarch_menu; bool use_retroarch_menu;
bool use_retroarch_reset; bool use_retroarch_reset;
bool use_retroarch_statebuttons; bool use_retroarch_statebuttons;
TCHAR whdload_path[MAX_DPATH];
TCHAR whdload_file[MAX_DPATH];
#endif #endif
/* ANDROID */ /* ANDROID */
@ -980,6 +991,8 @@ extern void cfgfile_compatibility_rtg(struct uae_prefs *p);
extern void whdload_auto_prefs (struct uae_prefs *p, char* filename); extern void whdload_auto_prefs (struct uae_prefs *p, char* filename);
extern void cd_auto_prefs (struct uae_prefs *p, char* filename);
extern void symlink_roms(struct uae_prefs *p);
extern void check_prefs_changed_custom (void); extern void check_prefs_changed_custom (void);

View file

@ -523,6 +523,7 @@ static void parse_cmdline(int argc, TCHAR **argv)
xfree(txt); xfree(txt);
loaded = true; loaded = true;
} }
// for backwards compatibility only - WHDLoading
else if (_tcsncmp(argv[i], _T("-autowhdload="), 13) == 0) { else if (_tcsncmp(argv[i], _T("-autowhdload="), 13) == 0) {
const auto txt = parsetextpath(argv[i] + 13); const auto txt = parsetextpath(argv[i] + 13);
whdload_auto_prefs(&currprefs, txt); whdload_auto_prefs(&currprefs, txt);
@ -530,6 +531,37 @@ static void parse_cmdline(int argc, TCHAR **argv)
firstconfig = false; firstconfig = false;
loaded = true; loaded = true;
} }
// for backwards compatibility only - CDLoading
else if (_tcsncmp(argv[i], _T("-autocd="), 8) == 0) {
const auto txt = parsetextpath(argv[i] + 8);
cd_auto_prefs(&currprefs, txt);
xfree(txt);
firstconfig = false;
loaded = true;
}
// autoload .... .cue / .lha
else if ((_tcsncmp(argv[i], _T("-autoload="), 10) == 0))
{
const auto txt = parsetextpath(argv[i] + 10);
//const auto txt2 = *GetExtension (txt); // Extract the extension from the string (incl '.')
// if (_tcsncmp(_T(txt2), _T("lha"),3) == 0)
// {
// printf("WHDLOAD... %s\n", txt);
// whdload_auto_prefs(&currprefs, txt);
// }
// else if (_tcsncmp(txt2, _T(".cue"),3) == 0)
// {
// printf("CDTV/CD32... %s\n", txt);
cd_auto_prefs(&currprefs, txt);
// }
// else
// {
// printf("Cant find extension ... %s\n", txt);
// }
}
else if (_tcscmp(argv[i], _T("-f")) == 0) { else if (_tcscmp(argv[i], _T("-f")) == 0) {
/* Check for new-style "-f xxx" argument, where xxx is config-file */ /* Check for new-style "-f xxx" argument, where xxx is config-file */
if (i + 1 == argc) { if (i + 1 == argc) {

View file

@ -252,6 +252,10 @@ static void scan_rom(char *path)
zfile_zopen(path, scan_rom_2, 0); zfile_zopen(path, scan_rom_2, 0);
} }
void SymlinkROMs()
{
symlink_roms(&changed_prefs);
}
void RescanROMs() void RescanROMs()
{ {

View file

@ -34,6 +34,7 @@ extern char currentDir[MAX_DPATH];
extern char last_loaded_config[MAX_DPATH]; extern char last_loaded_config[MAX_DPATH];
#include <fstream> /// Horace added #include <fstream> /// Horace added
#include <algorithm>
struct game_options struct game_options
{ {
@ -78,6 +79,7 @@ struct host_options
TCHAR frameskip[256] = "nul\0"; TCHAR frameskip[256] = "nul\0";
TCHAR aspect_ratio[256] = "nul\0"; TCHAR aspect_ratio[256] = "nul\0";
TCHAR line_double[256] = "nul\0"; TCHAR line_double[256] = "nul\0";
TCHAR fixed_height[256] = "nul\0";
}; };
static xmlNode* get_node(xmlNode* node, const char* name) static xmlNode* get_node(xmlNode* node, const char* name)
@ -181,6 +183,9 @@ struct membuf : std::streambuf
} }
}; };
std::string find_whdload_game_option(const TCHAR* find_setting, char* whd_options) std::string find_whdload_game_option(const TCHAR* find_setting, char* whd_options)
{ {
char temp_options[4096]; char temp_options[4096];
@ -190,16 +195,40 @@ std::string find_whdload_game_option(const TCHAR* find_setting, char* whd_option
auto output = "nul"; auto output = "nul";
auto full_line = strtok(temp_options, "\n"); auto full_line = strtok(temp_options, "\n");
while (full_line != nullptr) while (full_line != nullptr)
{ {
std::string t = full_line;
// remove leading tabs
if (full_line[0] == '\t' && full_line[1] == '\t')
{
memmove(full_line, full_line + 2, (sizeof(full_line[0]) - 2) / sizeof(full_line[0]));
}
// remove leading tabs
// for (auto i = 1; i < 5; ++i)
// {
// if (full_line[0] == '\t')
// {
// memmove(full_line, full_line + 1, (sizeof(full_line[0]) - 1) / sizeof(full_line[0]));
// }
// else
// break;
// }
//
std::string t = full_line;
// t.erase(std::remove(t.begin(), t.end(), '\t'), t.end()); // remove tabs
strcpy(temp_setting, find_setting); strcpy(temp_setting, find_setting);
strcat(temp_setting, "="); strcat(temp_setting, "=");
if (strlen(full_line) >= strlen(temp_setting)) if (strlen(full_line) >= strlen(temp_setting))
{ {
// check that the beginging of the full line // check that the beginging of the full line
if (strncmp(temp_setting, full_line, strlen(find_setting)) == 0) // if (strncmp(temp_setting, full_line, strlen(find_setting)) == 0)
if (strncmp(temp_setting, full_line, strlen(temp_setting)) == 0)
{ {
t.erase(t.begin(), t.begin() + strlen(temp_setting)); t.erase(t.begin(), t.begin() + strlen(temp_setting));
return t; return t;
@ -257,7 +286,7 @@ struct host_options get_host_settings(char* HW)
strcpy(output_detail.aspect_ratio, find_whdload_game_option("ASPECT_RATIO_FIX", HW).c_str()); strcpy(output_detail.aspect_ratio, find_whdload_game_option("ASPECT_RATIO_FIX", HW).c_str());
strcpy(output_detail.frameskip, find_whdload_game_option("FRAMESKIP", HW).c_str()); strcpy(output_detail.frameskip, find_whdload_game_option("FRAMESKIP", HW).c_str());
strcpy(output_detail.line_double, find_whdload_game_option("LINE_DOUBLING", HW).c_str()); strcpy(output_detail.line_double, find_whdload_game_option("LINE_DOUBLING", HW).c_str());
strcpy(output_detail.fixed_height, find_whdload_game_option("FIXED_HEIGHT", HW).c_str());
return output_detail; return output_detail;
} }
@ -269,12 +298,18 @@ void make_rom_symlink(const char* kick_short, char* kick_path, int kick_numb, st
// do the checks... // do the checks...
snprintf(kick_long, MAX_DPATH, "%s/%s", kick_path, kick_short); snprintf(kick_long, MAX_DPATH, "%s/%s", kick_path, kick_short);
// this should sort any broken links
my_unlink(kick_long);
if (!zfile_exists(kick_long)) if (!zfile_exists(kick_long))
{ {
roms[0] = kick_numb; // kickstart 1.2 A500 roms[0] = kick_numb; // kickstart 1.2 A500
const auto rom_test = configure_rom(p, roms, 0); // returns 0 or 1 if found or not found const auto rom_test = configure_rom(p, roms, 0); // returns 0 or 1 if found or not found
if (rom_test == 1) if (rom_test == 1)
symlink(p->romfile, kick_long); { symlink(p->romfile, kick_long);
write_log("Making SymLink for Kickstart ROM: %s\n",kick_long);
}
} }
} }
@ -287,6 +322,9 @@ void symlink_roms(struct uae_prefs* p)
char tmp[MAX_DPATH]; char tmp[MAX_DPATH];
char tmp2[MAX_DPATH]; char tmp2[MAX_DPATH];
write_log("SymLink Kickstart ROMs for Booter\n");
// here we can do some checks for Kickstarts we might need to make symlinks for // here we can do some checks for Kickstarts we might need to make symlinks for
strncpy(currentDir, start_path_data, MAX_DPATH); strncpy(currentDir, start_path_data, MAX_DPATH);
@ -334,10 +372,10 @@ void symlink_roms(struct uae_prefs* p)
symlink(tmp, tmp2); symlink(tmp, tmp2);
} }
void cd_auto_prefs(struct uae_prefs* p, char* filepath)
void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
{ {
// setup variables etc // setup variables etc
TCHAR game_name[MAX_DPATH]; TCHAR game_name[MAX_DPATH];
TCHAR* txt2 = nullptr; TCHAR* txt2 = nullptr;
@ -346,28 +384,16 @@ void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
char boot_path[MAX_DPATH]; char boot_path[MAX_DPATH];
char save_path[MAX_DPATH]; char save_path[MAX_DPATH];
char config_path[MAX_DPATH]; char config_path[MAX_DPATH];
// char GameTypePath[MAX_DPATH];
char whd_config[255]; char whd_config[255];
char hardware_settings[4096]; char hardware_settings[4096];
char custom_settings[4096]; //char custom_settings[4096];
fetch_configurationpath(config_path,MAX_DPATH); fetch_configurationpath(config_path,MAX_DPATH);
//
// *** KICKSTARTS ***
symlink_roms(p);
// this allows A600HD to be used to slow games down
int roms[2];
roms[0] = 15; // kickstart 2.05 A600HD .. 10
const auto rom_test = configure_rom(p, roms, 0); // returns 0 or 1 if found or not found
const auto a600_available = rom_test;
//
// *** GAME DETECTION *** // *** GAME DETECTION ***
printf("\nCD Autoload: %s \n\n",filepath);
// REMOVE THE FILE PATH AND EXTENSION // REMOVE THE FILE PATH AND EXTENSION
const auto filename = my_getfilepart(filepath); const auto filename = my_getfilepart(filepath);
// SOMEWHERE HERE WE NEED TO SET THE GAME 'NAME' FOR SAVESTATE ETC PURPOSES // SOMEWHERE HERE WE NEED TO SET THE GAME 'NAME' FOR SAVESTATE ETC PURPOSES
@ -392,11 +418,15 @@ void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
return; return;
} }
// LOAD HOST OPTIONS
char whd_path[MAX_DPATH];
struct host_options host_detail;
snprintf(whd_path, MAX_DPATH, "%s/whdboot/", start_path_data);
// LOAD HOST OPTIONS
char whd_path[MAX_DPATH];
snprintf(whd_path, MAX_DPATH, "%s/whdboot/", start_path_data);
// this should be made into it's own routine!! 1 (see repeat, below)
struct host_options host_detail;
strcpy(whd_config, whd_path); strcpy(whd_config, whd_path);
strcat(whd_config, "hostprefs.conf"); strcat(whd_config, "hostprefs.conf");
@ -409,6 +439,226 @@ void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
_stprintf(hardware_settings, "%s", contents.c_str()); _stprintf(hardware_settings, "%s", contents.c_str());
host_detail = get_host_settings(hardware_settings);
}
//
// *** EMULATED HARDWARE ***
//
p->start_gui = false;
const int is_cdtv = (strstr(filepath, "CD32") != nullptr || strstr(filepath, "cdtv") != nullptr);
const int is_cd32 = (strstr(filepath, "CD32") != nullptr || strstr(filepath, "cd32") != nullptr);
// CD32
if (static_cast<bool>(is_cd32))
{
_tcscpy(p->description, _T("AutoBoot Configuration [CD32]"));
// SET THE BASE AMIGA (CD32)
built_in_prefs(&currprefs, 8, 0, 0, 0);
}
else if (static_cast<bool>(is_cd32))
{
_tcscpy(p->description, _T("AutoBoot Configuration [CDTV]"));
// SET THE BASE AMIGA (CDTV)
built_in_prefs(&currprefs, 9, 0, 0, 0);
}
else
{
_tcscpy(p->description, _T("AutoBoot Configuration [A1200CD]"));
// SET THE BASE AMIGA (Expanded A1200)
built_in_prefs(&currprefs, 4, 1, 0, 0);
}
// enable CD
_stprintf(tmp, "cd32cd=1");
txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0);
// mount the image
_stprintf(tmp, "cdimage0=%s,image", filepath);
txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0);
//cfgfile_parse_option(&currprefs, _T("cdimage0"), filepath, 0);
//APPLY THE SETTINGS FOR MOUSE/JOYSTICK ETC
// CD32
if (static_cast<bool>(is_cd32))
{ p->jports[0].mode = 7;
p->jports[1].mode = 7;
}
else
{
// JOY
p->jports[1].mode = 3;
// MOUSE
p->jports[0].mode = 2;
}
// APPLY SPECIAL CONFIG E.G. MOUSE OR ALT. JOYSTICK SETTINGS
for (auto& jport : p->jports)
{
jport.id = JPORT_NONE;
jport.idc.configname[0] = 0;
jport.idc.name[0] = 0;
jport.idc.shortid[0] = 0;
}
// WHAT IS THE MAIN CONTROL?
// PORT 0 - MOUSE
if (static_cast<bool>(is_cd32) && !strcmpi(host_detail.controller2, "nul") == 0)
{
_stprintf(txt2, "%s=%s", _T("joyport0"), _T(host_detail.controller2));
cfgfile_parse_line(p, txt2, 0);
}
else if (!strcmpi(host_detail.mouse1, "nul") == 0)
{
_stprintf(txt2, "%s=%s", _T("joyport0"), _T(host_detail.mouse1));
cfgfile_parse_line(p, txt2, 0);
}
else
{
_stprintf(txt2, "%s=mouse", _T("joyport0"));
cfgfile_parse_line(p, txt2, 0);
}
// PORT 1 - JOYSTICK
if (!strcmpi(host_detail.controller1, "nul") == 0)
{
_stprintf(txt2, "%s=%s", _T("joyport1"), _T(host_detail.controller1));
cfgfile_parse_line(p, txt2, 0);
}
else
{
_stprintf(txt2, "%s=joy1", _T("joyport1"));
cfgfile_parse_line(p, txt2, 0);
}
}
void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
{
// setup variables etc
TCHAR game_name[MAX_DPATH];
TCHAR* txt2 = nullptr;
TCHAR tmp[MAX_DPATH];
char boot_path[MAX_DPATH];
char save_path[MAX_DPATH];
char config_path[MAX_DPATH];
char whd_path[MAX_DPATH];
char kick_path[MAX_DPATH];
// char GameTypePath[MAX_DPATH];
char whd_config[255];
char whd_startup[255];
char whd_bootscript[4096];
char hardware_settings[4096];
char custom_settings[4096];
char selected_slave[4096]; // note!! this should be global later on, and only collected from the XML if set to 'nothing'
char subpath[4096];
strcpy(selected_slave, "");
fetch_configurationpath(config_path,MAX_DPATH);
//
// *** KICKSTARTS ***
symlink_roms(p);
// this allows A600HD to be used to slow games down
int roms[2];
roms[0] = 15; // kickstart 2.05 A600HD .. 10
const auto rom_test = configure_rom(p, roms, 0); // returns 0 or 1 if found or not found
const auto a600_available = rom_test;
if (a600_available == true)
{
write_log("WHDBooter - Host: A600 ROM Available \n");
}
//
// *** GAME DETECTION ***
// REMOVE THE FILE PATH AND EXTENSION
const auto filename = my_getfilepart(filepath);
// SOMEWHERE HERE WE NEED TO SET THE GAME 'NAME' FOR SAVESTATE ETC PURPOSES
extractFileName(filepath, last_loaded_config);
extractFileName(filepath, game_name);
removeFileExtension(game_name);
auto filesize = get_file_size(filepath);
// const TCHAR* filesha = get_sha1_txt (input, filesize); <<< ??! FIX ME
// LOAD GAME SPECIFICS FOR EXISTING .UAE - USE SHA1 IF AVAILABLE
// CONFIG LOAD IF .UAE IS IN CONFIG PATH
strcpy(whd_config, config_path);
strcat(whd_config, game_name);
strcat(whd_config, ".uae");
snprintf(whd_path, MAX_DPATH, "%s/whdboot/save-data/Autoboots/", start_path_data);
strcpy(whd_startup, whd_path);
strcat(whd_startup, game_name);
strcat(whd_startup, ".auto-startup");
my_mkdir("/tmp/s");
my_mkdir("/tmp/c");
my_mkdir("/tmp/devs");
remove("/tmp/s/startup-sequence");
my_unlink("/tmp/s/startup-sequence");
// LOAD HOST OPTIONS
snprintf(whd_path, MAX_DPATH, "%s/whdboot/WHDLoad", start_path_data);
// are we using save-data/ ?
snprintf(kick_path, MAX_DPATH, "%s/whdboot/save-data/Kickstarts", start_path_data);
// boot with existing .UAE if possible, but for this the auto-startup must exist
if (zfile_exists(whd_config) && zfile_exists(whd_startup))
{
symlink(whd_startup, "/tmp/s/startup-sequence");
symlink(whd_path, "/tmp/c/WHDLoad");
symlink(kick_path, "/tmp/devs/Kickstarts");
target_cfgfile_load(&currprefs, whd_config, CONFIG_TYPE_ALL, 0);
return;
}
// this should be made into it's own routine!! 1 (see repeat, above)
snprintf(whd_path, MAX_DPATH, "%s/whdboot/", start_path_data);
struct host_options host_detail;
strcpy(whd_config, whd_path);
strcat(whd_config, "hostprefs.conf");
if (zfile_exists(whd_config)) // use hostprefs
{
ifstream read_file(whd_config);
std::ifstream in(whd_config);
std::string contents((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
_stprintf(hardware_settings, "%s", contents.c_str());
host_detail = get_host_settings(hardware_settings); host_detail = get_host_settings(hardware_settings);
} }
@ -419,117 +669,173 @@ void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
// EDIT THE FILE NAME TO USE HERE // EDIT THE FILE NAME TO USE HERE
strcpy(whd_config, whd_path);
strcat(whd_config, game_name); strcpy(whd_config, whd_path);
strcat(whd_config, ".whd"); strcat(whd_config, "whdload_db.xml");
if (zfile_exists(whd_config)) // use XML database
{
//printf("XML exists %s\n",game_name);
const auto doc = xmlParseFile(whd_config);
const auto root_element = xmlDocGetRootElement(doc);
auto game_node = get_node(root_element, "whdbooter");
while (game_node != nullptr)
{
const auto attr = xmlGetProp(game_node, reinterpret_cast<const xmlChar *>("filename"));
if (attr != nullptr)
{
if (strcmpi(reinterpret_cast<const char*>(attr),game_name) == 0)
{
// now get the <hardware> and <custom_controls> items
// get hardware
auto temp_node = game_node->xmlChildrenNode;
temp_node = get_node(temp_node, "hardware");
if (xmlNodeGetContent(temp_node) != nullptr)
{
_stprintf(hardware_settings, "%s",
reinterpret_cast<const char*>(xmlNodeGetContent(temp_node)));
game_detail = get_game_settings(hardware_settings);
write_log("WHDBooter - Game H/W Settings: \n%s\n",hardware_settings);
}
// get custom controls
temp_node = game_node->xmlChildrenNode;
temp_node = get_node(temp_node, "custom_controls");
if (xmlNodeGetContent(temp_node) != nullptr)
{
_stprintf(custom_settings, "%s",
reinterpret_cast<const char*>(xmlNodeGetContent(temp_node)));
// process these later
}
// if selected_slave = "" then use the default from the XML....
if (strlen(selected_slave) == 0)
{
temp_node = game_node->xmlChildrenNode;
temp_node = get_node(temp_node, "slave_default");
if (xmlNodeGetContent(temp_node) != nullptr)
{
_stprintf(selected_slave, "%s",
reinterpret_cast<const char*>(xmlNodeGetContent(temp_node)));
// process these later
write_log("WHDBooter - Default Slave: %s\n",selected_slave);
}
temp_node = game_node->xmlChildrenNode;
temp_node = get_node(temp_node, "subpath");
if (xmlNodeGetContent(temp_node) != nullptr)
{
_stprintf(subpath, "%s",
reinterpret_cast<const char*>(xmlNodeGetContent(temp_node)));
// process these later
write_log("WHDBooter - SubPath: %s\n",subpath);
}
temp_node = game_node->xmlChildrenNode;
printf("temp node: %s\n",temp_node);
}
break;
}
}
xmlFree(attr);
game_node = game_node->next;
}
xmlCleanupParser();
}
if (zfile_exists(whd_config)) // use direct .whd file //printf("selected_slave: %s\n",selected_slave);
{
ifstream readFile(whd_config); // then here, we will write a startup-sequence file (formerly autoboot file)
std::ifstream in(whd_config); if (strlen(selected_slave) != 0 && !zfile_exists(whd_startup))
std::string contents((std::istreambuf_iterator<char>(in)), {
std::istreambuf_iterator<char>()); // _stprintf(whd_bootscript, "DH3:C/Assign C: DH3:C/ ADD\n");
// _stprintf(whd_bootscript, "DH3:C/Assign LIBS: DH3:LIBS/ ADD\n");
_stprintf(whd_bootscript, "CD \"Games:%s\"\n",subpath);
_stprintf(whd_bootscript, "%sWHDLoad SLAVE=\"games:%s/%s\"",whd_bootscript,subpath,selected_slave);
_stprintf(whd_bootscript, "%s PRELOAD NOWRITECACHE NOREQ SPLASHDELAY=0",whd_bootscript);
_stprintf(whd_bootscript, "%s SAVEPATH=Saves:Savegames/ SAVEDIR=\"%s\"",whd_bootscript,subpath);
_stprintf(whd_bootscript, "%s\n",whd_bootscript,subpath);
write_log("WHDBooter - Created Startup-Sequence \n\n%s\n",whd_bootscript);
// create a file with save-data/Autoboots/ game name .auto-startup
_stprintf(hardware_settings, "%s", contents.c_str()); write_log("WHDBooter - Saved Auto-Startup to %s\n",whd_startup);
game_detail = get_game_settings(hardware_settings);
} ofstream myfile (whd_startup);
else if (myfile.is_open())
{ {
strcpy(whd_config, whd_path); myfile << whd_bootscript;
strcat(whd_config, "whdload_db.xml"); myfile.close();
}
}
// now we should have a startup-file (if we dont, we are going to use the orignal booter)
if (zfile_exists(whd_startup))
{
write_log("WHDBooter - Found Auto-Startup to SymLink\n");
// create a symlink to this as startup-sequence in /tmp/
symlink(whd_startup, "/tmp/s/startup-sequence");
if (zfile_exists(whd_config)) // use XML database // create a symlink to WHDLoad in /tmp/
{ snprintf(whd_path, MAX_DPATH, "%s/whdboot/WHDLoad", start_path_data);
//printf("XML exists %s\n",game_name); symlink(whd_path, "/tmp/c/WHDLoad");
const auto doc = xmlParseFile(whd_config); // create a symlink for DEVS in /tmp/
const auto root_element = xmlDocGetRootElement(doc); symlink(kick_path, "/tmp/devs/Kickstarts");
auto game_node = get_node(root_element, "whdbooter"); }
while (game_node != nullptr)
{ // debugging code!
const auto attr = xmlGetProp(game_node, reinterpret_cast<const xmlChar *>("filename")); write_log("WHDBooter - Game: Port 0 : %s \n",game_detail.port0);
if (attr != nullptr) write_log("WHDBooter - Game: Port 1 : %s \n",game_detail.port1);
{ write_log("WHDBooter - Game: Control : %s \n",game_detail.control);
// printf ("%s\n",attr); write_log("WHDBooter - Game: Fast Copper: %s \n",game_detail.fastcopper);
if (strcmpi(reinterpret_cast<const char*>(attr),game_name) == 0) write_log("WHDBooter - Game: CPU : %s \n",game_detail.cpu);
{ write_log("WHDBooter - Game: Blitter : %s \n",game_detail.blitter);
// now get the <hardware> and <custom_controls> items write_log("WHDBooter - Game: CPU Clock : %s \n",game_detail.clock);
write_log("WHDBooter - Game: Chipset : %s \n",game_detail.chipset);
//printf("found game in XML\n"); write_log("WHDBooter - Game: JIT : %s \n",game_detail.jit);
auto temp_node = game_node->xmlChildrenNode; write_log("WHDBooter - Game: CPU Compat : %s \n",game_detail.cpu_comp);
temp_node = get_node(temp_node, "hardware"); write_log("WHDBooter - Game: Scr Height : %s \n",game_detail.scr_height);
if (xmlNodeGetContent(temp_node) != nullptr) write_log("WHDBooter - Game: Scr YOffset: %s \n",game_detail.y_offset);
{ write_log("WHDBooter - Game: NTSC : %s \n",game_detail.ntsc);
_stprintf(hardware_settings, "%s", write_log("WHDBooter - Game: Fast Ram : %s \n",game_detail.fast);
reinterpret_cast<const char*>(xmlNodeGetContent(temp_node))); write_log("WHDBooter - Game: Z3 Ram : %s \n",game_detail.z3);
// printf("%s\n",hardware_settings);
game_detail = get_game_settings(hardware_settings);
}
temp_node = game_node->xmlChildrenNode;
temp_node = get_node(temp_node, "custom_controls");
if (xmlNodeGetContent(temp_node) != nullptr)
{
_stprintf(custom_settings, "%s",
reinterpret_cast<const char*>(xmlNodeGetContent(temp_node)));
// process these later
//printf("%s\n",custom_settings);
}
break;
}
}
xmlFree(attr);
game_node = game_node->next;
}
xmlCleanupParser();
}
}
// debugging code! // debugging code!
write_log("WHDBooter - Game: Port 0: %s \n",game_detail.port0); write_log("WHDBooter - Host: Controller 1 : %s \n", host_detail.controller1);
write_log("WHDBooter - Game: Port 1: %s \n",game_detail.port1); write_log("WHDBooter - Host: Controller 2 : %s \n", host_detail.controller2);
write_log("WHDBooter - Game: Control: %s \n",game_detail.control); write_log("WHDBooter - Host: Controller 3 : %s \n", host_detail.controller3);
// printf("fstcpr: %s \n",game_detail.fastcopper); write_log("WHDBooter - Host: Controller 4 : %s \n", host_detail.controller4);
// printf("cpu : %s \n",game_detail.cpu); write_log("WHDBooter - Host: Mouse 1 : %s \n", host_detail.mouse1);
// printf("blitta: %s \n",game_detail.blitter); write_log("WHDBooter - Host: Mouse 2 : %s \n", host_detail.mouse2);
// printf("clock : %s \n",game_detail.clock);
// printf("chipst: %s \n",game_detail.chipset);
// printf("jit : %s \n",game_detail.jit);
// printf("cpcomp: %s \n",game_detail.cpu_comp);
// printf("scrhei: %s \n",game_detail.scr_height);
// printf("scr y : %s \n",game_detail.y_offset);
// printf("ntsc : %s \n",game_detail.ntsc);
// printf("fast : %s \n",game_detail.fast);
// printf("z3 : %s \n",game_detail.z3);
// debugging code!
write_log("WHDBooter - Host: Controller 1: %s \n", host_detail.controller1);
write_log("WHDBooter - Host: Controller 2: %s \n", host_detail.controller2);
write_log("WHDBooter - Host: Controller 3: %s \n", host_detail.controller3);
write_log("WHDBooter - Host: Controller 4: %s \n", host_detail.controller4);
write_log("WHDBooter - Host: Mouse 1: %s \n", host_detail.mouse1);
write_log("WHDBooter - Host: Mouse 2: %s \n", host_detail.mouse2);
//printf("ra_qui: %s \n", host_detail.ra_quit); //printf("ra_qui: %s \n", host_detail.ra_quit);
//printf("ra_men: %s \n", host_detail.ra_menu); //printf("ra_men: %s \n", host_detail.ra_menu);
//printf("ra_rst: %s \n", host_detail.ra_reset); //printf("ra_rst: %s \n", host_detail.ra_reset);
//printf("ky_qut: %s \n", host_detail.key_quit); //printf("ky_qut: %s \n", host_detail.key_quit);
//printf("ky_gui: %s \n", host_detail.key_gui); //printf("ky_gui: %s \n", host_detail.key_gui);
//printf("deadzn: %s \n", host_detail.stereo_split); //printf("deadzn: %s \n", host_detail.stereo_split);
//printf("stereo: %s \n", host_detail.stereo_split); write_log("WHDBooter - Host: Sound On : %s \n", host_detail.sound_on);
//printf("snd_on: %s \n", host_detail.sound_on); write_log("WHDBooter - Host: Sound Mode : %s \n", host_detail.sound_mode);
//printf("snd_md: %s \n", host_detail.sound_mode); write_log("WHDBooter - Host: Stereo Split : %s \n", host_detail.stereo_split);
//printf("aspect: %s \n", host_detail.aspect_ratio); //printf("aspect: %s \n", host_detail.aspect_ratio);
//printf("frames: %s \n", host_detail.frameskip); //printf("frames: %s \n", host_detail.frameskip);
write_log("WHDBooter - Host: Fixed Height : %s \n", host_detail.fixed_height);
// //
// *** EMULATED HARDWARE *** // *** EMULATED HARDWARE ***
// //
// SET UNIVERSAL DEFAULTS
// SET UNIVERSAL DEFAULTS
p->start_gui = false; p->start_gui = false;
if ((strcmpi(game_detail.cpu,"68000") == 0 || strcmpi(game_detail.cpu,"68010") == 0) && a600_available != 0) if ((strcmpi(game_detail.cpu,"68000") == 0 || strcmpi(game_detail.cpu,"68010") == 0) && a600_available != 0)
@ -552,7 +858,7 @@ void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
// A1200 no AGA // A1200 no AGA
if (!static_cast<bool>(is_aga) && !static_cast<bool>(is_cd32)) if (!static_cast<bool>(is_aga) && !static_cast<bool>(is_cd32))
{ {
_tcscpy(p->description, _T("WHDLoad AutoBoot Configuration")); _tcscpy(p->description, _T("AutoBoot Configuration [WHDLoad]"));
p->cs_compatible = CP_A600; p->cs_compatible = CP_A600;
built_in_chipset_prefs(p); built_in_chipset_prefs(p);
@ -561,49 +867,81 @@ void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
} }
// A1200 // A1200
else else
_tcscpy(p->description, _T("WHDLoad AutoBoot Configuration [AGA]")); _tcscpy(p->description, _T("AutoBoot Configuration [WHDLoad] [AGA]"));
//SET THE WHD BOOTER AND GAME DATA
snprintf(boot_path, MAX_DPATH, "%s/whdboot/boot-data.zip", start_path_data);
//SET THE WHD BOOTER AND GAME DATA
if (strlen(selected_slave) != 0) // new booter solution
{
snprintf(boot_path, MAX_DPATH, "/tmp/");
if (!zfile_exists(boot_path)) _stprintf(tmp,_T("filesystem2=rw,DH0:DH0:%s,10"), boot_path);
snprintf(boot_path, MAX_DPATH, "%s/whdboot/boot-data/", start_path_data); txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0);
_stprintf(tmp,_T("uaehf0=dir,rw,DH0:DH0::%s,10"), boot_path);
txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0);
snprintf(boot_path, MAX_DPATH, "%s/whdboot/boot-data.zip", start_path_data);
if (!zfile_exists(boot_path))
snprintf(boot_path, MAX_DPATH, "%s/whdboot/boot-data/", start_path_data);
// set the first (whdboot) Drive _stprintf(tmp,_T("filesystem2=rw,DH3:DH3:%s,-10"), boot_path);
_stprintf(tmp,_T("filesystem2=rw,DH0:DH0:%s,10"), boot_path); txt2 = parsetextpath(_T(tmp));
txt2 = parsetextpath(_T(tmp)); cfgfile_parse_line(p, txt2, 0);
cfgfile_parse_line(p, txt2, 0);
_stprintf(tmp,_T("uaehf0=dir,rw,DH0:DH0::%s,10"), boot_path); _stprintf(tmp,_T("uaehf0=dir,rw,DH3:DH3::%s,-10"), boot_path);
txt2 = parsetextpath(_T(tmp)); txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0); cfgfile_parse_line(p, txt2, 0);
}
else // revert to original booter is no slave was set
{
snprintf(boot_path, MAX_DPATH, "%s/whdboot/boot-data.zip", start_path_data);
if (!zfile_exists(boot_path))
snprintf(boot_path, MAX_DPATH, "%s/whdboot/boot-data/", start_path_data);
_stprintf(tmp,_T("filesystem2=rw,DH0:DH0:%s,10"), boot_path);
txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0);
_stprintf(tmp,_T("uaehf0=dir,rw,DH0:DH0::%s,10"), boot_path);
txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0);
}
//set the Second (game data) drive //set the Second (game data) drive
_stprintf(tmp, "filesystem2=rw,DH1:games:%s,0", filepath); _stprintf(tmp, "filesystem2=rw,DH1:Games:%s,0", filepath);
txt2 = parsetextpath(_T(tmp)); txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0); cfgfile_parse_line(p, txt2, 0);
_stprintf(tmp, "uaehf1=dir,rw,DH1:games:%s,0", filepath); _stprintf(tmp, "uaehf1=dir,rw,DH1:Games:%s,0", filepath);
txt2 = parsetextpath(_T(tmp)); txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0); cfgfile_parse_line(p, txt2, 0);
//set the third (save data) drive //set the third (save data) drive
snprintf(save_path, MAX_DPATH, "%s/whdboot/save-data/", start_path_data); snprintf(save_path, MAX_DPATH, "%s/whdboot/save-data/", start_path_data);
if (my_existsdir(save_path)) if (my_existsdir(save_path))
{ {
_stprintf(tmp, "filesystem2=rw,DH2:saves:%s,0", save_path); _stprintf(tmp, "filesystem2=rw,DH2:Saves:%s,0", save_path);
txt2 = parsetextpath(_T(tmp)); txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0); cfgfile_parse_line(p, txt2, 0);
_stprintf(tmp, "uaehf2=dir,rw,DH2:saves:%s,0", save_path); _stprintf(tmp, "uaehf2=dir,rw,DH2:Saves:%s,0", save_path);
txt2 = parsetextpath(_T(tmp)); txt2 = parsetextpath(_T(tmp));
cfgfile_parse_line(p, txt2, 0); cfgfile_parse_line(p, txt2, 0);
} }
//APPLY THE SETTINGS FOR MOUSE/JOYSTICK ETC
// CD32 // APPLY THE SETTINGS FOR MOUSE/JOYSTICK ETC
// CD32
if ((static_cast<bool>(is_cd32) && strcmpi(game_detail.port0, "nul") == 0) if ((static_cast<bool>(is_cd32) && strcmpi(game_detail.port0, "nul") == 0)
|| strcmpi(game_detail.port0, "cd32") == 0) || strcmpi(game_detail.port0, "cd32") == 0)
p->jports[0].mode = 7; p->jports[0].mode = 7;
@ -913,15 +1251,19 @@ void whdload_auto_prefs(struct uae_prefs* p, char* filepath)
cfgfile_parse_line(p, txt2, 0); cfgfile_parse_line(p, txt2, 0);
} }
// NTSC
if (strcmpi(game_detail.ntsc,"true") == 0)
{
_stprintf(txt2, "ntsc=true");
cfgfile_parse_line(p, txt2, 0);
}
// SCREEN HEIGHT
if (strcmpi(game_detail.scr_height,"nul") != 0)
if (strcmpi(host_detail.fixed_height,"nul") != 0)
{
_stprintf(txt2, "gfx_height=%s", host_detail.fixed_height);
cfgfile_parse_line(p, txt2, 0);
_stprintf(txt2, "gfx_height_windowed=%s", host_detail.fixed_height);
cfgfile_parse_line(p, txt2, 0);
_stprintf(txt2, "gfx_height_fullscreen=%s", host_detail.fixed_height);
cfgfile_parse_line(p, txt2, 0);
}
else if (strcmpi(game_detail.scr_height,"nul") != 0)
{ {
_stprintf(txt2, "gfx_height=%s", game_detail.scr_height); _stprintf(txt2, "gfx_height=%s", game_detail.scr_height);
cfgfile_parse_line(p, txt2, 0); cfgfile_parse_line(p, txt2, 0);

View file

@ -100,6 +100,8 @@ public:
void action(const gcn::ActionEvent& actionEvent) override void action(const gcn::ActionEvent& actionEvent) override
{ {
RescanROMs(); RescanROMs();
SymlinkROMs();
import_joysticks(); import_joysticks();
RefreshPanelInput(); RefreshPanelInput();
RefreshPanelCustom(); RefreshPanelCustom();

View file

@ -68,6 +68,7 @@ extern void extractPath(char *str, char *buffer);
extern void removeFileExtension(char *filename); extern void removeFileExtension(char *filename);
extern void ReadConfigFileList(void); extern void ReadConfigFileList(void);
extern void RescanROMs(void); extern void RescanROMs(void);
extern void SymlinkROMs(void);
extern void ClearAvailableROMList(void); extern void ClearAvailableROMList(void);
#include <vector> #include <vector>

BIN
whdboot/boot-data.zip Normal file → Executable file

Binary file not shown.

File diff suppressed because it is too large Load diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.