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.cpp1127
1 files changed, 405 insertions, 722 deletions
diff --git a/docs/release/src/osd/winui/history.cpp b/docs/release/src/osd/winui/history.cpp
index fb96346f307..83452b36d13 100644
--- a/docs/release/src/osd/winui/history.cpp
+++ b/docs/release/src/osd/winui/history.cpp
@@ -1,6 +1,5 @@
// For licensing and usage information, read docs/winui_license.txt
// MASTER
-//****************************************************************************
/***************************************************************************
history.cpp
@@ -9,16 +8,27 @@
* History database engine
* Collect all information on the selected driver, and return it as
* a string. Called by winui.cpp
- *
+
* Token parsing by Neil Bradley
* Modifications and higher-level functions by John Butler
* Further work by Mamesick and Robbbert
+ * Completely rewritten by Robbbert in July 2017
+ * Notes:
+ * - The order listed in m_gameInfo is the order the data is displayed.
+ * - The other tables must have the files in the same places so that
+ * the index numbers line up. Anything with NULL indicates an
+ * unsupported option (the file doesn't contain the info).
+ * - Each table must contain at least MAX_HFILES members (extra lines
+ * are ignored)
+ * - Software comes first, followed by Game then Source.
***************************************************************************/
+// license:BSD-3-Clause
+// copyright-holders:Chris Kirmse, Mike Haaland, René Single, Mamesick, Robbbert
-// standard windows headers
#include <windows.h>
+#include <fstream>
// MAME/MAMEUI headers
#include "emu.h"
@@ -29,659 +39,420 @@
#include "mui_opts.h"
#include "sound/samples.h"
-#define MAX_TOKEN_LENGTH 256
-#define DATAFILE_TAG '$'
+#define WINUI_ARRAY_LENGTH(x) (sizeof(x) / sizeof(x[0]))
-/****************************************************************************
- * datafile constants
- ****************************************************************************/
-static const char *DATAFILE_TAG_KEY = "$info";
-static const char *DATAFILE_TAG_BIO = "$bio";
-static const char *DATAFILE_TAG_MAME = "$mame";
-static const char *DATAFILE_TAG_DRIV = "$drv";
-static const char *DATAFILE_TAG_CMD = "$cmd";
-static const char *DATAFILE_TAG_SCORE = "$story";
-static const char *DATAFILE_TAG_END = "$end";
/****************************************************************************
- * private data for parsing functions
+ * struct definitions
****************************************************************************/
-static FILE *fp = nullptr; /* Our file pointer */
-static UINT64 dwFilePos = 0; /* file position */
-static char filename[MAX_PATH]; /* datafile name */
-
-struct tDatafileIndex
-{
- long offset;
- const game_driver *driver;
-};
-
-static struct tDatafileIndex *gameinit_idx = nullptr;
-static struct tDatafileIndex *hist_idx = nullptr;
-static struct tDatafileIndex *mame_idx = nullptr;
-static struct tDatafileIndex *driv_idx = nullptr;
-static struct tDatafileIndex *sysinfo_idx = nullptr;
-static struct tDatafileIndex *mess_idx = nullptr;
-static struct tDatafileIndex *messdriv_idx = nullptr;
-static struct tDatafileIndex *cmd_idx = nullptr;
-static struct tDatafileIndex *score_idx = nullptr;
-
-/****************************************************************************
-* Create an array with sorted sourcedrivers for the function
-* index_datafile_drivinfo to speed up the datafile access
-****************************************************************************/
-
typedef struct
{
- const char *srcdriver;
- int index;
-} srcdriver_data_type;
-
-static srcdriver_data_type *sorted_srcdrivers = nullptr;
-
-static int SrcDriverDataCompareFunc(const void *arg1, const void *arg2)
-{
- return strcmp(((srcdriver_data_type *)arg1)->srcdriver, ((srcdriver_data_type *)arg2)->srcdriver);
+ LPCSTR filename;
+ LPCSTR header;
+ LPCSTR descriptor;
+ bool bClone; // if nothing found for a clone, try the parent
}
+HGAMEINFO;
-static int GetSrcDriverIndex(const char *srcdriver)
+typedef struct
{
- srcdriver_data_type *srcdriver_index_info;
- srcdriver_data_type key;
- key.srcdriver = srcdriver;
- int num_games = driver_list::total();
-
- if (sorted_srcdrivers == NULL)
- {
- /* initialize array of game names/indices */
- sorted_srcdrivers = (srcdriver_data_type *)malloc(sizeof(srcdriver_data_type) * num_games);
- for (int i = 0; i < num_games; i++)
- {
- sorted_srcdrivers[i].srcdriver = driver_list::driver(i).source_file+32;
- sorted_srcdrivers[i].index = i;
- }
- qsort(sorted_srcdrivers,num_games,sizeof(srcdriver_data_type),SrcDriverDataCompareFunc);
- }
-
- srcdriver_index_info = (srcdriver_data_type *)bsearch(&key, sorted_srcdrivers, num_games, sizeof(srcdriver_data_type), SrcDriverDataCompareFunc);
-
- if (srcdriver_index_info)
- return srcdriver_index_info->index;
- else
- return -1;
+ LPCSTR filename;
+ LPCSTR header;
+ LPCSTR descriptor;
}
+HSOURCEINFO;
-/****************************************************************************
- * ParseClose - Closes the existing opened file (if any)
- ****************************************************************************/
-static void ParseClose(void)
+/*************************** START CONFIGURABLE AREA *******************************/
+// number of dats we support
+#define MAX_HFILES 8
+// The order of these is the order they are displayed
+const HGAMEINFO m_gameInfo[MAX_HFILES] =
{
- /* If the file is open, time for fclose. */
- if (fp)
- fclose(fp);
-}
+ { "history.dat", "\n**** :HISTORY: ****\n\n", "$bio", 1 },
+ { "sysinfo.dat", "\n**** :SYSINFO: ****\n\n", "$bio", 1 },
+ { "messinfo.dat", "\n**** :MESSINFO: ****\n\n", "$mame", 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 },
+};
-/****************************************************************************
- * ParseOpen - Open up file for reading
- ****************************************************************************/
-static BOOL ParseOpen(const char *pszFilename)
+const HSOURCEINFO m_sourceInfo[MAX_HFILES] =
{
- /* MAME core file parsing functions fail in recognizing UNICODE chars in UTF-8 without BOM,
- so it's better and faster use standard C fileio functions */
- fp = fopen(pszFilename, "r");
-
- if (fp == NULL)
- return FALSE;
-
- /* Otherwise, prepare! */
- dwFilePos = 0;
- /* identify text file type first */
- fgetc(fp);
- fseek(fp, dwFilePos, SEEK_SET);
- return TRUE;
-}
+ { NULL },
+ { NULL },
+ { "messinfo.dat", "\n***:MESSINFO DRIVER: ", "$drv" },
+ { "mameinfo.dat", "\n***:MAMEINFO DRIVER: ", "$drv" },
+ { NULL },
+ { NULL },
+ { NULL },
+ { NULL },
+};
-/****************************************************************************
- * ParseSeek - Move the file position indicator
- ****************************************************************************/
-static UINT8 ParseSeek(UINT64 offset, int whence)
+const HSOURCEINFO m_swInfo[MAX_HFILES] =
{
- int result = fseek(fp, offset, whence);
+ { "history.dat", "\n**** :HISTORY item: ", "$bio" },
+ { NULL },
+ { NULL },
+ { NULL },
+ { NULL },
+ { NULL },
+ { NULL },
+ { NULL },
+};
- if (result == 0)
- dwFilePos = ftell(fp);
+/*************************** END CONFIGURABLE AREA *******************************/
- return (UINT8)result;
-}
+int file_sizes[MAX_HFILES] = { 0, };
+std::map<std::string, std::streampos> mymap[MAX_HFILES];
-/**************************************************************************
- **************************************************************************
- *
- * Datafile functions
- *
- **************************************************************************
- **************************************************************************/
-
- /**************************************************************************
- * index_datafile
- * Create an index for the records in the currently open datafile.
- *
- * Returns 0 on error, or the number of index entries created.
- **************************************************************************/
-static int index_datafile(struct tDatafileIndex **_index, int source)
+static bool create_index(std::ifstream &fp, int filenum)
{
- struct tDatafileIndex *idx;
- int count = 0;
- char readbuf[512];
- char name[40];
- int num_games = driver_list::total();
-
- /* rewind file */
- if (ParseSeek (0L, SEEK_SET))
- return 0;
-
- /* allocate index */
- idx = *_index = global_alloc_array(tDatafileIndex, (num_games + 1) * sizeof (struct tDatafileIndex));
-
- if (!idx)
- return 0;
-
- while (fgets(readbuf, 512, fp))
+ if (!fp.good())
+ return false;
+ // get file size
+ fp.seekg(0, std::ios::end);
+ size_t file_size = fp.tellg();
+ // same file as before?
+ if (file_size == file_sizes[filenum])
+ return true;
+ // new file, it needs to be indexed
+ mymap[filenum].clear();
+ file_sizes[filenum] = file_size;
+ fp.seekg(0);
+ std::string file_line, first, second;
+ std::getline(fp, file_line);
+ int position = file_line.size() + 2; // tellg is buggy, this works and is faster
+ while (fp.good())
{
- /* DATAFILE_TAG_KEY identifies the driver */
- if (!core_strnicmp(DATAFILE_TAG_KEY, readbuf, strlen(DATAFILE_TAG_KEY)))
+ char t1 = file_line[0];
+ if ((std::count(file_line.begin(),file_line.end(),'=') == 1) && (t1 == '$')) // line must start with $ and contain one =
{
- int game_index = 0;
- char *curpoint = &readbuf[strlen(DATAFILE_TAG_KEY) + 1];
- char *pch = NULL;
- char *ends = &readbuf[strlen(readbuf) - 1];
-
- while (curpoint < ends)
+ // 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)
{
- // search for comma
- pch = strpbrk(curpoint, ",");
-
- // found it
- if (pch)
- {
- // copy data and validate driver
- int len = pch - curpoint;
- strncpy(name, curpoint, len);
- name[len] = '\0';
-
- if (!source)
- game_index = GetGameNameIndex(name);
- else
- game_index = GetSrcDriverIndex(name);
-
- if (game_index >= 0)
- {
- idx->driver = &driver_list::driver(game_index);
- idx->offset = ftell(fp);
- idx++;
- count++;
- }
-
- // update current point
- curpoint = pch + 1;
- }
- // if comma not found, copy data while until reach the end of string
- else if (!pch && curpoint < ends)
- {
- int len = ends - curpoint;
- strncpy(name, curpoint, len);
- name[len] = '\0';
-
- if (!source)
- game_index = GetGameNameIndex(name);
- else
- game_index = GetSrcDriverIndex(name);
-
- if (game_index >= 0)
- {
- idx->driver = &driver_list::driver(game_index);
- idx->offset = ftell(fp);
- idx++;
- count++;
- }
-
- // update current point
- curpoint = ends;
- }
+ // store into index
+ mymap[filenum][std::string(first) + std::string("=") + std::string(second)] = position;
+ second = strtok(NULL, ",");
}
}
+ std::getline(fp, file_line);
+ position += (file_line.size() + 2);
}
-
- /* mark end of index */
- idx->offset = 0L;
- idx->driver = 0;
- return count;
+ // check contents
+// if (filenum == 0)
+// for (auto const &it : mymap[filenum])
+// printf("%s = %X\n", it.first.c_str(), int(it.second));
+ return true;
}
-/**************************************************************************
- * load_datafile_text
- *
- * Loads text field for a driver into the buffer specified. Specify the
- * driver, a pointer to the buffer, the buffer size, the index created by
- * index_datafile(), and the desired text field (e.g., DATAFILE_TAG_BIO).
- *
- * Returns 0 if successful.
- **************************************************************************/
-static int load_datafile_text(const game_driver *drv, char *buffer, int bufsize, struct tDatafileIndex *idx, const char *tag, int source_file, int mameinfo)
+static std::string load_datafile_text(std::ifstream &fp, std::string keycode, int filenum, const char *tag)
{
- char readbuf[16384];
+ std::string readbuf;
- *buffer = '\0';
-
- if (!source_file)
+ auto search = mymap[filenum].find(keycode);
+ if (search != mymap[filenum].end())
{
- /* find driver in datafile index */
- while (idx->driver)
- {
- if (idx->driver == drv)
- break;
+ std::streampos offset = mymap[filenum].find(keycode)->second;
+ fp.seekg(offset);
+ std::string file_line;
- idx++;
- }
- }
- else
- {
- /* find source file in datafile index */
- while (idx->driver)
+ /* read text until buffer is full or end of entry is encountered */
+ while (std::getline(fp, file_line))
{
- if (idx->driver->source_file == drv->source_file)
+ //printf("%s\n",file_line.c_str());
+ if (file_line.find("$end")==0)
break;
- idx++;
+ if (file_line.find(tag)==0)
+ continue;
+
+ readbuf.append(file_line).append("\n");
}
}
- if (idx->driver == 0)
- return 1; /* driver not found in index */
+ return readbuf;
+}
- /* seek to correct point in datafile */
- if (ParseSeek (idx->offset, SEEK_SET))
- return 1;
+std::string load_swinfo(const game_driver *drv, const char* datsdir, std::string software, int filenum)
+{
+ std::string buffer;
+ // if it's a NULL record exit now
+ if (!m_swInfo[filenum].filename)
+ return buffer;
- /* read text until buffer is full or end of entry is encountered */
- while (fgets(readbuf, 16384, fp))
- {
- if (!core_strnicmp(DATAFILE_TAG_END, readbuf, strlen(DATAFILE_TAG_END)))
- break;
+ // datafile name
+ std::string buf, filename = datsdir + std::string("\\") + m_swInfo[filenum].filename;
+ std::ifstream fp (filename);
- if (!core_strnicmp(tag, readbuf, strlen(tag)))
- continue;
+ /* try to open datafile */
+ if (create_index(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);
- if (strlen(buffer) + strlen(readbuf) > bufsize)
- break;
+ if (!buf.empty())
+ buffer.append(m_swInfo[filenum].header).append(ssoft).append("\n").append(buf).append("\n\n\n");
- if (mameinfo)
- {
- char *temp = strtok(readbuf, "\r\n\r\n");
- if (temp != nullptr)
- strcat(buffer, temp);
- else
- strcat(buffer, readbuf);
- }
- else
- strcat(buffer, readbuf);
+ fp.close();
}
- return 0;
+ return buffer;
}
-/**************************************************************************
- * load_driver_history
- * Load history text for the specified driver into the specified buffer.
- * Combines $bio field of HISTORY.DAT with $mame field of MAMEINFO.DAT.
- *
- * Returns 0 if successful.
- *
- * NOTE: For efficiency the indices are never freed (intentional leak).
- **************************************************************************/
-static int load_driver_history(const game_driver *drv, char *buffer, int bufsize, int filenum)
+std::string load_gameinfo(const game_driver *drv, const char* datsdir, int filenum)
{
- int history = 0;
+ std::string buffer;
+ // if it's a NULL record exit now
+ if (!m_gameInfo[filenum].filename)
+ return buffer;
- *buffer = 0;
+ // datafile name
+ std::string buf, filename = datsdir + std::string("\\") + m_gameInfo[filenum].filename;
+ std::ifstream fp (filename);
- if (filenum)
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\sysinfo.dat", GetDatsDir());
- else
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\history.dat", GetDatsDir());
-
- /* try to open history datafile */
- if (filenum)
+ /* try to open datafile */
+ if (create_index(fp, filenum))
{
- if (ParseOpen(filename))
- {
- /* create index if necessary */
- if (sysinfo_idx)
- history = 1;
- else
- history = (index_datafile (&sysinfo_idx, 0) != 0);
+ std::string first = std::string("$info=")+drv->name;
+ // get info on game
+ buf = load_datafile_text(fp, first, filenum, m_gameInfo[filenum].descriptor);
- /* load history text (append)*/
- if (sysinfo_idx)
+ // 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)
{
- strcat(buffer, "\n**** SYSINFO: ****\n\n");
- int len = strlen(buffer);
- int err = 0;
- const game_driver *gdrv;
- gdrv = drv;
-
- do
- {
- err = load_datafile_text(gdrv, buffer + len, bufsize - len, sysinfo_idx, DATAFILE_TAG_BIO, 0, 0);
- int g = driver_list::clone(*gdrv);
-
- if (g!=-1)
- gdrv = &driver_list::driver(g);
- else
- gdrv = NULL;
- } while (err && gdrv);
-
- if (err)
- history = 0;
+ drv = &driver_list::driver(g);
+ first = std::string("$info=")+drv->name;
+ buf = load_datafile_text(fp, first, filenum, m_gameInfo[filenum].descriptor);
}
-
- ParseClose();
}
- }
- else
- {
- if (ParseOpen(filename))
- {
- /* create index if necessary */
- if (hist_idx)
- history = 1;
- else
- history = (index_datafile (&hist_idx, 0) != 0);
-
- /* load history text (append)*/
- if (hist_idx)
- {
- strcat(buffer, "\n**** HISTORY: ****\n\n");
- int len = strlen(buffer);
- int err = 0;
- const game_driver *gdrv;
- gdrv = drv;
- do
- {
- err = load_datafile_text(gdrv, buffer + len, bufsize - len, hist_idx, DATAFILE_TAG_BIO, 0, 0);
- int g = driver_list::clone(*gdrv);
-
- if (g!=-1)
- gdrv = &driver_list::driver(g);
- else
- gdrv = NULL;
- } while (err && gdrv);
-
- if (err)
- history = 0;
- }
+ if (!buf.empty())
+ buffer.append(m_gameInfo[filenum].header).append(buf).append("\n\n\n");
- ParseClose();
- }
+ fp.close();
}
- strcat(buffer, "\n");
- return (history == 0);
+ return buffer;
}
-static int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsize, int filenum)
+std::string load_sourceinfo(const game_driver *drv, const char* datsdir, int filenum)
{
- machine_config config(*drv, MameUIGlobal());
- const game_driver *parent = NULL;
- char name[512];
- int mameinfo = 0;
- int is_bios = 0;
+ std::string buffer;
+ // if it's a NULL record exit now
+ if (!m_sourceInfo[filenum].filename)
+ return buffer;
- *buffer = 0;
+ // datafile name
+ std::string buf, filename = datsdir + std::string("\\") + m_sourceInfo[filenum].filename;
+ std::ifstream fp (filename);
- switch (filenum)
- {
- case 0:
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\mameinfo.dat", GetDatsDir());
- strcat(buffer, "\n**** MAMEINFO: ****\n\n");
- break;
- case 1:
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\messinfo.dat", GetDatsDir());
- strcat(buffer, "\n**** MESSINFO: ****\n\n");
- break;
- case 2:
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\gameinit.dat", GetDatsDir());
- strcat(buffer, "\n**** GAMEINIT: ****\n\n");
- break;
- default:
- break;
- }
+ std::string source = drv->type.source();
+ size_t i = source.find_last_of("/");
+ source.erase(0,i+1);
- if (filenum < 2)
+ if (create_index(fp, filenum))
{
- /* List the game info 'flags' */
- if (drv->flags & MACHINE_NOT_WORKING)
- strcat(buffer, "THIS GAME DOESN'T WORK PROPERLY\n");
+ std::string first = std::string("$info=")+source;
+ // get info on game driver source
+ buf = load_datafile_text(fp, first, filenum, m_sourceInfo[filenum].descriptor);
- if (drv->flags & MACHINE_UNEMULATED_PROTECTION)
- strcat(buffer, "The game has protection which isn't fully emulated.\n");
+ if (!buf.empty())
+ buffer.append(m_sourceInfo[filenum].header).append(source).append("\n").append(buf).append("\n\n\n");
- if (drv->flags & MACHINE_IMPERFECT_GRAPHICS)
- strcat(buffer, "The video emulation isn't 100% accurate.\n");
+ fp.close();
+ }
- if (drv->flags & MACHINE_WRONG_COLORS)
- strcat(buffer, "The colors are completely wrong.\n");
+ return buffer;
+}
- if (drv->flags & MACHINE_IMPERFECT_COLORS)
- strcat(buffer, "The colors aren't 100% accurate.\n");
- if (drv->flags & MACHINE_NO_SOUND)
- strcat(buffer, "The game lacks sound.\n");
+// General hardware information
+std::string load_driver_geninfo(const game_driver *drv, int drvindex)
+{
+ machine_config config(*drv, MameUIGlobal());
+ const game_driver *parent = NULL;
+ char name[512];
+ bool is_bios = false;
+ std::string buffer = "\n**** :GENERAL MACHINE INFO: ****\n\n";
- if (drv->flags & MACHINE_IMPERFECT_SOUND)
- strcat(buffer, "The sound emulation isn't 100% accurate.\n");
+ /* List the game info 'flags' */
+ uint32_t cache = GetDriverCacheLower(drvindex);
+ if (BIT(cache, 6))
+ buffer.append("This game doesn't work properly\n");
- if (drv->flags & MACHINE_SUPPORTS_SAVE)
- strcat(buffer, "Save state support.\n");
+ if (BIT(cache, 22))
+ buffer.append("This game has protection which isn't fully emulated.\n");
- if (drv->flags & MACHINE_MECHANICAL)
- strcat(buffer, "The game contains mechanical parts.\n");
+ if (BIT(cache, 18))
+ buffer.append("The video emulation isn't 100% accurate.\n");
- strcat(buffer, "\n");
+ if (BIT(cache, 21))
+ buffer.append("The colors are completely wrong.\n");
- if (drv->flags & MACHINE_IS_BIOS_ROOT)
- is_bios = 1;
- }
+ if (BIT(cache, 20))
+ buffer.append("The colors aren't 100% accurate.\n");
- /* try to open mameinfo datafile */
- if (ParseOpen(filename))
- {
- if (filenum == 2)
- {
- /* create index if necessary */
- if (gameinit_idx)
- mameinfo = 1;
- else
- mameinfo = (index_datafile (&gameinit_idx, 0) != 0);
+ if (BIT(cache, 17))
+ buffer.append("This game lacks sound.\n");
- /* load informational text (append) */
- if (gameinit_idx)
- {
- int len = strlen(buffer);
- int err = 0;
- const game_driver *gdrv;
- gdrv = drv;
+ if (BIT(cache, 16))
+ buffer.append("The sound emulation isn't 100% accurate.\n");
- do
- {
- err = load_datafile_text(gdrv, buffer + len, bufsize - len, gameinit_idx, DATAFILE_TAG_MAME, 0, 1);
- int g = driver_list::clone(*gdrv);
+ if (BIT(cache, 7))
+ buffer.append("Save state not supported.\n");
- if (g!=-1)
- gdrv = &driver_list::driver(g);
- else
- gdrv = NULL;
- } while (err && gdrv);
+ if (BIT(cache, 14))
+ buffer.append("This game contains mechanical parts.\n");
- if (err)
- mameinfo = 0;
- }
- }
- else
- if (filenum == 1)
- {
- /* create index if necessary */
- if (mess_idx)
- mameinfo = 1;
- else
- mameinfo = (index_datafile (&mess_idx, 0) != 0);
+ if (BIT(cache, 15))
+ buffer.append("This game was never completed.\n");
- /* load informational text (append) */
- if (mess_idx)
- {
- int len = strlen(buffer);
- int err = 0;
- const game_driver *gdrv;
- gdrv = drv;
+ if (BIT(cache, 13))
+ buffer.append("This game has no sound hardware.\n");
- do
- {
- err = load_datafile_text(gdrv, buffer + len, bufsize - len, mess_idx, DATAFILE_TAG_MAME, 0, 1);
- int g = driver_list::clone(*gdrv);
+ buffer.append("\n");
- if (g!=-1)
- gdrv = &driver_list::driver(g);
- else
- gdrv = NULL;
- } while (err && gdrv);
+ if (drv->flags & MACHINE_IS_BIOS_ROOT)
+ is_bios = true;
- if (err)
- mameinfo = 0;
- }
- }
- else
- if (filenum == 0)
- {
- /* create index if necessary */
- if (mame_idx)
- mameinfo = 1;
- else
- mameinfo = (index_datafile (&mame_idx, 0) != 0);
+ /* GAME INFORMATIONS */
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "\nGAME: %s\n", drv->name);
+ buffer.append(name);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%s", drv->type.fullname());
+ buffer.append(name);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), " (%s %s)\n\nCPU:\n", drv->manufacturer, drv->year);
+ buffer.append(name);
+ /* iterate over CPUs */
+ execute_interface_iterator cpuiter(config.root_device());
+ std::unordered_set<std::string> exectags;
- /* load informational text (append) */
- if (mame_idx)
- {
- int len = strlen(buffer);
- int err = 0;
- const game_driver *gdrv;
- gdrv = drv;
+ for (device_execute_interface &exec : cpuiter)
+ {
+ if (!exectags.insert(exec.device().tag()).second)
+ continue;
- do
- {
- err = load_datafile_text(gdrv, buffer + len, bufsize - len, mame_idx, DATAFILE_TAG_MAME, 0, 1);
- int g = driver_list::clone(*gdrv);
+ int count = 1;
+ int clock = exec.device().clock();
+ const char *cpu_name = exec.device().name();
- if (g!=-1)
- gdrv = &driver_list::driver(g);
- else
- gdrv = NULL;
- } while (err && gdrv);
+ for (device_execute_interface &scan : cpuiter)
+ if (exec.device().type() == scan.device().type() && strcmp(cpu_name, scan.device().name()) == 0 && clock == scan.device().clock())
+ if (exectags.insert(scan.device().tag()).second)
+ count++;
- if (err)
- mameinfo = 0;
- }
+ if (count > 1)
+ {
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%d x ", count);
+ buffer.append(name);
}
- ParseClose();
- }
-
- if (filenum > 1)
- return (mameinfo == 0);
-
- /* GAME INFORMATIONS */
- snprintf(name, ARRAY_LENGTH(name), "\nGAME: %s\n", drv->name);
- strcat(buffer, name);
- snprintf(name, ARRAY_LENGTH(name), "%s", drv->description);
- strcat(buffer, name);
- snprintf(name, ARRAY_LENGTH(name), " (%s %s)\n\nCPU:\n", drv->manufacturer, drv->year);
- strcat(buffer, name);
- /* iterate over CPUs */
- for (device_execute_interface &cpu : execute_interface_iterator(config.root_device()))
- {
- if (cpu.device().clock() >= 1000000)
- snprintf(name, ARRAY_LENGTH(name), "%s %d.%06d MHz\n", cpu.device().name(), cpu.device().clock() / 1000000, cpu.device().clock() % 1000000);
+ if (clock >= 1000000)
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%s %d.%06d MHz\n", cpu_name, clock / 1000000, clock % 1000000);
else
- snprintf(name, ARRAY_LENGTH(name), "%s %d.%03d kHz\n", cpu.device().name(), cpu.device().clock() / 1000, cpu.device().clock() % 1000);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%s %d.%03d kHz\n", cpu_name, clock / 1000, clock % 1000);
- strcat(buffer, name);
+ buffer.append(name);
}
- strcat(buffer, "\nSOUND:\n");
+ buffer.append("\nSOUND:\n");
int has_sound = 0;
/* iterate over sound chips */
+ sound_interface_iterator sounditer(config.root_device());
+ std::unordered_set<std::string> soundtags;
- for (device_sound_interface &sound : sound_interface_iterator(config.root_device()))
+ for (device_sound_interface &sound : sounditer)
{
- char tmpname[1024];
+ if (!soundtags.insert(sound.device().tag()).second)
+ continue;
- snprintf(tmpname, ARRAY_LENGTH(tmpname), "%s", sound.device().name());
- int clock = sound.device().clock();
has_sound = 1;
+ int count = 1;
+ int clock = sound.device().clock();
+ const char *sound_name = sound.device().name();
+
+ for (device_sound_interface &scan : sounditer)
+ if (sound.device().type() == scan.device().type() && strcmp(sound_name, scan.device().name()) == 0 && clock == scan.device().clock())
+ if (soundtags.insert(scan.device().tag()).second)
+ count++;
+
+ if (count > 1)
+ {
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%d x ", count);
+ buffer.append(name);
+ }
- strcat(buffer, tmpname);
+ buffer.append(sound_name);
if (clock)
{
if (clock >= 1000000)
- snprintf(name, ARRAY_LENGTH(name), " %d.%06d MHz", clock / 1000000, clock % 1000000);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), " %d.%06d MHz", clock / 1000000, clock % 1000000);
else
- snprintf(name, ARRAY_LENGTH(name), " %d.%03d kHz", clock / 1000, clock % 1000);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), " %d.%03d kHz", clock / 1000, clock % 1000);
- strcat(buffer, name);
+ buffer.append(name);
}
- strcat(buffer, "\n");
+ buffer.append("\n");
}
if (has_sound)
{
- speaker_device_iterator iter(config.root_device());
- int channels = iter.count();
+ speaker_device_iterator audioiter(config.root_device());
+ int channels = audioiter.count();
if(channels == 1)
- snprintf(name, ARRAY_LENGTH(name), "%d Channel\n",channels);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%d Channel\n", channels);
else
- snprintf(name, ARRAY_LENGTH(name), "%dx Channels\n",channels);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%d Channels\n", channels);
- strcat(buffer, name);
+ buffer.append(name);
}
- strcat(buffer, "\nVIDEO:\n");
+ buffer.append("\nVIDEO:\n");
screen_device_iterator screeniter(config.root_device());
- const screen_device *screen1 = screeniter.first();
+ int scrcount = screeniter.count();
- if (screen1 == nullptr)
- strcat(buffer, "Screenless\n");
- else if (screen1->screen_type() == SCREEN_TYPE_VECTOR)
- strcat(buffer,"Vector\n");
+ if (scrcount == 0)
+ buffer.append("Screenless");
else
{
- for (screen_device &screen : screen_device_iterator(config.root_device()))
+ for (screen_device &screen : screeniter)
{
- if (drv->flags & ORIENTATION_SWAP_XY)
- snprintf(name, ARRAY_LENGTH(name), "%d x %d (V)", screen.visible_area().height(), screen.visible_area().width());
+ if (screen.screen_type() == SCREEN_TYPE_VECTOR)
+ buffer.append("Vector");
else
- snprintf(name, ARRAY_LENGTH(name), "%d x %d (H)", screen.visible_area().width(), screen.visible_area().height());
+ {
+ const rectangle &visarea = screen.visible_area();
+
+ if (drv->flags & ORIENTATION_SWAP_XY)
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%d x %d (V) %f Hz", visarea.width(), visarea.height(), ATTOSECONDS_TO_HZ(screen.refresh_attoseconds()));
+ else
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%d x %d (H) %f Hz", visarea.width(), visarea.height(), ATTOSECONDS_TO_HZ(screen.refresh_attoseconds()));
- strcat(buffer, name);
- snprintf(name, ARRAY_LENGTH(name), " %f Hz", ATTOSECONDS_TO_HZ(screen.refresh_attoseconds()));
- strcat(buffer, name);
- strcat(buffer, "\n");
+ buffer.append(name);
+ }
+
+ buffer.append("\n");
}
}
- strcat(buffer, "\nROM REGION:\n");
+ buffer.append("\nROM REGION:\n");
int g = driver_list::clone(*drv);
if (g != -1)
@@ -698,10 +469,11 @@ static int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsiz
if (g != -1)
{
machine_config pconfig(*parent, MameUIGlobal());
- device_iterator deviter(pconfig.root_device());
for (device_t &device : device_iterator(pconfig.root_device()))
+ {
for (const rom_entry *pregion = rom_first_region(device); pregion; pregion = rom_next_region(pregion))
+ {
for (const rom_entry *prom = rom_first_file(pregion); prom; prom = rom_next_file(prom))
{
util::hash_collection phashes(ROM_GETHASHDATA(prom));
@@ -709,15 +481,16 @@ static int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsiz
if (hashes == phashes)
break;
}
+ }
+ }
}
- snprintf(name, ARRAY_LENGTH(name), "%-16s \t", ROM_GETNAME(rom));
- strcat(buffer, name);
- snprintf(name, ARRAY_LENGTH(name), "%09d \t", rom_file_size(rom));
- strcat(buffer, name);
- snprintf(name, ARRAY_LENGTH(name), "%-10s", ROMREGION_GETTAG(region));
- strcat(buffer, name);
- strcat(buffer, "\n");
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%-16s \t", ROM_GETNAME(rom));
+ buffer.append(name);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%09d \t", rom_file_size(rom));
+ buffer.append(name);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%-10s", ROMREGION_GETTAG(region));
+ buffer.append(name).append("\n");
}
}
}
@@ -726,10 +499,10 @@ static int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsiz
{
samples_iterator sampiter(device);
- if (sampiter.altbasename() )
+ if (sampiter.altbasename())
{
- snprintf(name, ARRAY_LENGTH(name), "\nSAMPLES (%s):\n", sampiter.altbasename());
- strcat(buffer, name);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "\nSAMPLES (%s):\n", sampiter.altbasename());
+ buffer.append(name);
}
std::unordered_set<std::string> already_printed;
@@ -741,8 +514,8 @@ static int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsiz
continue;
// output the sample name
- snprintf(name, ARRAY_LENGTH(name), "%s.wav\n", samplename);
- strcat(buffer, name);
+ snprintf(name, WINUI_ARRAY_LENGTH(name), "%s.wav\n", samplename);
+ buffer.append(name);
}
}
@@ -753,230 +526,140 @@ static int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsiz
if (g != -1)
drv = &driver_list::driver(g);
- strcat(buffer, "\nORIGINAL:\n");
- strcat(buffer, drv->description);
- strcat(buffer, "\n\nCLONES:\n");
+ buffer.append("\nORIGINAL:\n");
+ buffer.append(drv->type.fullname());
+ buffer.append("\n\nCLONES:\n");
for (int i = 0; i < driver_list::total(); i++)
{
if (!strcmp (drv->name, driver_list::driver(i).parent))
{
- strcat(buffer, driver_list::driver(i).description);
- strcat(buffer, "\n");
+ buffer.append(driver_list::driver(i).type.fullname());
+ buffer.append("\n");
}
}
}
- strcat(buffer, "\n");
- return (mameinfo == 0);
-}
-
-static int load_driver_driverinfo(const game_driver *drv, char *buffer, int bufsize, int filenum)
-{
- int drivinfo = 0;
- char source_file[40];
- char tmp[100];
- std::string temp = core_filename_extract_base(drv->source_file);
+ char source_file[40], tmp[100];
+ std::string temp = core_filename_extract_base(drv->type.source(), false);
strcpy(source_file, temp.c_str());
+ snprintf(tmp, WINUI_ARRAY_LENGTH(tmp), "\nGENERAL SOURCE INFO: %s\n", temp.c_str());
+ buffer.append(tmp);
+ buffer.append("\nGAMES SUPPORTED:\n");
- *buffer = 0;
-
- if (filenum)
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\messinfo.dat", GetDatsDir());
- else
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\mameinfo.dat", GetDatsDir());
-
- /* Print source code file */
- snprintf(tmp, ARRAY_LENGTH(tmp), "\n\nSOURCE: %s\n\n", source_file);
- strcat(buffer, tmp);
-
- /* Try to open mameinfo datafile - driver section*/
- if (ParseOpen(filename))
+ for (int i = 0; i < driver_list::total(); i++)
{
- if (filenum)
- {
- /* create index if necessary */
- if (messdriv_idx)
- drivinfo = 1;
- else
- drivinfo = (index_datafile (&messdriv_idx, 1) != 0);
-
- /* load informational text (append) */
- if (messdriv_idx)
- {
- int len = strlen(buffer);
- int err = load_datafile_text(drv, buffer + len, bufsize - len, messdriv_idx, DATAFILE_TAG_DRIV, 1, 1);
-
- if (err)
- drivinfo = 0;
- }
- }
- else
- {
- /* create index if necessary */
- if (driv_idx)
- drivinfo = 1;
- else
- drivinfo = (index_datafile (&driv_idx, 1) != 0);
+ std::string t1 = driver_list::driver(i).type.source();
+ size_t j = t1.find_last_of("/");
+ t1.erase(0, j+1);
+ if ((strcmp(source_file, t1.c_str())==0) && !(DriverIsBios(i)))
+ buffer.append(driver_list::driver(i).type.fullname()).append("\n");
+ }
- /* load informational text (append) */
- if (driv_idx)
- {
- int len = strlen(buffer);
- int err = load_datafile_text(drv, buffer + len, bufsize - len, driv_idx, DATAFILE_TAG_DRIV, 1, 1);
+ return buffer;
+}
- if (err)
- drivinfo = 0;
- }
- }
- ParseClose();
+// This is check that the tables are at least as big as they should be
+bool validate_datfiles(void)
+{
+ bool result = true;
+ if (WINUI_ARRAY_LENGTH(m_gameInfo) < MAX_HFILES)
+ {
+ printf("m_gameInfo needs to have at least MAX_HFILES members\n");
+ result = false;
}
- strcat(buffer, "\nGAMES SUPPORTED:\n");
+ if (WINUI_ARRAY_LENGTH(m_sourceInfo) < MAX_HFILES)
+ {
+ printf("m_sourceInfo needs to have at least MAX_HFILES members\n");
+ result = false;
+ }
- for (int i = 0; i < driver_list::total(); i++)
+ if (WINUI_ARRAY_LENGTH(m_swInfo) < MAX_HFILES)
{
- if (!strcmp(source_file, GetDriverFilename(i)) && !(DriverIsBios(i)))
- {
- strcat(buffer, driver_list::driver(i).description);
- strcat(buffer,"\n");
- }
+ printf("m_swInfo needs to have at least MAX_HFILES members\n");
+ result = false;
}
- strcat(buffer, "\n\n");
- return (drivinfo == 0);
+ return result;
}
-static int load_driver_command(const game_driver *drv, char *buffer, int bufsize)
-{
- int command = 0;
- *buffer = 0;
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\command.dat", GetDatsDir());
- strcat(buffer, "\n**** COMMAND: ****\n\n");
+// For all of MAME builds - called by winui.cpp
+char * GetGameHistory(int driver_index, std::string software)
+{
+ std::string fullbuf;
+ if (driver_index < 0)
+ return ConvertToWindowsNewlines(fullbuf.c_str());
- /* try to open command datafile */
- if (ParseOpen(filename))
+ if (validate_datfiles())
{
- /* create index if necessary */
- if (cmd_idx)
- command = 1;
- else
- command = (index_datafile (&cmd_idx, 0) != 0);
+ // Get the path to dat files
+ char buf[400];
+ std::string t = GetDatsDir();
+ strcpy(buf, t.c_str());
+ // only want first path
+ const char* datsdir = strtok(buf, ";");
+ // validate software
+ BOOL sw_valid = false;
+ if (!software.empty())
+ {
+ size_t i = software.find(':');
+ sw_valid = (i != std::string::npos) ? true : false;
+ }
- /* load informational text (append) */
- if (cmd_idx)
+ if (datsdir && osd::directory::open(datsdir))
{
- int len = strlen(buffer);
- int err = 0;
- const game_driver *gdrv;
- gdrv = drv;
-
- do
+ for (int filenum = 0; filenum < MAX_HFILES; filenum++)
{
- err = load_datafile_text(gdrv, buffer + len, bufsize - len, cmd_idx, DATAFILE_TAG_CMD, 0, 0);
- int g = driver_list::clone(*gdrv);
-
- if (g!=-1)
- gdrv = &driver_list::driver(g);
- else
- gdrv = NULL;
- } while (err && gdrv);
-
- if (err)
- command = 0;
+ if (sw_valid)
+ fullbuf.append(load_swinfo(&driver_list::driver(driver_index), datsdir, software, filenum));
+ fullbuf.append(load_gameinfo(&driver_list::driver(driver_index), datsdir, filenum));
+ fullbuf.append(load_sourceinfo(&driver_list::driver(driver_index), datsdir, filenum));
+ }
}
-
- ParseClose();
+ else
+ fullbuf = "\nThe path to your dat files is invalid.\n\n\n";
}
+ else
+ fullbuf = "\nUnable to display info due to an internal error.\n\n\n";
- strcat(buffer, "\n\n");
- return (command == 0);
+ fullbuf.append(load_driver_geninfo(&driver_list::driver(driver_index), driver_index));
+
+ return ConvertToWindowsNewlines(fullbuf.c_str());
}
-static int load_driver_scoreinfo(const game_driver *drv, char *buffer, int bufsize)
+// For Arcade-only builds
+char * GetGameHistory(int driver_index)
{
- int scoreinfo = 0;
+ std::string fullbuf;
+ if (driver_index < 0)
+ return ConvertToWindowsNewlines(fullbuf.c_str());
- *buffer = 0;
- snprintf(filename, ARRAY_LENGTH(filename), "%s\\story.dat", GetDatsDir());
-
- /* try to open story datafile */
- if (ParseOpen(filename))
+ if (validate_datfiles())
{
- /* create index if necessary */
- if (score_idx)
- scoreinfo = 1;
- else
- scoreinfo = (index_datafile (&score_idx, 0) != 0);
+ char buf[400];
+ std::string t = GetDatsDir();
+ strcpy(buf, t.c_str());
+ // only want first path
+ const char* datsdir = strtok(buf, ";");
- /* load informational text (append) */
- if (score_idx)
+ if (datsdir && osd::directory::open(datsdir))
{
- int len = strlen(buffer);
- int err = 0;
- const game_driver *gdrv;
- gdrv = drv;
-
- do
+ for (int filenum = 0; filenum < MAX_HFILES; filenum++)
{
- err = load_datafile_text(gdrv, buffer + len, bufsize - len, score_idx, DATAFILE_TAG_SCORE, 0, 0);
- int g = driver_list::clone(*gdrv);
-
- if (g!=-1)
- gdrv = &driver_list::driver(g);
- else
- gdrv = NULL;
- } while (err && gdrv);
-
- if (err)
- scoreinfo = 0;
+ fullbuf.append(load_gameinfo(&driver_list::driver(driver_index), datsdir, filenum));
+ fullbuf.append(load_sourceinfo(&driver_list::driver(driver_index), datsdir, filenum));
+ }
}
-
- ParseClose();
+ else
+ fullbuf = "\nThe path to your dat files is invalid.\n\n\n";
}
+ else
+ fullbuf = "\nUnable to display info due to an internal error.\n\n\n";
- return (scoreinfo == 0);
-}
-/**************************************************************
- * functions
- **************************************************************/
-
-// Load indexes from history.dat if found
-char * GetGameHistory(int driver_index)
-{
- static char dataBuf[2048 * 2048];
- static char buffer[2048 * 2048];
-
- memset(&buffer, 0, sizeof(buffer));
- memset(&dataBuf, 0, sizeof(dataBuf));
-
- if (load_driver_mameinfo(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer), 2) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_history(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer), 0) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_history(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer), 1) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_mameinfo(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer), 0) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_driverinfo(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer), 0) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_mameinfo(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer), 1) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_driverinfo(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer), 1) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_command(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer)) == 0)
- strcat(dataBuf, buffer);
-
- if (load_driver_scoreinfo(&driver_list::driver(driver_index), buffer, ARRAY_LENGTH(buffer)) == 0)
- strcat(dataBuf, buffer);
+ fullbuf.append(load_driver_geninfo(&driver_list::driver(driver_index), driver_index));
- return ConvertToWindowsNewlines(dataBuf);
+ return ConvertToWindowsNewlines(fullbuf.c_str());
}
+