diff --git a/source/frontends/common2/commonframe.cpp b/source/frontends/common2/commonframe.cpp index 744f6d0f..c23f83e8 100644 --- a/source/frontends/common2/commonframe.cpp +++ b/source/frontends/common2/commonframe.cpp @@ -60,57 +60,62 @@ namespace } -CommonFrame::CommonFrame() - : myResourcePath(getResourcePath()) +namespace common2 { -} - -void CommonFrame::Destroy() -{ - LinuxFrame::Destroy(); - myResource.clear(); -} - -BYTE* CommonFrame::GetResource(WORD id, LPCSTR lpType, DWORD expectedSize) -{ - myResource.clear(); - - const std::string & filename = getResourceName(id); - const std::string path = getResourcePath() + filename; - - const int fd = open(path.c_str(), O_RDONLY); - - if (fd != -1) + CommonFrame::CommonFrame() + : myResourcePath(getResourcePath()) { - struct stat stdbuf; - if ((fstat(fd, &stdbuf) == 0) && S_ISREG(stdbuf.st_mode)) + } + + + void CommonFrame::Destroy() + { + LinuxFrame::Destroy(); + myResource.clear(); + } + + BYTE* CommonFrame::GetResource(WORD id, LPCSTR lpType, DWORD expectedSize) + { + myResource.clear(); + + const std::string & filename = getResourceName(id); + const std::string path = getResourcePath() + filename; + + const int fd = open(path.c_str(), O_RDONLY); + + if (fd != -1) { - const off_t size = stdbuf.st_size; - std::vector data(size); - const ssize_t rd = read(fd, data.data(), size); - if (rd == expectedSize) + struct stat stdbuf; + if ((fstat(fd, &stdbuf) == 0) && S_ISREG(stdbuf.st_mode)) { - std::swap(myResource, data); + const off_t size = stdbuf.st_size; + std::vector data(size); + const ssize_t rd = read(fd, data.data(), size); + if (rd == expectedSize) + { + std::swap(myResource, data); + } } + close(fd); } - close(fd); + + if (myResource.empty()) + { + LogFileOutput("FindResource: could not load resource %s\n", filename.c_str()); + } + + return myResource.data(); } - if (myResource.empty()) + std::string CommonFrame::getBitmapFilename(const std::string & resource) { - LogFileOutput("FindResource: could not load resource %s\n", filename.c_str()); + if (resource == "CHARSET40") return "CHARSET4.BMP"; + if (resource == "CHARSET82") return "CHARSET82.bmp"; + if (resource == "CHARSET8M") return "CHARSET8M.bmp"; + if (resource == "CHARSET8C") return "CHARSET8C.bmp"; + + return resource; } - return myResource.data(); -} - -std::string CommonFrame::getBitmapFilename(const std::string & resource) -{ - if (resource == "CHARSET40") return "CHARSET4.BMP"; - if (resource == "CHARSET82") return "CHARSET82.bmp"; - if (resource == "CHARSET8M") return "CHARSET8M.bmp"; - if (resource == "CHARSET8C") return "CHARSET8C.bmp"; - - return resource; } diff --git a/source/frontends/common2/commonframe.h b/source/frontends/common2/commonframe.h index 8c25547b..67d30cba 100644 --- a/source/frontends/common2/commonframe.h +++ b/source/frontends/common2/commonframe.h @@ -4,18 +4,23 @@ #include #include -class CommonFrame : public LinuxFrame +namespace common2 { -public: - CommonFrame(); - void Destroy() override; + class CommonFrame : public LinuxFrame + { + public: + CommonFrame(); - BYTE* GetResource(WORD id, LPCSTR lpType, DWORD expectedSize) override; + void Destroy() override; -protected: - static std::string getBitmapFilename(const std::string & resource); + BYTE* GetResource(WORD id, LPCSTR lpType, DWORD expectedSize) override; - const std::string myResourcePath; - std::vector myResource; -}; + protected: + static std::string getBitmapFilename(const std::string & resource); + + const std::string myResourcePath; + std::vector myResource; + }; + +} diff --git a/source/frontends/common2/fileregistry.cpp b/source/frontends/common2/fileregistry.cpp index 4db2de50..4e692fa0 100644 --- a/source/frontends/common2/fileregistry.cpp +++ b/source/frontends/common2/fileregistry.cpp @@ -39,7 +39,7 @@ namespace return std::string(homeDir); } - class Configuration : public PTreeRegistry + class Configuration : public common2::PTreeRegistry { public: Configuration(const std::string & filename, const bool saveOnExit); @@ -84,42 +84,47 @@ namespace } -std::string GetConfigFile(const std::string & filename) +namespace common2 { - const std::string dir = getHomeDir() + "/.applewin"; - const int status = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); - if (!status || (errno == EEXIST)) + + std::string GetConfigFile(const std::string & filename) { - return dir + "/" + filename; + const std::string dir = getHomeDir() + "/.applewin"; + const int status = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + if (!status || (errno == EEXIST)) + { + return dir + "/" + filename; + } + else + { + const char * s = strerror(errno); + LogFileOutput("No registry. Cannot create %s in %s: %s\n", filename.c_str(), dir.c_str(), s); + return std::string(); + } } - else + + void InitializeFileRegistry(const EmulatorOptions & options) { - const char * s = strerror(errno); - LogFileOutput("No registry. Cannot create %s in %s: %s\n", filename.c_str(), dir.c_str(), s); - return std::string(); + const std::string homeDir = getHomeDir(); + + std::string filename; + bool saveOnExit; + + if (options.useQtIni) + { + filename = homeDir + "/.config/" + ORGANIZATION_NAME + "/" + APPLICATION_NAME + ".conf"; + saveOnExit = false; + } + else + { + filename = GetConfigFile("applewin.conf"); + saveOnExit = !filename.empty() && options.saveConfigurationOnExit; + } + + std::shared_ptr config(new Configuration(filename, saveOnExit)); + config->addExtraOptions(options.registryOptions); + + Registry::instance = config; } -} - -void InitializeFileRegistry(const EmulatorOptions & options) -{ - const std::string homeDir = getHomeDir(); - - std::string filename; - bool saveOnExit; - - if (options.useQtIni) - { - filename = homeDir + "/.config/" + ORGANIZATION_NAME + "/" + APPLICATION_NAME + ".conf"; - saveOnExit = false; - } - else - { - filename = GetConfigFile("applewin.conf"); - saveOnExit = !filename.empty() && options.saveConfigurationOnExit; - } - - std::shared_ptr config(new Configuration(filename, saveOnExit)); - config->addExtraOptions(options.registryOptions); - - Registry::instance = config; + } diff --git a/source/frontends/common2/fileregistry.h b/source/frontends/common2/fileregistry.h index ae5124bb..4d51a665 100644 --- a/source/frontends/common2/fileregistry.h +++ b/source/frontends/common2/fileregistry.h @@ -2,7 +2,12 @@ #include -struct EmulatorOptions; +namespace common2 +{ -std::string GetConfigFile(const std::string & filename); -void InitializeFileRegistry(const EmulatorOptions & options); + struct EmulatorOptions; + + std::string GetConfigFile(const std::string & filename); + void InitializeFileRegistry(const EmulatorOptions & options); + +} diff --git a/source/frontends/common2/programoptions.cpp b/source/frontends/common2/programoptions.cpp index 3b98fc4f..f4939a0e 100644 --- a/source/frontends/common2/programoptions.cpp +++ b/source/frontends/common2/programoptions.cpp @@ -19,7 +19,7 @@ namespace po = boost::program_options; namespace { - void parseGeometry(const std::string & s, Geometry & geometry) + void parseGeometry(const std::string & s, common2::Geometry & geometry) { std::smatch m; if (std::regex_match(s, m, std::regex("^(\\d+)x(\\d+)(\\+(\\d+)\\+(\\d+))?$"))) @@ -42,174 +42,179 @@ namespace } -bool getEmulatorOptions(int argc, const char * argv [], const std::string & edition, EmulatorOptions & options) +namespace common2 { - const std::string name = "Apple Emulator for " + edition + " (based on AppleWin " + getVersion() + ")"; - po::options_description desc(name); - desc.add_options() - ("help,h", "Print this help message") - ; - po::options_description configDesc("configuration"); - configDesc.add_options() - ("save-conf", "Save configuration on exit") - ("config,c", po::value>(), "Registry options section.path=value") - ("qt-ini,q", "Use Qt ini file (read only)") - ; - desc.add(configDesc); - - po::options_description diskDesc("Disk"); - diskDesc.add_options() - ("d1,1", po::value(), "Disk in 1st drive") - ("d2,2", po::value(), "Disk in 2nd drive") - ; - desc.add(diskDesc); - - po::options_description snapshotDesc("Snapshot"); - snapshotDesc.add_options() - ("state-filename,f", po::value(), "Set snapshot filename") - ("load-state,s", po::value(), "Load snapshot from file") - ; - desc.add(snapshotDesc); - - po::options_description memoryDesc("Memory"); - memoryDesc.add_options() - ("memclear", po::value()->default_value(options.memclear), "Memory initialization pattern [0..7]") - ; - desc.add(memoryDesc); - - po::options_description emulatorDesc("Emulator"); - emulatorDesc.add_options() - ("log", "Log to AppleWin.log") - ("headless", "Headless: disable video (freewheel)") - ("fixed-speed", "Fixed (non-adaptive) speed") - ("ntsc,nt", "NTSC: execute NTSC code") - ("benchmark,b", "Benchmark emulator") - ; - desc.add(emulatorDesc); - - po::options_description sdlDesc("SDL"); - sdlDesc.add_options() - ("multi-threaded,m", "Multi threaded") - ("timer-interval,i", po::value()->default_value(options.timerInterval), "Timer interval in ms") - ("loose-mutex,l", "Loose mutex") - ("sdl-driver", po::value()->default_value(options.sdlDriver), "SDL driver") - ("gl-swap", po::value()->default_value(options.glSwapInterval), "SDL_GL_SwapInterval") - ("imgui", "Render with Dear ImGui") - ("geometry", po::value(), "WxH(+X+Y)") - ; - desc.add(sdlDesc); - - po::options_description paddleDesc("Paddle"); - paddleDesc.add_options() - ("no-squaring", "Gamepad range is (already) a square") - ("device-name", po::value(), "Gamepad device name") - ; - desc.add(paddleDesc); - - po::variables_map vm; - try + bool getEmulatorOptions(int argc, const char * argv [], const std::string & edition, EmulatorOptions & options) { - po::store(po::parse_command_line(argc, argv, desc), vm); + const std::string name = "Apple Emulator for " + edition + " (based on AppleWin " + getVersion() + ")"; + po::options_description desc(name); + desc.add_options() + ("help,h", "Print this help message") + ; - if (vm.count("help")) + po::options_description configDesc("configuration"); + configDesc.add_options() + ("save-conf", "Save configuration on exit") + ("config,c", po::value>(), "Registry options section.path=value") + ("qt-ini,q", "Use Qt ini file (read only)") + ; + desc.add(configDesc); + + po::options_description diskDesc("Disk"); + diskDesc.add_options() + ("d1,1", po::value(), "Disk in 1st drive") + ("d2,2", po::value(), "Disk in 2nd drive") + ; + desc.add(diskDesc); + + po::options_description snapshotDesc("Snapshot"); + snapshotDesc.add_options() + ("state-filename,f", po::value(), "Set snapshot filename") + ("load-state,s", po::value(), "Load snapshot from file") + ; + desc.add(snapshotDesc); + + po::options_description memoryDesc("Memory"); + memoryDesc.add_options() + ("memclear", po::value()->default_value(options.memclear), "Memory initialization pattern [0..7]") + ; + desc.add(memoryDesc); + + po::options_description emulatorDesc("Emulator"); + emulatorDesc.add_options() + ("log", "Log to AppleWin.log") + ("headless", "Headless: disable video (freewheel)") + ("fixed-speed", "Fixed (non-adaptive) speed") + ("ntsc,nt", "NTSC: execute NTSC code") + ("benchmark,b", "Benchmark emulator") + ; + desc.add(emulatorDesc); + + po::options_description sdlDesc("SDL"); + sdlDesc.add_options() + ("multi-threaded,m", "Multi threaded") + ("timer-interval,i", po::value()->default_value(options.timerInterval), "Timer interval in ms") + ("loose-mutex,l", "Loose mutex") + ("sdl-driver", po::value()->default_value(options.sdlDriver), "SDL driver") + ("gl-swap", po::value()->default_value(options.glSwapInterval), "SDL_GL_SwapInterval") + ("imgui", "Render with Dear ImGui") + ("geometry", po::value(), "WxH(+X+Y)") + ; + desc.add(sdlDesc); + + po::options_description paddleDesc("Paddle"); + paddleDesc.add_options() + ("no-squaring", "Gamepad range is (already) a square") + ("device-name", po::value(), "Gamepad device name") + ; + desc.add(paddleDesc); + + po::variables_map vm; + try { - std::cout << desc << std::endl; + po::store(po::parse_command_line(argc, argv, desc), vm); + + if (vm.count("help")) + { + std::cout << desc << std::endl; + return false; + } + + options.saveConfigurationOnExit = vm.count("save-conf"); + options.useQtIni = vm.count("qt-ini"); + options.multiThreaded = vm.count("multi-threaded"); + options.looseMutex = vm.count("loose-mutex"); + options.timerInterval = vm["timer-interval"].as(); + options.sdlDriver = vm["sdl-driver"].as(); + options.glSwapInterval = vm["gl-swap"].as(); + options.imgui = vm.count("imgui"); + + if (vm.count("config")) + { + options.registryOptions = vm["config"].as >(); + } + + if (vm.count("d1")) + { + options.disk1 = vm["d1"].as(); + } + + if (vm.count("d2")) + { + options.disk2 = vm["d2"].as(); + } + + if (vm.count("load-state")) + { + options.snapshotFilename = vm["load-state"].as(); + options.loadSnapshot = true; + } + + if (vm.count("state-filename")) + { + options.snapshotFilename = vm["state-filename"].as(); + options.loadSnapshot = false; + } + + const int memclear = vm["memclear"].as(); + if (memclear >=0 && memclear < NUM_MIP) + options.memclear = memclear; + + options.benchmark = vm.count("benchmark") > 0; + options.headless = vm.count("headless") > 0; + options.log = vm.count("log") > 0; + options.ntsc = vm.count("ntsc") > 0; + options.fixedSpeed = vm.count("fixed-speed") > 0; + + options.paddleSquaring = vm.count("no-squaring") == 0; + if (vm.count("device-name")) + { + options.paddleDeviceName = vm["device-name"].as(); + } + + if (vm.count("geometry")) + { + parseGeometry(vm["geometry"].as(), options.geometry); + } + + return true; + } + catch (const po::error& e) + { + std::cerr << "ERROR: " << e.what() << std::endl << desc << std::endl; return false; } - - options.saveConfigurationOnExit = vm.count("save-conf"); - options.useQtIni = vm.count("qt-ini"); - options.multiThreaded = vm.count("multi-threaded"); - options.looseMutex = vm.count("loose-mutex"); - options.timerInterval = vm["timer-interval"].as(); - options.sdlDriver = vm["sdl-driver"].as(); - options.glSwapInterval = vm["gl-swap"].as(); - options.imgui = vm.count("imgui"); - - if (vm.count("config")) + catch (const std::exception & e) { - options.registryOptions = vm["config"].as >(); + std::cerr << "ERROR: " << e.what() << std::endl; + return false; } - - if (vm.count("d1")) - { - options.disk1 = vm["d1"].as(); - } - - if (vm.count("d2")) - { - options.disk2 = vm["d2"].as(); - } - - if (vm.count("load-state")) - { - options.snapshotFilename = vm["load-state"].as(); - options.loadSnapshot = true; - } - - if (vm.count("state-filename")) - { - options.snapshotFilename = vm["state-filename"].as(); - options.loadSnapshot = false; - } - - const int memclear = vm["memclear"].as(); - if (memclear >=0 && memclear < NUM_MIP) - options.memclear = memclear; - - options.benchmark = vm.count("benchmark") > 0; - options.headless = vm.count("headless") > 0; - options.log = vm.count("log") > 0; - options.ntsc = vm.count("ntsc") > 0; - options.fixedSpeed = vm.count("fixed-speed") > 0; - - options.paddleSquaring = vm.count("no-squaring") == 0; - if (vm.count("device-name")) - { - options.paddleDeviceName = vm["device-name"].as(); - } - - if (vm.count("geometry")) - { - parseGeometry(vm["geometry"].as(), options.geometry); - } - - return true; } - catch (const po::error& e) + + void applyOptions(const EmulatorOptions & options) { - std::cerr << "ERROR: " << e.what() << std::endl << desc << std::endl; - return false; - } - catch (const std::exception & e) - { - std::cerr << "ERROR: " << e.what() << std::endl; - return false; + bool disksOk = true; + if (!options.disk1.empty()) + { + const bool ok = DoDiskInsert(SLOT6, DRIVE_1, options.disk1.c_str()); + disksOk = disksOk && ok; + LogFileOutput("Init: DoDiskInsert(D1), res=%d\n", ok); + } + + if (!options.disk2.empty()) + { + const bool ok = DoDiskInsert(SLOT6, DRIVE_2, options.disk2.c_str()); + disksOk = disksOk && ok; + LogFileOutput("Init: DoDiskInsert(D2), res=%d\n", ok); + } + + if (!options.snapshotFilename.empty()) + { + setSnapshotFilename(options.snapshotFilename, options.loadSnapshot); + } + + Paddle::setSquaring(options.paddleSquaring); } -} - -void applyOptions(const EmulatorOptions & options) -{ - bool disksOk = true; - if (!options.disk1.empty()) - { - const bool ok = DoDiskInsert(SLOT6, DRIVE_1, options.disk1.c_str()); - disksOk = disksOk && ok; - LogFileOutput("Init: DoDiskInsert(D1), res=%d\n", ok); - } - - if (!options.disk2.empty()) - { - const bool ok = DoDiskInsert(SLOT6, DRIVE_2, options.disk2.c_str()); - disksOk = disksOk && ok; - LogFileOutput("Init: DoDiskInsert(D2), res=%d\n", ok); - } - - if (!options.snapshotFilename.empty()) - { - setSnapshotFilename(options.snapshotFilename, options.loadSnapshot); - } - - Paddle::setSquaring(options.paddleSquaring); + } diff --git a/source/frontends/common2/programoptions.h b/source/frontends/common2/programoptions.h index b535e732..55ac08fc 100644 --- a/source/frontends/common2/programoptions.h +++ b/source/frontends/common2/programoptions.h @@ -3,55 +3,59 @@ #include #include - -struct Geometry +namespace common2 { - int width; - int height; - int x; - int y; -}; + + struct Geometry + { + int width; + int height; + int x; + int y; + }; -struct EmulatorOptions -{ - std::string disk1; - std::string disk2; + struct EmulatorOptions + { + std::string disk1; + std::string disk2; - std::string snapshotFilename; - bool loadSnapshot = false; + std::string snapshotFilename; + bool loadSnapshot = false; - int memclear = 0; + int memclear = 0; - bool log = false; + bool log = false; - bool benchmark = false; - bool headless = false; - bool ntsc = false; // only for applen + bool benchmark = false; + bool headless = false; + bool ntsc = false; // only for applen - bool paddleSquaring = true; // turn the x/y range to a square - // on my PC it is something like - // "/dev/input/by-id/usb-©Microsoft_Corporation_Controller_1BBE3DB-event-joystick" - std::string paddleDeviceName; + bool paddleSquaring = true; // turn the x/y range to a square + // on my PC it is something like + // "/dev/input/by-id/usb-©Microsoft_Corporation_Controller_1BBE3DB-event-joystick" + std::string paddleDeviceName; - bool saveConfigurationOnExit = false; - bool useQtIni = false; // use Qt .ini file (read only) + bool saveConfigurationOnExit = false; + bool useQtIni = false; // use Qt .ini file (read only) - bool run = true; // false if options include "-h" + bool run = true; // false if options include "-h" - bool multiThreaded = false; - bool looseMutex = false; // whether SDL_UpdateTexture is mutex protected (from CPU) - int timerInterval = 16; // only when multithreaded - bool fixedSpeed = false; // default adaptive + bool multiThreaded = false; + bool looseMutex = false; // whether SDL_UpdateTexture is mutex protected (from CPU) + int timerInterval = 16; // only when multithreaded + bool fixedSpeed = false; // default adaptive - int sdlDriver = -1; // default = -1 to let SDL choose - bool imgui = false; // use imgui renderer - Geometry geometry; // must be initialised with defaults - int glSwapInterval = 1; // SDL_GL_SetSwapInterval + int sdlDriver = -1; // default = -1 to let SDL choose + bool imgui = false; // use imgui renderer + Geometry geometry; // must be initialised with defaults + int glSwapInterval = 1; // SDL_GL_SetSwapInterval - std::vector registryOptions; -}; + std::vector registryOptions; + }; -bool getEmulatorOptions(int argc, const char * argv [], const std::string & edition, EmulatorOptions & options); + bool getEmulatorOptions(int argc, const char * argv [], const std::string & edition, EmulatorOptions & options); -void applyOptions(const EmulatorOptions & options); + void applyOptions(const EmulatorOptions & options); + +} diff --git a/source/frontends/common2/ptreeregistry.cpp b/source/frontends/common2/ptreeregistry.cpp index eb22868c..671be460 100644 --- a/source/frontends/common2/ptreeregistry.cpp +++ b/source/frontends/common2/ptreeregistry.cpp @@ -16,49 +16,54 @@ namespace } -bool PTreeRegistry::KeyQtEncodedLess::operator()(const std::string & lhs, const std::string & rhs) const +namespace common2 { - const std::string key1 = decodeKey(lhs); - const std::string key2 = decodeKey(rhs); - return key1 < key2; -} -std::string PTreeRegistry::getString(const std::string & section, const std::string & key) const -{ - return getValue(section, key); -} + bool PTreeRegistry::KeyQtEncodedLess::operator()(const std::string & lhs, const std::string & rhs) const + { + const std::string key1 = decodeKey(lhs); + const std::string key2 = decodeKey(rhs); + return key1 < key2; + } -DWORD PTreeRegistry::getDWord(const std::string & section, const std::string & key) const -{ - return getValue(section, key); -} + std::string PTreeRegistry::getString(const std::string & section, const std::string & key) const + { + return getValue(section, key); + } -bool PTreeRegistry::getBool(const std::string & section, const std::string & key) const -{ - return getValue(section, key); -} + DWORD PTreeRegistry::getDWord(const std::string & section, const std::string & key) const + { + return getValue(section, key); + } -void PTreeRegistry::putString(const std::string & section, const std::string & key, const std::string & value) -{ - putValue(section, key, value); -} + bool PTreeRegistry::getBool(const std::string & section, const std::string & key) const + { + return getValue(section, key); + } -void PTreeRegistry::putDWord(const std::string & section, const std::string & key, const DWORD value) -{ - putValue(section, key, value); -} + void PTreeRegistry::putString(const std::string & section, const std::string & key, const std::string & value) + { + putValue(section, key, value); + } -template -T PTreeRegistry::getValue(const std::string & section, const std::string & key) const -{ - const std::string path = section + "." + key; - const T value = myINI.get(path); - return value; -} + void PTreeRegistry::putDWord(const std::string & section, const std::string & key, const DWORD value) + { + putValue(section, key, value); + } + + template + T PTreeRegistry::getValue(const std::string & section, const std::string & key) const + { + const std::string path = section + "." + key; + const T value = myINI.get(path); + return value; + } + + template + void PTreeRegistry::putValue(const std::string & section, const std::string & key, const T & value) + { + const std::string path = section + "." + key; + myINI.put(path, value); + } -template -void PTreeRegistry::putValue(const std::string & section, const std::string & key, const T & value) -{ - const std::string path = section + "." + key; - myINI.put(path, value); } diff --git a/source/frontends/common2/ptreeregistry.h b/source/frontends/common2/ptreeregistry.h index 4c0945f8..443615de 100644 --- a/source/frontends/common2/ptreeregistry.h +++ b/source/frontends/common2/ptreeregistry.h @@ -4,33 +4,37 @@ #include #include - -class PTreeRegistry : public Registry +namespace common2 { -public: - struct KeyQtEncodedLess + + class PTreeRegistry : public Registry { - // this function is used to make the Qt registry compatible with sa2 and napple - // it is here, in the base class PTreeRegistry simply because it makes things easier - // KeyQtEncodedLess goes in the typedef init_t below - bool operator()(const std::string & lhs, const std::string & rhs) const; + public: + struct KeyQtEncodedLess + { + // this function is used to make the Qt registry compatible with sa2 and napple + // it is here, in the base class PTreeRegistry simply because it makes things easier + // KeyQtEncodedLess goes in the typedef init_t below + bool operator()(const std::string & lhs, const std::string & rhs) const; + }; + + typedef boost::property_tree::basic_ptree ini_t; + + std::string getString(const std::string & section, const std::string & key) const override; + DWORD getDWord(const std::string & section, const std::string & key) const override; + bool getBool(const std::string & section, const std::string & key) const override; + + void putString(const std::string & section, const std::string & key, const std::string & value) override; + void putDWord(const std::string & section, const std::string & key, const DWORD value) override; + + template + T getValue(const std::string & section, const std::string & key) const; + + template + void putValue(const std::string & section, const std::string & key, const T & value); + + protected: + ini_t myINI; }; - typedef boost::property_tree::basic_ptree ini_t; - - std::string getString(const std::string & section, const std::string & key) const override; - DWORD getDWord(const std::string & section, const std::string & key) const override; - bool getBool(const std::string & section, const std::string & key) const override; - - void putString(const std::string & section, const std::string & key, const std::string & value) override; - void putDWord(const std::string & section, const std::string & key, const DWORD value) override; - - template - T getValue(const std::string & section, const std::string & key) const; - - template - void putValue(const std::string & section, const std::string & key, const T & value); - -protected: - ini_t myINI; -}; +} diff --git a/source/frontends/common2/speed.cpp b/source/frontends/common2/speed.cpp index 17ba0c54..9ea5ab9c 100644 --- a/source/frontends/common2/speed.cpp +++ b/source/frontends/common2/speed.cpp @@ -4,46 +4,51 @@ #include "CPU.h" #include "Core.h" -Speed::Speed(const bool fixedSpeed) - : myFixedSpeed(fixedSpeed) +namespace common2 { - reset(); -} -void Speed::reset() -{ - myStartTime = std::chrono::steady_clock::now(); - myStartCycles = g_nCumulativeCycles; -} - -size_t Speed::getCyclesTillNext(const size_t microseconds) const -{ - if (myFixedSpeed) + Speed::Speed(const bool fixedSpeed) + : myFixedSpeed(fixedSpeed) { - const size_t cycles = static_cast(microseconds * g_fCurrentCLK6502 * 1.0e-6); - return cycles; + reset(); } - else + + void Speed::reset() { - const uint64_t currentCycles = g_nCumulativeCycles; - const auto currentTime = std::chrono::steady_clock::now(); + myStartTime = std::chrono::steady_clock::now(); + myStartCycles = g_nCumulativeCycles; + } - const auto currentDelta = std::chrono::duration_cast(currentTime - myStartTime).count(); - // target the next time we will be called - const auto targetDeltaInMicros = currentDelta + microseconds; - - const uint64_t targetCycles = static_cast(targetDeltaInMicros * g_fCurrentCLK6502 * 1.0e-6) + myStartCycles; - if (targetCycles > currentCycles) + size_t Speed::getCyclesTillNext(const size_t microseconds) const + { + if (myFixedSpeed) { - // number of cycles to fill this period - const uint64_t cyclesToExecute = targetCycles - currentCycles; - return cyclesToExecute; + const size_t cycles = static_cast(microseconds * g_fCurrentCLK6502 * 1.0e-6); + return cycles; } else { - // we got ahead, nothing to do this time - // CpuExecute will still execute 1 instruction, which does not cause any issues - return 0; + const uint64_t currentCycles = g_nCumulativeCycles; + const auto currentTime = std::chrono::steady_clock::now(); + + const auto currentDelta = std::chrono::duration_cast(currentTime - myStartTime).count(); + // target the next time we will be called + const auto targetDeltaInMicros = currentDelta + microseconds; + + const uint64_t targetCycles = static_cast(targetDeltaInMicros * g_fCurrentCLK6502 * 1.0e-6) + myStartCycles; + if (targetCycles > currentCycles) + { + // number of cycles to fill this period + const uint64_t cyclesToExecute = targetCycles - currentCycles; + return cyclesToExecute; + } + else + { + // we got ahead, nothing to do this time + // CpuExecute will still execute 1 instruction, which does not cause any issues + return 0; + } } } + } diff --git a/source/frontends/common2/speed.h b/source/frontends/common2/speed.h index df3db64e..220dca69 100644 --- a/source/frontends/common2/speed.h +++ b/source/frontends/common2/speed.h @@ -2,20 +2,25 @@ #include -class Speed +namespace common2 { -public: - Speed(const bool fixedSpeed); - void reset(); + class Speed + { + public: + Speed(const bool fixedSpeed); - // calculate the number of cycles to execute in the current period - // assuming the next call will happen in x microseconds - size_t getCyclesTillNext(const size_t microseconds) const; + void reset(); -private: + // calculate the number of cycles to execute in the current period + // assuming the next call will happen in x microseconds + size_t getCyclesTillNext(const size_t microseconds) const; - const bool myFixedSpeed; - std::chrono::time_point myStartTime; - uint64_t myStartCycles; -}; + private: + + const bool myFixedSpeed; + std::chrono::time_point myStartTime; + uint64_t myStartCycles; + }; + +} diff --git a/source/frontends/common2/timer.cpp b/source/frontends/common2/timer.cpp index bb1519da..dc92364e 100644 --- a/source/frontends/common2/timer.cpp +++ b/source/frontends/common2/timer.cpp @@ -4,45 +4,50 @@ #include #include -Timer::Timer() - : mySum(0) - , mySum2(0) - , myN(0) +namespace common2 { - tic(); -} -void Timer::tic() -{ - myT0 = std::chrono::steady_clock::now(); -} + Timer::Timer() + : mySum(0) + , mySum2(0) + , myN(0) + { + tic(); + } -void Timer::toc() -{ - const auto now = std::chrono::steady_clock::now(); - const auto micros = std::chrono::duration_cast(now - myT0).count(); - const double s = micros * 0.000001; - mySum += s; - mySum2 += s * s; - ++myN; - myT0 = now; -} + void Timer::tic() + { + myT0 = std::chrono::steady_clock::now(); + } -double Timer::getTimeInSeconds() const -{ - return mySum; -} + void Timer::toc() + { + const auto now = std::chrono::steady_clock::now(); + const auto micros = std::chrono::duration_cast(now - myT0).count(); + const double s = micros * 0.000001; + mySum += s; + mySum2 += s * s; + ++myN; + myT0 = now; + } + + double Timer::getTimeInSeconds() const + { + return mySum; + } + + std::ostream& operator<<(std::ostream& os, const Timer & timer) + { + const int width = 10; + const double m1 = timer.mySum / timer.myN; + const double m2 = timer.mySum2 / timer.myN; + const double std = std::sqrt(std::max(0.0, m2 - m1 * m1)); + const double scale = 1000; + os << "total = " << std::setw(width) << timer.mySum * scale << " ms"; + os << ", mean = " << std::setw(width) << m1 * scale << " ms"; + os << ", std = " << std::setw(width) << std * scale << " ms"; + os << ", n = " << std::setw(6) << timer.myN; + return os; + } -std::ostream& operator<<(std::ostream& os, const Timer & timer) -{ - const int width = 10; - const double m1 = timer.mySum / timer.myN; - const double m2 = timer.mySum2 / timer.myN; - const double std = std::sqrt(std::max(0.0, m2 - m1 * m1)); - const double scale = 1000; - os << "total = " << std::setw(width) << timer.mySum * scale << " ms"; - os << ", mean = " << std::setw(width) << m1 * scale << " ms"; - os << ", std = " << std::setw(width) << std * scale << " ms"; - os << ", n = " << std::setw(6) << timer.myN; - return os; } diff --git a/source/frontends/common2/timer.h b/source/frontends/common2/timer.h index dd0fa61c..88ac7db4 100644 --- a/source/frontends/common2/timer.h +++ b/source/frontends/common2/timer.h @@ -1,24 +1,29 @@ #include #include -class Timer +namespace common2 { -public: - Timer(); - void tic(); - void toc(); - double getTimeInSeconds() const; + class Timer + { + public: + Timer(); + void tic(); + void toc(); - friend std::ostream& operator<<(std::ostream& os, const Timer & timer); + double getTimeInSeconds() const; -private: + friend std::ostream& operator<<(std::ostream& os, const Timer & timer); - std::chrono::time_point myT0; + private: - double mySum; - double mySum2; - int myN; -}; + std::chrono::time_point myT0; -std::ostream& operator<<(std::ostream& os, const Timer & timer); + double mySum; + double mySum2; + int myN; + }; + + std::ostream& operator<<(std::ostream& os, const Timer & timer); + +} diff --git a/source/frontends/common2/utils.cpp b/source/frontends/common2/utils.cpp index c79b30c4..260e17c3 100644 --- a/source/frontends/common2/utils.cpp +++ b/source/frontends/common2/utils.cpp @@ -30,82 +30,87 @@ #include #include -void setSnapshotFilename(const std::string & filename, const bool load) +namespace common2 { - // same logic as qapple - // setting chdir allows to load relative disks from the snapshot file (tests?) - // but if the snapshot file itself is relative, it wont work after a chdir - // so we convert to absolute first - char * absPath = realpath(filename.c_str(), nullptr); - if (absPath) + + void setSnapshotFilename(const std::string & filename, const bool load) { - char * temp = strdup(absPath); - const char * dir = dirname(temp); - // dir points inside temp! - chdir(dir); - Snapshot_SetFilename(absPath); - - free(temp); - free(absPath); - - if (load) + // same logic as qapple + // setting chdir allows to load relative disks from the snapshot file (tests?) + // but if the snapshot file itself is relative, it wont work after a chdir + // so we convert to absolute first + char * absPath = realpath(filename.c_str(), nullptr); + if (absPath) { - Snapshot_LoadState(); + char * temp = strdup(absPath); + const char * dir = dirname(temp); + // dir points inside temp! + chdir(dir); + Snapshot_SetFilename(absPath); + + free(temp); + free(absPath); + + if (load) + { + Snapshot_LoadState(); + } } } -} -Initialisation::Initialisation() -{ + Initialisation::Initialisation() + { #ifdef RIFF_SPKR - RiffInitWriteFile("/tmp/Spkr.wav", SPKR_SAMPLE_RATE, 1); + RiffInitWriteFile("/tmp/Spkr.wav", SPKR_SAMPLE_RATE, 1); #endif #ifdef RIFF_MB - RiffInitWriteFile("/tmp/Mockingboard.wav", 44100, 2); + RiffInitWriteFile("/tmp/Mockingboard.wav", 44100, 2); #endif - g_nAppMode = MODE_RUNNING; - LogFileOutput("Initialisation\n"); + g_nAppMode = MODE_RUNNING; + LogFileOutput("Initialisation\n"); - g_bFullSpeed = false; + g_bFullSpeed = false; - LoadConfiguration(); - SetCurrentCLK6502(); - GetAppleWindowTitle(); - GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES | DRAW_DISK_STATUS); + LoadConfiguration(); + SetCurrentCLK6502(); + GetAppleWindowTitle(); + GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES | DRAW_DISK_STATUS); - DSInit(); - MB_Initialize(); - SpkrInitialize(); + DSInit(); + MB_Initialize(); + SpkrInitialize(); - MemInitialize(); - GetFrame().Initialize(); + MemInitialize(); + GetFrame().Initialize(); - GetCardMgr().GetDisk2CardMgr().Reset(); - HD_Reset(); - Snapshot_Startup(); -} - -Initialisation::~Initialisation() -{ - Snapshot_Shutdown(); - CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard(); - if (pMouseCard) - { - pMouseCard->Reset(); + GetCardMgr().GetDisk2CardMgr().Reset(); + HD_Reset(); + Snapshot_Startup(); } - MemDestroy(); - GetFrame().Destroy(); - SpkrDestroy(); - MB_Destroy(); - DSUninit(); + Initialisation::~Initialisation() + { + Snapshot_Shutdown(); + CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard(); + if (pMouseCard) + { + pMouseCard->Reset(); + } + MemDestroy(); + GetFrame().Destroy(); - HD_Destroy(); - PrintDestroy(); - CpuDestroy(); + SpkrDestroy(); + MB_Destroy(); + DSUninit(); + + HD_Destroy(); + PrintDestroy(); + CpuDestroy(); + + GetCardMgr().GetDisk2CardMgr().Destroy(); + LogDone(); + RiffFinishWriteFile(); + } - GetCardMgr().GetDisk2CardMgr().Destroy(); - LogDone(); - RiffFinishWriteFile(); } diff --git a/source/frontends/common2/utils.h b/source/frontends/common2/utils.h index 1705a1e5..a4d121dd 100644 --- a/source/frontends/common2/utils.h +++ b/source/frontends/common2/utils.h @@ -2,11 +2,16 @@ #include -void setSnapshotFilename(const std::string & filename, const bool load); - -class Initialisation +namespace common2 { -public: - Initialisation(); - ~Initialisation(); -}; + + void setSnapshotFilename(const std::string & filename, const bool load); + + class Initialisation + { + public: + Initialisation(); + ~Initialisation(); + }; + +} diff --git a/source/frontends/libretro/game.cpp b/source/frontends/libretro/game.cpp index 7cf89f61..7581cbfa 100644 --- a/source/frontends/libretro/game.cpp +++ b/source/frontends/libretro/game.cpp @@ -58,7 +58,7 @@ Game::Game(const std::shared_ptr & frame) LogInit(); InitialiseRetroRegistry(); - myInit.reset(new Initialisation); + myInit.reset(new common2::Initialisation); switch (ourInputDevices[0]) { @@ -286,6 +286,6 @@ bool Game::loadGame(const std::string & path) bool Game::loadSnapshot(const std::string & path) { - setSnapshotFilename(path, true); + common2::setSnapshotFilename(path, true); return true; } diff --git a/source/frontends/libretro/game.h b/source/frontends/libretro/game.h index 075cbe5a..8ceff047 100644 --- a/source/frontends/libretro/game.h +++ b/source/frontends/libretro/game.h @@ -6,8 +6,12 @@ #include #include +namespace common2 +{ + class Initialisation; +} + class RetroFrame; -class Initialisation; class Game { @@ -33,11 +37,11 @@ public: private: const std::shared_ptr myFrame; - Speed mySpeed; // fixed speed + common2::Speed mySpeed; // fixed speed std::vector myButtonStates; - std::shared_ptr myInit; + std::shared_ptr myInit; bool checkButtonPressed(unsigned id); void keyboardEmulation(); diff --git a/source/frontends/libretro/retroframe.h b/source/frontends/libretro/retroframe.h index fa14a272..cd0bde0a 100644 --- a/source/frontends/libretro/retroframe.h +++ b/source/frontends/libretro/retroframe.h @@ -5,7 +5,7 @@ #include #include -class RetroFrame : public CommonFrame +class RetroFrame : public common2::CommonFrame { public: RetroFrame(); diff --git a/source/frontends/libretro/retroregistry.cpp b/source/frontends/libretro/retroregistry.cpp index 7233cd83..ba32a898 100644 --- a/source/frontends/libretro/retroregistry.cpp +++ b/source/frontends/libretro/retroregistry.cpp @@ -132,7 +132,7 @@ void SetupRetroVariables() void InitialiseRetroRegistry() { - const auto registry = std::make_shared(); + const auto registry = std::make_shared(); for (const Variable & variable : ourVariables) { diff --git a/source/frontends/ncurses/main.cpp b/source/frontends/ncurses/main.cpp index ebd194ec..3803644c 100644 --- a/source/frontends/ncurses/main.cpp +++ b/source/frontends/ncurses/main.cpp @@ -27,7 +27,7 @@ namespace { - bool ContinueExecution(const EmulatorOptions & options, const std::shared_ptr & frame) + bool ContinueExecution(const common2::EmulatorOptions & options, const std::shared_ptr & frame) { const auto start = std::chrono::steady_clock::now(); @@ -130,7 +130,7 @@ namespace } } - void EnterMessageLoop(const EmulatorOptions & options, const std::shared_ptr & frame) + void EnterMessageLoop(const common2::EmulatorOptions & options, const std::shared_ptr & frame) { LogFileTimeUntilFirstKeyReadReset(); while (ContinueExecution(options, frame)) @@ -140,7 +140,7 @@ namespace int run_ncurses(int argc, const char * argv []) { - EmulatorOptions options; + common2::EmulatorOptions options; options.memclear = g_nMemoryClearType; const bool run = getEmulatorOptions(argc, argv, "ncurses", options); @@ -161,7 +161,7 @@ namespace g_nMemoryClearType = options.memclear; - Initialisation init; + common2::Initialisation init; SetCtrlCHandler(options.headless); applyOptions(options); diff --git a/source/frontends/ncurses/nframe.h b/source/frontends/ncurses/nframe.h index 7fc25fd4..e54aceb6 100644 --- a/source/frontends/ncurses/nframe.h +++ b/source/frontends/ncurses/nframe.h @@ -10,7 +10,7 @@ class ASCIIArt; class EvDevPaddle; struct NCurses; -class NFrame : public CommonFrame +class NFrame : public common2::CommonFrame { public: NFrame(const std::string & paddleDevice); diff --git a/source/frontends/sdl/imgui/sdlimguiframe.cpp b/source/frontends/sdl/imgui/sdlimguiframe.cpp index 2d23e3d3..37a94fef 100644 --- a/source/frontends/sdl/imgui/sdlimguiframe.cpp +++ b/source/frontends/sdl/imgui/sdlimguiframe.cpp @@ -35,7 +35,7 @@ namespace } -SDLImGuiFrame::SDLImGuiFrame(const EmulatorOptions & options) +SDLImGuiFrame::SDLImGuiFrame(const common2::EmulatorOptions & options) : SDLFrame(options) { SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, 0); @@ -49,7 +49,7 @@ SDLImGuiFrame::SDLImGuiFrame(const EmulatorOptions & options) SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); const SDL_WindowFlags windowFlags = (SDL_WindowFlags)(SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); - const Geometry & geometry = options.geometry; + const common2::Geometry & geometry = options.geometry; myWindow.reset(SDL_CreateWindow(g_pAppTitle.c_str(), geometry.x, geometry.y, geometry.width, geometry.height, windowFlags), SDL_DestroyWindow); if (!myWindow) @@ -81,7 +81,7 @@ SDLImGuiFrame::SDLImGuiFrame(const EmulatorOptions & options) ImGui::CreateContext(); ImGuiIO& io = ImGui::GetIO(); - mySettings.iniFileLocation = GetConfigFile("imgui.ini"); + mySettings.iniFileLocation = common2::GetConfigFile("imgui.ini"); if (mySettings.iniFileLocation.empty()) { io.IniFilename = nullptr; diff --git a/source/frontends/sdl/imgui/sdlimguiframe.h b/source/frontends/sdl/imgui/sdlimguiframe.h index b8e63b5a..ff86e408 100644 --- a/source/frontends/sdl/imgui/sdlimguiframe.h +++ b/source/frontends/sdl/imgui/sdlimguiframe.h @@ -3,12 +3,15 @@ #include "frontends/sdl/sdlframe.h" #include "frontends/sdl/imgui/gles.h" -class EmulatorOptions; +namespace common2 +{ + class EmulatorOptions; +} class SDLImGuiFrame : public SDLFrame { public: - SDLImGuiFrame(const EmulatorOptions & options); + SDLImGuiFrame(const common2::EmulatorOptions & options); ~SDLImGuiFrame() override; diff --git a/source/frontends/sdl/main.cpp b/source/frontends/sdl/main.cpp index 6857b5b7..a0237e32 100644 --- a/source/frontends/sdl/main.cpp +++ b/source/frontends/sdl/main.cpp @@ -53,7 +53,7 @@ namespace return current.refresh_rate; } - void execute(Speed speed, const size_t next) + void execute(common2::Speed speed, const size_t next) { if (g_nAppMode == MODE_RUNNING) { @@ -73,9 +73,9 @@ namespace struct Data { - Speed * speed; + common2::Speed * speed; SDL_mutex * mutex; - Timer * timer; + common2::Timer * timer; }; Uint32 emulator_callback(Uint32 interval, void *param) @@ -97,7 +97,7 @@ void run_sdl(int argc, const char * argv []) { std::cerr << std::fixed << std::setprecision(2); - EmulatorOptions options; + common2::EmulatorOptions options; Video & video = GetVideo(); const int sw = video.GetFrameBufferBorderlessWidth(); @@ -146,7 +146,7 @@ void run_sdl(int argc, const char * argv []) g_nMemoryClearType = options.memclear; - Initialisation init; + common2::Initialisation init; applyOptions(options); const int fps = getRefreshRate(); @@ -177,17 +177,17 @@ void run_sdl(int argc, const char * argv []) } else { - Timer global; - Timer updateTextureTimer; - Timer refreshScreenTimer; - Timer cpuTimer; - Timer eventTimer; - Timer frameTimer; + common2::Timer global; + common2::Timer updateTextureTimer; + common2::Timer refreshScreenTimer; + common2::Timer cpuTimer; + common2::Timer eventTimer; + common2::Timer frameTimer; const std::string globalTag = ". ."; std::string updateTextureTimerTag, refreshScreenTimerTag, cpuTimerTag, eventTimerTag; - Speed speed(options.fixedSpeed); + common2::Speed speed(options.fixedSpeed); if (options.multiThreaded) { diff --git a/source/frontends/sdl/renderer/sdlrendererframe.cpp b/source/frontends/sdl/renderer/sdlrendererframe.cpp index eb26a6ff..6dab4e10 100644 --- a/source/frontends/sdl/renderer/sdlrendererframe.cpp +++ b/source/frontends/sdl/renderer/sdlrendererframe.cpp @@ -8,10 +8,10 @@ #include -SDLRendererFrame::SDLRendererFrame(const EmulatorOptions & options) +SDLRendererFrame::SDLRendererFrame(const common2::EmulatorOptions & options) : SDLFrame(options) { - const Geometry & geometry = options.geometry; + const common2::Geometry & geometry = options.geometry; myWindow.reset(SDL_CreateWindow(g_pAppTitle.c_str(), geometry.x, geometry.y, geometry.width, geometry.height, SDL_WINDOW_RESIZABLE), SDL_DestroyWindow); if (!myWindow) diff --git a/source/frontends/sdl/renderer/sdlrendererframe.h b/source/frontends/sdl/renderer/sdlrendererframe.h index 869d974f..8e708109 100644 --- a/source/frontends/sdl/renderer/sdlrendererframe.h +++ b/source/frontends/sdl/renderer/sdlrendererframe.h @@ -2,12 +2,15 @@ #include "frontends/sdl/sdlframe.h" -class EmulatorOptions; +namespace common2 +{ + class EmulatorOptions; +} class SDLRendererFrame : public SDLFrame { public: - SDLRendererFrame(const EmulatorOptions & options); + SDLRendererFrame(const common2::EmulatorOptions & options); void UpdateTexture() override; void RenderPresent() override; diff --git a/source/frontends/sdl/sdlframe.cpp b/source/frontends/sdl/sdlframe.cpp index 5fcabf7b..f1ca1e23 100644 --- a/source/frontends/sdl/sdlframe.cpp +++ b/source/frontends/sdl/sdlframe.cpp @@ -112,7 +112,7 @@ namespace } -SDLFrame::SDLFrame(const EmulatorOptions & options) +SDLFrame::SDLFrame(const common2::EmulatorOptions & options) : myForceCapsLock(true) , myMultiplier(1) , myFullscreen(false) diff --git a/source/frontends/sdl/sdlframe.h b/source/frontends/sdl/sdlframe.h index 59186066..5e87558b 100644 --- a/source/frontends/sdl/sdlframe.h +++ b/source/frontends/sdl/sdlframe.h @@ -4,12 +4,15 @@ #include "frontends/common2/speed.h" #include -struct EmulatorOptions; +namespace common2 +{ + struct EmulatorOptions; +} -class SDLFrame : public CommonFrame +class SDLFrame : public common2::CommonFrame { public: - SDLFrame(const EmulatorOptions & options); + SDLFrame(const common2::EmulatorOptions & options); void VideoPresentScreen() override; void FrameRefreshStatus(int drawflags) override; @@ -38,5 +41,5 @@ protected: int myMultiplier; bool myFullscreen; - Speed mySpeed; + common2::Speed mySpeed; };