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.cpp982
1 files changed, 982 insertions, 0 deletions
diff --git a/docs/release/src/osd/winui/history.cpp b/docs/release/src/osd/winui/history.cpp
new file mode 100644
index 00000000000..fb96346f307
--- /dev/null
+++ b/docs/release/src/osd/winui/history.cpp
@@ -0,0 +1,982 @@
+// For licensing and usage information, read docs/winui_license.txt
+// MASTER
+//****************************************************************************
+/***************************************************************************
+
+ history.cpp
+
+ * history functions.
+ * 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
+
+***************************************************************************/
+
+// standard windows headers
+#include <windows.h>
+
+// MAME/MAMEUI headers
+#include "emu.h"
+#include "screen.h"
+#include "speaker.h"
+#include "drivenum.h"
+#include "mui_util.h"
+#include "mui_opts.h"
+#include "sound/samples.h"
+
+#define MAX_TOKEN_LENGTH 256
+#define DATAFILE_TAG '$'
+
+/****************************************************************************
+ * 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
+ ****************************************************************************/
+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);
+}
+
+static int GetSrcDriverIndex(const char *srcdriver)
+{
+ 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;
+}
+
+/****************************************************************************
+ * ParseClose - Closes the existing opened file (if any)
+ ****************************************************************************/
+static void ParseClose(void)
+{
+ /* If the file is open, time for fclose. */
+ if (fp)
+ fclose(fp);
+}
+
+/****************************************************************************
+ * ParseOpen - Open up file for reading
+ ****************************************************************************/
+static BOOL ParseOpen(const char *pszFilename)
+{
+ /* 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;
+}
+
+/****************************************************************************
+ * ParseSeek - Move the file position indicator
+ ****************************************************************************/
+static UINT8 ParseSeek(UINT64 offset, int whence)
+{
+ int result = fseek(fp, offset, whence);
+
+ if (result == 0)
+ dwFilePos = ftell(fp);
+
+ return (UINT8)result;
+}
+
+/**************************************************************************
+ **************************************************************************
+ *
+ * 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)
+{
+ 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))
+ {
+ /* DATAFILE_TAG_KEY identifies the driver */
+ if (!core_strnicmp(DATAFILE_TAG_KEY, readbuf, strlen(DATAFILE_TAG_KEY)))
+ {
+ int game_index = 0;
+ char *curpoint = &readbuf[strlen(DATAFILE_TAG_KEY) + 1];
+ char *pch = NULL;
+ char *ends = &readbuf[strlen(readbuf) - 1];
+
+ while (curpoint < ends)
+ {
+ // 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;
+ }
+ }
+ }
+ }
+
+ /* mark end of index */
+ idx->offset = 0L;
+ idx->driver = 0;
+ return count;
+}
+
+/**************************************************************************
+ * 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)
+{
+ char readbuf[16384];
+
+ *buffer = '\0';
+
+ if (!source_file)
+ {
+ /* find driver in datafile index */
+ while (idx->driver)
+ {
+ if (idx->driver == drv)
+ break;
+
+ idx++;
+ }
+ }
+ else
+ {
+ /* find source file in datafile index */
+ while (idx->driver)
+ {
+ if (idx->driver->source_file == drv->source_file)
+ break;
+
+ idx++;
+ }
+ }
+
+ if (idx->driver == 0)
+ return 1; /* driver not found in index */
+
+ /* seek to correct point in datafile */
+ if (ParseSeek (idx->offset, SEEK_SET))
+ return 1;
+
+ /* 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;
+
+ if (!core_strnicmp(tag, readbuf, strlen(tag)))
+ continue;
+
+ if (strlen(buffer) + strlen(readbuf) > bufsize)
+ break;
+
+ if (mameinfo)
+ {
+ char *temp = strtok(readbuf, "\r\n\r\n");
+ if (temp != nullptr)
+ strcat(buffer, temp);
+ else
+ strcat(buffer, readbuf);
+ }
+ else
+ strcat(buffer, readbuf);
+ }
+
+ return 0;
+}
+
+/**************************************************************************
+ * 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)
+{
+ int history = 0;
+
+ *buffer = 0;
+
+ 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)
+ {
+ if (ParseOpen(filename))
+ {
+ /* create index if necessary */
+ if (sysinfo_idx)
+ history = 1;
+ else
+ history = (index_datafile (&sysinfo_idx, 0) != 0);
+
+ /* load history text (append)*/
+ if (sysinfo_idx)
+ {
+ 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;
+ }
+
+ 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;
+ }
+
+ ParseClose();
+ }
+ }
+
+ strcat(buffer, "\n");
+ return (history == 0);
+}
+
+static int load_driver_mameinfo(const game_driver *drv, char *buffer, int bufsize, int filenum)
+{
+ machine_config config(*drv, MameUIGlobal());
+ const game_driver *parent = NULL;
+ char name[512];
+ int mameinfo = 0;
+ int is_bios = 0;
+
+ *buffer = 0;
+
+ 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;
+ }
+
+ if (filenum < 2)
+ {
+ /* List the game info 'flags' */
+ if (drv->flags & MACHINE_NOT_WORKING)
+ strcat(buffer, "THIS GAME DOESN'T WORK PROPERLY\n");
+
+ if (drv->flags & MACHINE_UNEMULATED_PROTECTION)
+ strcat(buffer, "The game has protection which isn't fully emulated.\n");
+
+ if (drv->flags & MACHINE_IMPERFECT_GRAPHICS)
+ strcat(buffer, "The video emulation isn't 100% accurate.\n");
+
+ if (drv->flags & MACHINE_WRONG_COLORS)
+ strcat(buffer, "The colors are completely wrong.\n");
+
+ 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");
+
+ if (drv->flags & MACHINE_IMPERFECT_SOUND)
+ strcat(buffer, "The sound emulation isn't 100% accurate.\n");
+
+ if (drv->flags & MACHINE_SUPPORTS_SAVE)
+ strcat(buffer, "Save state support.\n");
+
+ if (drv->flags & MACHINE_MECHANICAL)
+ strcat(buffer, "The game contains mechanical parts.\n");
+
+ strcat(buffer, "\n");
+
+ if (drv->flags & MACHINE_IS_BIOS_ROOT)
+ is_bios = 1;
+ }
+
+ /* 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);
+
+ /* load informational text (append) */
+ if (gameinit_idx)
+ {
+ int len = strlen(buffer);
+ int err = 0;
+ const game_driver *gdrv;
+ gdrv = drv;
+
+ do
+ {
+ err = load_datafile_text(gdrv, buffer + len, bufsize - len, gameinit_idx, DATAFILE_TAG_MAME, 0, 1);
+ int g = driver_list::clone(*gdrv);
+
+ if (g!=-1)
+ gdrv = &driver_list::driver(g);
+ else
+ gdrv = NULL;
+ } while (err && gdrv);
+
+ 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);
+
+ /* load informational text (append) */
+ if (mess_idx)
+ {
+ int len = strlen(buffer);
+ int err = 0;
+ const game_driver *gdrv;
+ gdrv = drv;
+
+ do
+ {
+ err = load_datafile_text(gdrv, buffer + len, bufsize - len, mess_idx, DATAFILE_TAG_MAME, 0, 1);
+ int g = driver_list::clone(*gdrv);
+
+ if (g!=-1)
+ gdrv = &driver_list::driver(g);
+ else
+ gdrv = NULL;
+ } while (err && gdrv);
+
+ 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);
+
+ /* load informational text (append) */
+ if (mame_idx)
+ {
+ int len = strlen(buffer);
+ int err = 0;
+ const game_driver *gdrv;
+ gdrv = drv;
+
+ do
+ {
+ err = load_datafile_text(gdrv, buffer + len, bufsize - len, mame_idx, DATAFILE_TAG_MAME, 0, 1);
+ int g = driver_list::clone(*gdrv);
+
+ if (g!=-1)
+ gdrv = &driver_list::driver(g);
+ else
+ gdrv = NULL;
+ } while (err && gdrv);
+
+ if (err)
+ mameinfo = 0;
+ }
+ }
+
+ 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);
+ else
+ snprintf(name, ARRAY_LENGTH(name), "%s %d.%03d kHz\n", cpu.device().name(), cpu.device().clock() / 1000, cpu.device().clock() % 1000);
+
+ strcat(buffer, name);
+ }
+
+ strcat(buffer, "\nSOUND:\n");
+ int has_sound = 0;
+ /* iterate over sound chips */
+
+ for (device_sound_interface &sound : sound_interface_iterator(config.root_device()))
+ {
+ char tmpname[1024];
+
+ snprintf(tmpname, ARRAY_LENGTH(tmpname), "%s", sound.device().name());
+ int clock = sound.device().clock();
+ has_sound = 1;
+
+ strcat(buffer, tmpname);
+
+ if (clock)
+ {
+ if (clock >= 1000000)
+ snprintf(name, ARRAY_LENGTH(name), " %d.%06d MHz", clock / 1000000, clock % 1000000);
+ else
+ snprintf(name, ARRAY_LENGTH(name), " %d.%03d kHz", clock / 1000, clock % 1000);
+
+ strcat(buffer, name);
+ }
+
+ strcat(buffer, "\n");
+ }
+
+ if (has_sound)
+ {
+ speaker_device_iterator iter(config.root_device());
+ int channels = iter.count();
+
+ if(channels == 1)
+ snprintf(name, ARRAY_LENGTH(name), "%d Channel\n",channels);
+ else
+ snprintf(name, ARRAY_LENGTH(name), "%dx Channels\n",channels);
+
+ strcat(buffer, name);
+ }
+
+ strcat(buffer, "\nVIDEO:\n");
+ screen_device_iterator screeniter(config.root_device());
+ const screen_device *screen1 = screeniter.first();
+
+ if (screen1 == nullptr)
+ strcat(buffer, "Screenless\n");
+ else if (screen1->screen_type() == SCREEN_TYPE_VECTOR)
+ strcat(buffer,"Vector\n");
+ else
+ {
+ for (screen_device &screen : screen_device_iterator(config.root_device()))
+ {
+ if (drv->flags & ORIENTATION_SWAP_XY)
+ snprintf(name, ARRAY_LENGTH(name), "%d x %d (V)", screen.visible_area().height(), screen.visible_area().width());
+ else
+ snprintf(name, ARRAY_LENGTH(name), "%d x %d (H)", screen.visible_area().width(), screen.visible_area().height());
+
+ strcat(buffer, name);
+ snprintf(name, ARRAY_LENGTH(name), " %f Hz", ATTOSECONDS_TO_HZ(screen.refresh_attoseconds()));
+ strcat(buffer, name);
+ strcat(buffer, "\n");
+ }
+ }
+
+ strcat(buffer, "\nROM REGION:\n");
+ int g = driver_list::clone(*drv);
+
+ if (g != -1)
+ parent = &driver_list::driver(g);
+
+ for (device_t &device : device_iterator(config.root_device()))
+ {
+ for (const rom_entry *region = rom_first_region(device); region; region = rom_next_region(region))
+ {
+ for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
+ {
+ util::hash_collection hashes(ROM_GETHASHDATA(rom));
+
+ 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));
+
+ 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");
+ }
+ }
+ }
+
+ for (samples_device &device : samples_device_iterator(config.root_device()))
+ {
+ samples_iterator sampiter(device);
+
+ if (sampiter.altbasename() )
+ {
+ snprintf(name, ARRAY_LENGTH(name), "\nSAMPLES (%s):\n", sampiter.altbasename());
+ strcat(buffer, name);
+ }
+
+ std::unordered_set<std::string> already_printed;
+
+ for (const char *samplename = sampiter.first(); samplename; samplename = sampiter.next())
+ {
+ // filter out duplicates
+ if (!already_printed.insert(samplename).second)
+ continue;
+
+ // output the sample name
+ snprintf(name, ARRAY_LENGTH(name), "%s.wav\n", samplename);
+ strcat(buffer, name);
+ }
+ }
+
+ if (!is_bios)
+ {
+ int g = driver_list::clone(*drv);
+
+ if (g != -1)
+ drv = &driver_list::driver(g);
+
+ strcat(buffer, "\nORIGINAL:\n");
+ strcat(buffer, drv->description);
+ strcat(buffer, "\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");
+ }
+ }
+ }
+
+ 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);
+ strcpy(source_file, temp.c_str());
+
+ *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))
+ {
+ 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);
+
+ /* 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);
+
+ if (err)
+ drivinfo = 0;
+ }
+ }
+ ParseClose();
+ }
+
+ strcat(buffer, "\nGAMES SUPPORTED:\n");
+
+ for (int i = 0; i < driver_list::total(); i++)
+ {
+ if (!strcmp(source_file, GetDriverFilename(i)) && !(DriverIsBios(i)))
+ {
+ strcat(buffer, driver_list::driver(i).description);
+ strcat(buffer,"\n");
+ }
+ }
+
+ strcat(buffer, "\n\n");
+ return (drivinfo == 0);
+}
+
+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");
+
+ /* try to open command datafile */
+ if (ParseOpen(filename))
+ {
+ /* create index if necessary */
+ if (cmd_idx)
+ command = 1;
+ else
+ command = (index_datafile (&cmd_idx, 0) != 0);
+
+ /* load informational text (append) */
+ if (cmd_idx)
+ {
+ int len = strlen(buffer);
+ int err = 0;
+ const game_driver *gdrv;
+ gdrv = drv;
+
+ do
+ {
+ 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;
+ }
+
+ ParseClose();
+ }
+
+ strcat(buffer, "\n\n");
+ return (command == 0);
+}
+
+static int load_driver_scoreinfo(const game_driver *drv, char *buffer, int bufsize)
+{
+ int scoreinfo = 0;
+
+ *buffer = 0;
+ snprintf(filename, ARRAY_LENGTH(filename), "%s\\story.dat", GetDatsDir());
+
+ /* try to open story datafile */
+ if (ParseOpen(filename))
+ {
+ /* create index if necessary */
+ if (score_idx)
+ scoreinfo = 1;
+ else
+ scoreinfo = (index_datafile (&score_idx, 0) != 0);
+
+ /* load informational text (append) */
+ if (score_idx)
+ {
+ int len = strlen(buffer);
+ int err = 0;
+ const game_driver *gdrv;
+ gdrv = drv;
+
+ do
+ {
+ 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;
+ }
+
+ ParseClose();
+ }
+
+ 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);
+
+ return ConvertToWindowsNewlines(dataBuf);
+}