summaryrefslogtreecommitdiffstats
path: root/docs/release/src/osd/winui/history.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docs/release/src/osd/winui/history.cpp')
-rw-r--r--docs/release/src/osd/winui/history.cpp346
1 files changed, 272 insertions, 74 deletions
diff --git a/docs/release/src/osd/winui/history.cpp b/docs/release/src/osd/winui/history.cpp
index b4cdfe718f6..2e222129bdd 100644
--- a/docs/release/src/osd/winui/history.cpp
+++ b/docs/release/src/osd/winui/history.cpp
@@ -23,6 +23,12 @@
* - Each table must contain at least MAX_HFILES members (extra lines
* are ignored)
* - Software comes first, followed by Game then Source.
+
+ * 2023-06: Robbbert
+ * - Added support for history.xml
+ * - Dropped support for history.dat
+ * - HBMAME: Dropped support for messinfo.dat, sysinfo.dat, story.dat, marp.dat
+
***************************************************************************/
// license:BSD-3-Clause
// copyright-holders:Chris Kirmse, Mike Haaland, René Single, Mamesick, Robbbert
@@ -39,6 +45,7 @@
#include "mui_opts.h"
#include "emu_opts.h"
#include "sound/samples.h"
+#include "path.h"
/****************************************************************************
@@ -63,39 +70,27 @@ HSOURCEINFO;
/*************************** START CONFIGURABLE AREA *******************************/
// number of dats we support
-#define MAX_HFILES 8
+#define MAX_HFILES 4
// The order of these is the order they are displayed
const HGAMEINFO m_gameInfo[MAX_HFILES] =
{
- { "history.dat", "\n**** :HISTORY: ****\n\n", "$bio", 1 },
- { "sysinfo.dat", "\n**** :SYSINFO: ****\n\n", "$bio", 1 },
- { "messinfo.dat", "\n**** :MESSINFO: ****\n\n", "$mame", 1 },
+ { "history.xml", "\n**** :HISTORY: ****\n\n", "<text>", 1 },
{ "mameinfo.dat", "\n**** :MAMEINFO: ****\n\n", "$mame", 1 },
{ "gameinit.dat", "\n**** :GAMEINIT: ****\n\n", "$mame", 1 },
{ "command.dat", "\n**** :COMMANDS: ****\n\n", "$cmd", 1 },
- { "story.dat", "\n**** :HIGH SCORES: ****\n\n", "$story", 0 },
- { "marp.dat", "\n**** :MARP HIGH SCORES: ****\n\n", "$marp", 0 },
};
const HSOURCEINFO m_sourceInfo[MAX_HFILES] =
{
{ NULL },
- { NULL },
- { "messinfo.dat", "\n***:MESSINFO DRIVER: ", "$drv" },
{ "mameinfo.dat", "\n***:MAMEINFO DRIVER: ", "$drv" },
{ NULL },
{ NULL },
- { NULL },
- { NULL },
};
const HSOURCEINFO m_swInfo[MAX_HFILES] =
{
- { "history.dat", "\n**** :HISTORY item: ", "$bio" },
- { NULL },
- { NULL },
- { NULL },
- { NULL },
+ { "history.xml", "\n**** :HISTORY item: ", "<text>" },
{ NULL },
{ NULL },
{ NULL },
@@ -105,8 +100,125 @@ const HSOURCEINFO m_swInfo[MAX_HFILES] =
int file_sizes[MAX_HFILES] = { 0, };
std::map<std::string, std::streampos> mymap[MAX_HFILES];
+const size_t npos = std::string::npos;
-static bool create_index(std::ifstream &fp, int filenum)
+static void create_index_history(const char* datsdir, std::ifstream &fp, std::string file_line, int filenum)
+{
+ int what_to_do = 0; // 0 = xml not found; 1 = idx not found or version mismatch; 2 = both ok, need to read idx.
+ const std::string text1 = "<system name=", text4 = "\"";
+ std::string xml_ver, idx_ver;
+ size_t quot1 = npos, quot2 = npos;
+
+ if (!fp.good())
+ return; // xml not found
+ // get version from line 2
+ std::getline(fp, file_line);
+ quot1 = file_line.find(text4);
+ if (quot1 != npos)
+ {
+ quot1++;
+ quot2 = file_line.find(text4, quot1);
+ if (quot2 != npos)
+ {
+ xml_ver = file_line.substr(quot1, quot2-quot1);
+ //printf("XML-VER = %s\n",xml_ver.c_str());fflush(stdout);
+ }
+ }
+
+ std::string buf, filename = datsdir + std::string("\\history.idx");
+ std::ifstream fi (filename);
+ if (!fi.good())
+ what_to_do = 1; // idx not found
+ else
+ // get version from line 1
+ {
+ std::getline(fi, idx_ver);
+ //printf("IDX-VER = %s\n",idx_ver.c_str());fflush(stdout);
+ if (xml_ver == idx_ver)
+ what_to_do = 2;
+ }
+
+ //printf("*******2 %d\n",what_to_do);fflush(stdout);
+ // 2: just read idx into map
+ if (what_to_do == 2)
+ {
+ std::getline(fi, file_line);
+ while (fi.good())
+ {
+ quot1 = file_line.find("=");
+ //std::string t4 = file_line.substr(0, quot1);printf("*** %s\n",t4.c_str());fflush(stdout);
+ //u32 t5 = stoi(file_line.substr(quot1+1));printf("*** %d\n",t5);fflush(stdout);
+ mymap[filenum][file_line.substr(0, quot1)] = stoi(file_line.substr(quot1+1));
+ std::getline(fi, file_line);
+ }
+ fi.close();
+ return;
+ }
+
+ // 1: create idx then save it
+ fi.close();
+ std::streampos key_position = file_line.size() + 2, text_position = 0U; // tellg is buggy, this works and is faster
+ while (fp.good())
+ {
+ size_t find = file_line.find(text1);
+ std::string final_key;
+ if (find != npos) // found a system
+ {
+ // Find position of the 2 double-quotes
+ quot1 = file_line.find(text4);
+ if (quot1 != npos)
+ {
+ quot1++;
+ quot2 = file_line.find(text4, quot1);
+ if (quot2 != npos)
+ final_key = file_line.substr(quot1, quot2-quot1);
+ }
+ }
+ // If we passed the tests we now have the key, find the next text
+ if (!final_key.empty())
+ {
+ bool found = false;
+ if (key_position > text_position) // else new key uses the same text as last time
+ {
+ // look for next text
+ text_position = key_position; // set to actual fp
+ for (;found == false;)
+ {
+ std::getline(fp, file_line);
+ find = file_line.find("<text>");
+ if (find != npos)
+ {
+ found = true;
+ text_position += (find+6);
+ }
+ else
+ text_position += (file_line.size() + 2);
+ }
+ }
+ // Save info
+ mymap[filenum][final_key] = text_position;
+ }
+ fp.seekg(key_position);
+ std::getline(fp, file_line);
+ key_position += (file_line.size() + 2);
+ }
+
+ // Save idx
+ FILE *f = fopen(filename.c_str(), "w");
+ if (f == NULL)
+ {
+ printf("Unable to open history.idx for writing.\n");
+ return;
+ }
+
+ fprintf(f, "%s\n",xml_ver.c_str());
+ for (auto const &it : mymap[filenum])
+ fprintf(f, "%s=%d\n", it.first.c_str(), int(it.second));
+ fclose(f);
+
+}
+
+static bool create_index(const char* datsdir, std::ifstream &fp, int filenum)
{
if (!fp.good())
return false;
@@ -120,41 +232,103 @@ static bool create_index(std::ifstream &fp, int filenum)
mymap[filenum].clear();
file_sizes[filenum] = file_size;
fp.seekg(0);
- std::string file_line, first, second;
+ std::string file_line;
std::getline(fp, file_line);
- int position = file_line.size() + 2; // tellg is buggy, this works and is faster
- while (fp.good())
+ if (filenum == 0)
+ create_index_history(datsdir, fp, file_line, filenum);
+ else
{
- char t1 = file_line[0];
- if ((std::count(file_line.begin(),file_line.end(),'=') == 1) && (t1 == '$')) // line must start with $ and contain one =
+ std::streampos position = file_line.size() + 2; // tellg is buggy, this works and is faster
+ while (fp.good())
{
- // now start by removing all spaces
- file_line.erase(remove_if(file_line.begin(), file_line.end(), ::isspace), file_line.end());
- char s[file_line.length()+1];
- strcpy(s, file_line.c_str());
-
- const char* first = strtok(s, "="); // get first part of key
- char* second = strtok(NULL, ","); // get second part
- while (second)
+ if (file_line.find("$info=")==0)
{
- // store into index
- mymap[filenum][std::string(first) + std::string("=") + std::string(second)] = position;
- second = strtok(NULL, ",");
+ // now start by removing all spaces
+ file_line.erase(remove_if(file_line.begin(), file_line.end(), ::isspace), file_line.end());
+ file_line.erase(0,6);
+ size_t t1 = npos;
+ while (file_line.length() > 0)
+ {
+ t1 = file_line.find(",");
+ // store into index
+ mymap[filenum][file_line.substr(0, t1)] = position;
+ if (t1 == npos)
+ file_line.erase();
+ else
+ file_line.erase(0, t1+1); // erase key and comma
+ }
}
+ std::getline(fp, file_line);
+ position += (file_line.size() + 2);
}
- std::getline(fp, file_line);
- position += (file_line.size() + 2);
}
// check contents
-// if (filenum == 0)
-// for (auto const &it : mymap[filenum])
-// printf("%s = %X\n", it.first.c_str(), int(it.second));
+// if (filenum == 6)
+// for (auto const &it : mymap[filenum])
+// printf("%s = %X\n", it.first.c_str(), int(it.second));
return true;
}
+static std::string convert_xml(std::string buf)
+{
+ // convert xml to real chars
+ if (!buf.empty())
+ {
+ bool found = false;
+ size_t find = 0;
+ for (; found == false;)
+ {
+ find = buf.find("&amp;");
+ if (find != npos)
+ buf.replace(find,5,"&");
+ else
+ found = true;
+ }
+ found = false;
+ for (; found == false;)
+ {
+ find = buf.find("&apos;");
+ if (find != npos)
+ buf.replace(find,6,"\'");
+ else
+ found = true;
+ }
+ found = false;
+ for (; found == false;)
+ {
+ find = buf.find("&quot;");
+ if (find != npos)
+ buf.replace(find,6,"\"");
+ else
+ found = true;
+ }
+ found = false;
+ for (; found == false;)
+ {
+ find = buf.find("&lt;");
+ if (find != npos)
+ buf.replace(find,4,"<");
+ else
+ found = true;
+ }
+ found = false;
+ for (; found == false;)
+ {
+ find = buf.find("&gt;");
+ if (find != npos)
+ buf.replace(find,4,">");
+ else
+ found = true;
+ }
+ }
+ return buf;
+}
+
+std::string readbuf;
+
static std::string load_datafile_text(std::ifstream &fp, std::string keycode, int filenum, const char *tag)
{
- std::string readbuf;
+ readbuf.clear();
auto search = mymap[filenum].find(keycode);
if (search != mymap[filenum].end())
@@ -163,13 +337,19 @@ static std::string load_datafile_text(std::ifstream &fp, std::string keycode, in
fp.seekg(offset);
std::string file_line;
- /* read text until buffer is full or end of entry is encountered */
+ // read text until buffer is full or end of entry is encountered
while (std::getline(fp, file_line))
{
- //printf("%s\n",file_line.c_str());
+ //if (filenum == 6) ("*******2: %s\n",file_line.c_str());
+ if (file_line == "- CONTRIBUTE -")
+ break;
+
if (file_line.find("$end")==0)
break;
+ if (file_line.find("</text>") != npos)
+ break;
+
if (file_line.find(tag)==0)
continue;
@@ -180,9 +360,11 @@ static std::string load_datafile_text(std::ifstream &fp, std::string keycode, in
return readbuf;
}
+std::string buffer;
+
std::string load_swinfo(const game_driver *drv, const char* datsdir, std::string software, int filenum)
{
- std::string buffer;
+ buffer.clear();
// if it's a NULL record exit now
if (!m_swInfo[filenum].filename)
return buffer;
@@ -191,15 +373,13 @@ std::string load_swinfo(const game_driver *drv, const char* datsdir, std::string
std::string buf, filename = datsdir + std::string("\\") + m_swInfo[filenum].filename;
std::ifstream fp (filename);
- /* try to open datafile */
- if (create_index(fp, filenum))
+ // try to open datafile
+ if (create_index(datsdir, fp, filenum))
{
size_t i = software.find(":");
- std::string ssys = software.substr(0, i);
std::string ssoft = software.substr(i+1);
- std::string first = std::string("$") + ssys + std::string("=") + ssoft;
// get info on software
- buf = load_datafile_text(fp, first, filenum, m_swInfo[filenum].descriptor);
+ buf = load_datafile_text(fp, software, filenum, m_swInfo[filenum].descriptor);
if (!buf.empty())
buffer.append(m_swInfo[filenum].header).append(ssoft).append("\n").append(buf).append("\n\n\n");
@@ -207,12 +387,12 @@ std::string load_swinfo(const game_driver *drv, const char* datsdir, std::string
fp.close();
}
- return buffer;
+ return convert_xml(buffer);
}
std::string load_gameinfo(const game_driver *drv, const char* datsdir, int filenum)
{
- std::string buffer;
+ buffer.clear();
// if it's a NULL record exit now
if (!m_gameInfo[filenum].filename)
return buffer;
@@ -221,13 +401,32 @@ std::string load_gameinfo(const game_driver *drv, const char* datsdir, int filen
std::string buf, filename = datsdir + std::string("\\") + m_gameInfo[filenum].filename;
std::ifstream fp (filename);
- /* try to open datafile */
- if (create_index(fp, filenum))
+ if (filenum == 0)
{
- std::string first = std::string("$info=")+drv->name;
- // get info on game
- buf = load_datafile_text(fp, first, filenum, m_gameInfo[filenum].descriptor);
+ // try to open history.xml
+ if (create_index(datsdir, fp, filenum))
+ {
+ // get info on game
+ buf = load_datafile_text(fp, drv->name, filenum, m_gameInfo[filenum].descriptor);
+ // if nothing, and it's a clone, and it's allowed, try the parent
+ if (buf.empty() && m_gameInfo[filenum].bClone)
+ {
+ int g = driver_list::clone(*drv);
+ if (g != -1)
+ {
+ drv = &driver_list::driver(g);
+ buf = load_datafile_text(fp, drv->name, filenum, m_gameInfo[filenum].descriptor);
+ }
+ }
+ }
+ }
+ else
+ // try to open datafile
+ if (create_index(datsdir, fp, filenum))
+ {
+ // get info on game
+ buf = load_datafile_text(fp, drv->name, filenum, m_gameInfo[filenum].descriptor);
// if nothing, and it's a clone, and it's allowed, try the parent
if (buf.empty() && m_gameInfo[filenum].bClone)
{
@@ -235,23 +434,22 @@ std::string load_gameinfo(const game_driver *drv, const char* datsdir, int filen
if (g != -1)
{
drv = &driver_list::driver(g);
- first = std::string("$info=")+drv->name;
- buf = load_datafile_text(fp, first, filenum, m_gameInfo[filenum].descriptor);
+ buf = load_datafile_text(fp, drv->name, filenum, m_gameInfo[filenum].descriptor);
}
}
+ }
- if (!buf.empty())
- buffer.append(m_gameInfo[filenum].header).append(buf).append("\n\n\n");
+ if (!buf.empty())
+ buffer.append(m_gameInfo[filenum].header).append(buf).append("\n\n\n");
- fp.close();
- }
+ fp.close();
- return buffer;
+ return convert_xml(buffer);
}
std::string load_sourceinfo(const game_driver *drv, const char* datsdir, int filenum)
{
- std::string buffer;
+ buffer.clear();
// if it's a NULL record exit now
if (!m_sourceInfo[filenum].filename)
return buffer;
@@ -264,11 +462,10 @@ std::string load_sourceinfo(const game_driver *drv, const char* datsdir, int fil
size_t i = source.find_last_of("/");
source.erase(0,i+1);
- if (create_index(fp, filenum))
+ if (create_index(datsdir, fp, filenum))
{
- std::string first = std::string("$info=")+source;
// get info on game driver source
- buf = load_datafile_text(fp, first, filenum, m_sourceInfo[filenum].descriptor);
+ buf = load_datafile_text(fp, source, filenum, m_sourceInfo[filenum].descriptor);
if (!buf.empty())
buffer.append(m_sourceInfo[filenum].header).append(source).append("\n").append(buf).append("\n\n\n");
@@ -287,9 +484,9 @@ std::string load_driver_geninfo(const game_driver *drv, int drvindex)
const game_driver *parent = NULL;
char name[512];
bool is_bios = false;
- std::string buffer = "\n**** :GENERAL MACHINE INFO: ****\n\n";
+ buffer = "\n**** :GENERAL MACHINE INFO: ****\n\n";
- /* List the game info 'flags' */
+ // List the game info 'flags'
uint32_t cache = GetDriverCacheLower(drvindex);
if (BIT(cache, 6))
buffer.append("This game doesn't work properly\n");
@@ -329,14 +526,14 @@ std::string load_driver_geninfo(const game_driver *drv, int drvindex)
if (drv->flags & MACHINE_IS_BIOS_ROOT)
is_bios = true;
- /* GAME INFORMATIONS */
+ // GAME INFORMATIONS
snprintf(name, std::size(name), "\nGAME: %s\n", drv->name);
buffer.append(name);
snprintf(name, std::size(name), "%s", drv->type.fullname());
buffer.append(name);
snprintf(name, std::size(name), " (%s %s)\n\nCPU:\n", drv->manufacturer, drv->year);
buffer.append(name);
- /* iterate over CPUs */
+ // iterate over CPUs
execute_interface_enumerator cpuiter(config.root_device());
std::unordered_set<std::string> exectags;
@@ -370,7 +567,7 @@ std::string load_driver_geninfo(const game_driver *drv, int drvindex)
buffer.append("\nSOUND:\n");
int has_sound = 0;
- /* iterate over sound chips */
+ // iterate over sound chips
sound_interface_enumerator sounditer(config.root_device());
std::unordered_set<std::string> soundtags;
@@ -583,13 +780,14 @@ bool validate_datfiles(void)
return result;
}
+std::string fullbuf;
// For all of MAME builds - called by winui.cpp
char * GetGameHistory(int driver_index, std::string software)
{
- std::string fullbuf;
+ fullbuf.clear();
if (driver_index < 0)
- return ConvertToWindowsNewlines(fullbuf.c_str());
+ return ConvertToWindowsNewlines(fullbuf.c_str());
if (validate_datfiles())
{
@@ -604,7 +802,7 @@ char * GetGameHistory(int driver_index, std::string software)
if (!software.empty())
{
size_t i = software.find(':');
- sw_valid = (i != std::string::npos) ? true : false;
+ sw_valid = (i != npos) ? true : false;
}
if (datsdir && osd::directory::open(datsdir))
@@ -631,9 +829,9 @@ char * GetGameHistory(int driver_index, std::string software)
// For Arcade-only builds
char * GetGameHistory(int driver_index)
{
- std::string fullbuf;
+ fullbuf.clear();
if (driver_index < 0)
- return ConvertToWindowsNewlines(fullbuf.c_str());
+ return ConvertToWindowsNewlines(fullbuf.c_str());
if (validate_datfiles())
{