summaryrefslogtreecommitdiffstats
path: root/docs/release/src/osd/winui/game_opts.h
diff options
context:
space:
mode:
Diffstat (limited to 'docs/release/src/osd/winui/game_opts.h')
-rw-r--r--docs/release/src/osd/winui/game_opts.h367
1 files changed, 367 insertions, 0 deletions
diff --git a/docs/release/src/osd/winui/game_opts.h b/docs/release/src/osd/winui/game_opts.h
new file mode 100644
index 00000000000..65bca005ea4
--- /dev/null
+++ b/docs/release/src/osd/winui/game_opts.h
@@ -0,0 +1,367 @@
+// For licensing and usage information, read docs/winui_license.txt
+// MASTER
+//****************************************************************************
+
+#ifndef WINUI_GAMEOPTS_H
+#define WINUI_GAMEOPTS_H
+
+class winui_game_options
+{
+ uint32_t m_total;
+ uint32_t m_cache;
+ uint32_t m_version;
+ bool m_rebuild;
+
+ struct driver_options
+ {
+ uint32_t game_number;
+ int rom;
+ int sample;
+ uint32_t cache_lower;
+ uint32_t cache_upper;
+ uint32_t play_count;
+ uint32_t play_time;
+ };
+
+ std::vector<driver_options> m_list;
+
+ // convert audit cache - normally only 1 digit, although we can do 2. If the input is -1, it is treated as invalid and -1 is returned.
+ int convert_to_int(const char* inp)
+ {
+ if (!inp)
+ return -1;
+ int c = inp[0];
+ if (c < 0x30 || c > 0x39)
+ return -1;
+ int oup = c - 0x30;
+ c = inp[1];
+ if (c < 0x30 || c > 0x39)
+ return oup;
+ else
+ return oup * 10 + (c - 0x30);
+ }
+
+ // convert all other numbers, up to end-of-string/invalid-character. If number is too large, return 0.
+ uint32_t convert_to_uint(const char* inp)
+ {
+ if (!inp)
+ return 0;
+ uint32_t oup = 0;
+ for (int i = 0; i < 11; i++)
+ {
+ int c = inp[i];
+ if (c >= 0x30 && c <= 0x39)
+ oup = oup * 10 + (c - 0x30);
+ else
+ return oup;
+ }
+ return 0; // numeric overflow
+ }
+
+ // true = recache needed
+ bool create_index(std::ifstream &fp)
+ {
+ // does file exist?
+ if (!fp.good())
+ return true;
+
+ // check first line is ok
+ string file_line;
+ std::getline(fp, file_line);
+ if (file_line.empty())
+ return true;
+
+ char s1[file_line.length()+1];
+ strcpy(s1, file_line.c_str());
+
+ // check that totals match
+ const char* s2 = strtok(s1, ",");
+ if (!s2)
+ return true; // file is corrupt
+
+ uint32_t total = convert_to_uint(s2);
+ if (total == m_total)
+ m_rebuild = false; // everything is fine so far
+
+ // check that versions match
+ s2 = strtok(NULL, ",");
+ if (!s2)
+ return true; // file is corrupt or old version
+
+ uint32_t version = convert_to_uint(s2);
+ if (version != m_version)
+ return true; // file is old version, complete rebuild necessary
+
+ // all good, read file to memory. If rebuild needed, it will overwrite cache, but we need the rest.
+ int index; // must be int for validity check below
+ bool is_ready = false;
+ std::getline(fp, file_line);
+ while (fp.good())
+ {
+ if (is_ready)
+ {
+ char s[file_line.length()+1];
+ strcpy(s, file_line.c_str());
+
+ const char* name = strtok(s, "\t"); // get driver name
+ index = driver_list::find(name);
+ if (index > -1)
+ {
+ char* data = strtok(NULL, ","); // get next part (old game number, ignore)
+ m_list[index].game_number = index; // get new game number
+ data = strtok(NULL, ","); // get next part
+ if (data)
+ m_list[index].rom = convert_to_int(data);
+ data = strtok(NULL, ","); // get next part
+ if (data)
+ m_list[index].sample = convert_to_int(data);
+ data = strtok(NULL, ","); // get next part
+ if (data)
+ m_list[index].cache_lower = convert_to_uint(data);
+ data = strtok(NULL, ","); // get next part
+ if (data)
+ m_list[index].cache_upper = convert_to_uint(data);
+ data = strtok(NULL, ","); // get next part
+ if (data)
+ m_list[index].play_count = convert_to_uint(data);
+ data = strtok(NULL, ","); // get next part
+ if (data)
+ m_list[index].play_time = convert_to_uint(data);
+ }
+ }
+ else
+ {
+ if (file_line == "$start")
+ is_ready = true;
+ }
+
+ std::getline(fp, file_line);
+ }
+
+ fp.close();
+ return m_rebuild;
+ }
+
+public:
+ // construction - runs before main
+ winui_game_options()
+ {
+ m_version = 1;
+ m_rebuild = true;
+ m_total = driver_list::total();
+ m_list.resize(m_total);
+ std::fill(m_list.begin(), m_list.end(), driver_options{0, -1, -1, 0, 0, 0, 0});
+ }
+
+ int rom(uint32_t index)
+ {
+ if (index < m_total)
+ return m_list[index].rom;
+ else
+ return -1;
+ }
+
+ void rom(uint32_t index, int val)
+ {
+ if (index < m_total)
+ m_list[index].rom = val;
+ }
+
+ int sample(uint32_t index)
+ {
+ if (index < m_total)
+ return m_list[index].sample;
+ else
+ return -1;
+ }
+
+ void sample(uint32_t index, int val)
+ {
+ if (index < m_total)
+ m_list[index].sample = val;
+ }
+
+ uint32_t cache_lower(uint32_t index)
+ {
+ if (index < m_total)
+ return m_list[index].cache_lower;
+ else
+ return 0;
+ }
+
+ uint32_t cache_upper(uint32_t index)
+ {
+ if (index < m_total)
+ return m_list[index].cache_upper;
+ else
+ return 0;
+ }
+
+ void cache_upper(uint32_t index, uint32_t val)
+ {
+ if (index < m_total)
+ m_list[index].cache_upper = val;
+ }
+
+ uint32_t play_count(uint32_t index)
+ {
+ if (index < m_total)
+ return m_list[index].play_count;
+ else
+ return 0;
+ }
+
+ void play_count(uint32_t index, int val)
+ {
+ if (index < m_total)
+ m_list[index].play_count = val;
+ }
+
+ uint32_t play_time(uint32_t index)
+ {
+ if (index < m_total)
+ return m_list[index].play_time;
+ else
+ return 0;
+ }
+
+ void play_time(uint32_t index, int val)
+ {
+ if (index < m_total)
+ m_list[index].play_time = val;
+ }
+
+ bool rebuild()
+ {
+ return m_rebuild;
+ }
+
+ void force_rebuild()
+ {
+ m_rebuild = true;
+ }
+
+ void load_file(const char *filename)
+ {
+ std::ifstream infile (filename);
+ if (create_index(infile))
+ {
+ // rebuild the cache
+ device_t::feature_type ft;
+ const game_driver *drv;
+ windows_options dummy;
+ printf("game_opts.cpp::load_file : Rebuilding cache\n");fflush(stdout);
+ for (uint32_t i = 0; i < m_total; i++)
+ {
+ uint32_t t = 0;
+ // BITS 0,1 = arcade, console, computer, other
+ drv = &driver_list::driver(i);
+ ui::machine_static_info const info(machine_config(*drv, dummy));
+ if ((info.machine_flags() & machine_flags::MASK_TYPE) == machine_flags::TYPE_CONSOLE)
+ t = 1;
+ else
+ if ((info.machine_flags() & machine_flags::MASK_TYPE) == machine_flags::TYPE_COMPUTER)
+ t = 2;
+ else
+ if ((info.machine_flags() & machine_flags::MASK_TYPE) == machine_flags::TYPE_OTHER)
+ t = 3;
+ m_cache = t;
+ // BIT 2 = SWAP_XY
+ t = (drv->flags & ORIENTATION_SWAP_XY) ? 0x0004 : 0;
+ m_cache |= t;
+ // BIT 6 = NOT_WORKING
+ t = (info.machine_flags() & machine_flags::NOT_WORKING) ? 0x0040 : 0;
+ m_cache |= t;
+ // BIT 7 = SUPPORTS_SAVE
+ t = (info.machine_flags() & machine_flags::SUPPORTS_SAVE) ? 0: 0x0080;
+ m_cache |= t;
+ // BIT 8 = NO_COCKTAIL
+ t = (info.machine_flags() & machine_flags::NO_COCKTAIL) ? 0x0100 : 0;
+ m_cache |= t;
+ // BIT 9 = IS_BIOS_ROOT
+ t = (info.machine_flags() & machine_flags::IS_BIOS_ROOT) ? 0x0200 : 0;
+ m_cache |= t;
+ // BIT 10 = REQUIRES_ARTWORK
+ t = (info.machine_flags() & machine_flags::REQUIRES_ARTWORK) ? 0x0400 : 0;
+ m_cache |= t;
+ // BIT 11 = CLICKABLE_ARTWORK
+ t = (info.machine_flags() & machine_flags::CLICKABLE_ARTWORK) ? 0x0800 : 0;
+ m_cache |= t;
+ // BIT 12 = UNOFFICIAL
+ t = (info.machine_flags() & machine_flags::UNOFFICIAL) ? 0x1000 : 0;
+ m_cache |= t;
+ // BIT 13 = NO_SOUND_HW
+ t = (info.machine_flags() & machine_flags::NO_SOUND_HW) ? 0x2000 : 0;
+ m_cache |= t;
+ // BIT 14 = MECHANICAL
+ t = (info.machine_flags() & machine_flags::MECHANICAL) ? 0x4000 : 0;
+ m_cache |= t;
+ // BIT 15 = IS_INCOMPLETE
+ t = (info.machine_flags() & machine_flags::IS_INCOMPLETE) ? 0x8000 : 0;
+ m_cache |= t;
+
+ ft = info.imperfect_features();
+ // BIT 16 = IMPERFECT_SOUND
+ t = (ft & device_t::feature::SOUND) ? 0x10000 : 0;
+ m_cache |= t;
+ // BIT 18 = IMPERFECT_GRAPHICS
+ t = (ft & device_t::feature::GRAPHICS) ? 0x40000 : 0;
+ m_cache |= t;
+ // BIT 20 = IMPERFECT_COLOUR
+ t = (ft & device_t::feature::PALETTE) ? 0x100000 : 0;
+ m_cache |= t;
+ // BIT 22 = PROTECTION
+ t = (ft & device_t::feature::PROTECTION) ? 0x400000 : 0;
+ m_cache |= t;
+ // BIT 23 = IMPERFECT_CONTROLS
+ t = (ft & device_t::feature::CONTROLS) ? 0x800000 : 0;
+ m_cache |= t;
+
+ ft = info.unemulated_features();
+ // BIT 17 = NO_SOUND
+ t = (ft & device_t::feature::SOUND) ? 0x20000 : 0;
+ m_cache |= t;
+ // BIT 19 = NO_GRAPHICS
+ t = (ft & device_t::feature::GRAPHICS) ? 0x80000 : 0;
+ m_cache |= t;
+ // BIT 21 = NO_COLOUR
+ t = (ft & device_t::feature::PALETTE) ? 0x200000 : 0;
+ m_cache |= t;
+
+ m_list[i].cache_lower = m_cache;
+ m_list[i].cache_upper = 0;
+ }
+ printf("game_opts.cpp::load_file : Finished Rebuilding cache\n");fflush(stdout);
+ }
+ }
+
+ void save_file(const char *filename)
+ {
+ string inistring = std::to_string(m_total).append(",").append(std::to_string(m_version)).append("\n");
+ inistring.append("YOU CAN SAFELY DELETE THIS FILE TO RESET THE GAME STATS.\n\n$start\n");
+
+ for (uint32_t i = 0; i < m_total; i++)
+ {
+ // 1:Game number(for debugging only), 2:Rom, 3:Sample, 4:Cache(New), 5:Cache(Legacy) 6:Play Count, 7:Play Time
+ inistring.append(driver_list::driver(i).name).append("\t");
+ inistring.append(std::to_string(m_list[i].game_number)).append(",");
+ inistring.append(std::to_string(m_list[i].rom)).append(",");
+ inistring.append(std::to_string(m_list[i].sample)).append(",");
+ inistring.append(std::to_string(m_list[i].cache_lower)).append(",");
+ inistring.append(std::to_string(m_list[i].cache_upper)).append(",");
+ inistring.append(std::to_string(m_list[i].play_count)).append(",");
+ inistring.append(std::to_string(m_list[i].play_time)).append("\n");
+ }
+
+ std::ofstream outfile (filename, std::ios::out | std::ios::trunc);
+ size_t size = inistring.size();
+ char t1[size+1];
+ strcpy(t1, inistring.c_str());
+ outfile.write(t1, size);
+ outfile.close();
+ return;
+ }
+};
+
+#endif // __GAME_OPTS_H__
+