common2: add namespace and reformat everything with space over tabs.

This makes it "possible" to use other editors (than emacs).

Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
Andrea Odetti 2021-02-25 16:04:50 +00:00
parent 9366956c49
commit 3b917e93be
27 changed files with 623 additions and 542 deletions

View file

@ -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<BYTE> 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<BYTE> 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;
}

View file

@ -4,18 +4,23 @@
#include <vector>
#include <string>
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<BYTE> myResource;
};
protected:
static std::string getBitmapFilename(const std::string & resource);
const std::string myResourcePath;
std::vector<BYTE> myResource;
};
}

View file

@ -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<Configuration> 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<Configuration> config(new Configuration(filename, saveOnExit));
config->addExtraOptions(options.registryOptions);
Registry::instance = config;
}

View file

@ -2,7 +2,12 @@
#include <string>
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);
}

View file

@ -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<std::vector<std::string>>(), "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<std::string>(), "Disk in 1st drive")
("d2,2", po::value<std::string>(), "Disk in 2nd drive")
;
desc.add(diskDesc);
po::options_description snapshotDesc("Snapshot");
snapshotDesc.add_options()
("state-filename,f", po::value<std::string>(), "Set snapshot filename")
("load-state,s", po::value<std::string>(), "Load snapshot from file")
;
desc.add(snapshotDesc);
po::options_description memoryDesc("Memory");
memoryDesc.add_options()
("memclear", po::value<int>()->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<int>()->default_value(options.timerInterval), "Timer interval in ms")
("loose-mutex,l", "Loose mutex")
("sdl-driver", po::value<int>()->default_value(options.sdlDriver), "SDL driver")
("gl-swap", po::value<int>()->default_value(options.glSwapInterval), "SDL_GL_SwapInterval")
("imgui", "Render with Dear ImGui")
("geometry", po::value<std::string>(), "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<std::string>(), "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<std::vector<std::string>>(), "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<std::string>(), "Disk in 1st drive")
("d2,2", po::value<std::string>(), "Disk in 2nd drive")
;
desc.add(diskDesc);
po::options_description snapshotDesc("Snapshot");
snapshotDesc.add_options()
("state-filename,f", po::value<std::string>(), "Set snapshot filename")
("load-state,s", po::value<std::string>(), "Load snapshot from file")
;
desc.add(snapshotDesc);
po::options_description memoryDesc("Memory");
memoryDesc.add_options()
("memclear", po::value<int>()->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<int>()->default_value(options.timerInterval), "Timer interval in ms")
("loose-mutex,l", "Loose mutex")
("sdl-driver", po::value<int>()->default_value(options.sdlDriver), "SDL driver")
("gl-swap", po::value<int>()->default_value(options.glSwapInterval), "SDL_GL_SwapInterval")
("imgui", "Render with Dear ImGui")
("geometry", po::value<std::string>(), "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<std::string>(), "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<int>();
options.sdlDriver = vm["sdl-driver"].as<int>();
options.glSwapInterval = vm["gl-swap"].as<int>();
options.imgui = vm.count("imgui");
if (vm.count("config"))
{
options.registryOptions = vm["config"].as<std::vector<std::string> >();
}
if (vm.count("d1"))
{
options.disk1 = vm["d1"].as<std::string>();
}
if (vm.count("d2"))
{
options.disk2 = vm["d2"].as<std::string>();
}
if (vm.count("load-state"))
{
options.snapshotFilename = vm["load-state"].as<std::string>();
options.loadSnapshot = true;
}
if (vm.count("state-filename"))
{
options.snapshotFilename = vm["state-filename"].as<std::string>();
options.loadSnapshot = false;
}
const int memclear = vm["memclear"].as<int>();
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<std::string>();
}
if (vm.count("geometry"))
{
parseGeometry(vm["geometry"].as<std::string>(), 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<int>();
options.sdlDriver = vm["sdl-driver"].as<int>();
options.glSwapInterval = vm["gl-swap"].as<int>();
options.imgui = vm.count("imgui");
if (vm.count("config"))
catch (const std::exception & e)
{
options.registryOptions = vm["config"].as<std::vector<std::string> >();
std::cerr << "ERROR: " << e.what() << std::endl;
return false;
}
if (vm.count("d1"))
{
options.disk1 = vm["d1"].as<std::string>();
}
if (vm.count("d2"))
{
options.disk2 = vm["d2"].as<std::string>();
}
if (vm.count("load-state"))
{
options.snapshotFilename = vm["load-state"].as<std::string>();
options.loadSnapshot = true;
}
if (vm.count("state-filename"))
{
options.snapshotFilename = vm["state-filename"].as<std::string>();
options.loadSnapshot = false;
}
const int memclear = vm["memclear"].as<int>();
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<std::string>();
}
if (vm.count("geometry"))
{
parseGeometry(vm["geometry"].as<std::string>(), 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);
}

View file

@ -3,55 +3,59 @@
#include <string>
#include <vector>
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<std::string> registryOptions;
};
std::vector<std::string> 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);
}

View file

@ -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<std::string>(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<DWORD>(section, key);
}
std::string PTreeRegistry::getString(const std::string & section, const std::string & key) const
{
return getValue<std::string>(section, key);
}
bool PTreeRegistry::getBool(const std::string & section, const std::string & key) const
{
return getValue<bool>(section, key);
}
DWORD PTreeRegistry::getDWord(const std::string & section, const std::string & key) const
{
return getValue<DWORD>(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<bool>(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 <typename T>
T PTreeRegistry::getValue(const std::string & section, const std::string & key) const
{
const std::string path = section + "." + key;
const T value = myINI.get<T>(path);
return value;
}
void PTreeRegistry::putDWord(const std::string & section, const std::string & key, const DWORD value)
{
putValue(section, key, value);
}
template <typename T>
T PTreeRegistry::getValue(const std::string & section, const std::string & key) const
{
const std::string path = section + "." + key;
const T value = myINI.get<T>(path);
return value;
}
template <typename T>
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 <typename T>
void PTreeRegistry::putValue(const std::string & section, const std::string & key, const T & value)
{
const std::string path = section + "." + key;
myINI.put(path, value);
}

View file

@ -4,33 +4,37 @@
#include <boost/property_tree/ptree.hpp>
#include <string>
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<std::string, std::string, KeyQtEncodedLess> 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<typename T>
T getValue(const std::string & section, const std::string & key) const;
template<typename T>
void putValue(const std::string & section, const std::string & key, const T & value);
protected:
ini_t myINI;
};
typedef boost::property_tree::basic_ptree<std::string, std::string, KeyQtEncodedLess> 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<typename T>
T getValue(const std::string & section, const std::string & key) const;
template<typename T>
void putValue(const std::string & section, const std::string & key, const T & value);
protected:
ini_t myINI;
};
}

View file

@ -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<uint64_t>(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<std::chrono::microseconds>(currentTime - myStartTime).count();
// target the next time we will be called
const auto targetDeltaInMicros = currentDelta + microseconds;
const uint64_t targetCycles = static_cast<uint64_t>(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<uint64_t>(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<std::chrono::microseconds>(currentTime - myStartTime).count();
// target the next time we will be called
const auto targetDeltaInMicros = currentDelta + microseconds;
const uint64_t targetCycles = static_cast<uint64_t>(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;
}
}
}
}

View file

@ -2,20 +2,25 @@
#include <chrono>
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<std::chrono::steady_clock> myStartTime;
uint64_t myStartCycles;
};
private:
const bool myFixedSpeed;
std::chrono::time_point<std::chrono::steady_clock> myStartTime;
uint64_t myStartCycles;
};
}

View file

@ -4,45 +4,50 @@
#include <cmath>
#include <iomanip>
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<std::chrono::microseconds>(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<std::chrono::microseconds>(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;
}

View file

@ -1,24 +1,29 @@
#include <chrono>
#include <iosfwd>
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<std::chrono::steady_clock> myT0;
private:
double mySum;
double mySum2;
int myN;
};
std::chrono::time_point<std::chrono::steady_clock> 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);
}

View file

@ -30,82 +30,87 @@
#include <libgen.h>
#include <unistd.h>
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();
}

View file

@ -2,11 +2,16 @@
#include <string>
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();
};
}

View file

@ -58,7 +58,7 @@ Game::Game(const std::shared_ptr<RetroFrame> & 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;
}

View file

@ -6,8 +6,12 @@
#include <string>
#include <vector>
namespace common2
{
class Initialisation;
}
class RetroFrame;
class Initialisation;
class Game
{
@ -33,11 +37,11 @@ public:
private:
const std::shared_ptr<RetroFrame> myFrame;
Speed mySpeed; // fixed speed
common2::Speed mySpeed; // fixed speed
std::vector<int> myButtonStates;
std::shared_ptr<Initialisation> myInit;
std::shared_ptr<common2::Initialisation> myInit;
bool checkButtonPressed(unsigned id);
void keyboardEmulation();

View file

@ -5,7 +5,7 @@
#include <memory>
#include <vector>
class RetroFrame : public CommonFrame
class RetroFrame : public common2::CommonFrame
{
public:
RetroFrame();

View file

@ -132,7 +132,7 @@ void SetupRetroVariables()
void InitialiseRetroRegistry()
{
const auto registry = std::make_shared<PTreeRegistry>();
const auto registry = std::make_shared<common2::PTreeRegistry>();
for (const Variable & variable : ourVariables)
{

View file

@ -27,7 +27,7 @@
namespace
{
bool ContinueExecution(const EmulatorOptions & options, const std::shared_ptr<NFrame> & frame)
bool ContinueExecution(const common2::EmulatorOptions & options, const std::shared_ptr<NFrame> & frame)
{
const auto start = std::chrono::steady_clock::now();
@ -130,7 +130,7 @@ namespace
}
}
void EnterMessageLoop(const EmulatorOptions & options, const std::shared_ptr<NFrame> & frame)
void EnterMessageLoop(const common2::EmulatorOptions & options, const std::shared_ptr<NFrame> & 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);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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)
{

View file

@ -8,10 +8,10 @@
#include <iostream>
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)

View file

@ -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;

View file

@ -112,7 +112,7 @@ namespace
}
SDLFrame::SDLFrame(const EmulatorOptions & options)
SDLFrame::SDLFrame(const common2::EmulatorOptions & options)
: myForceCapsLock(true)
, myMultiplier(1)
, myFullscreen(false)

View file

@ -4,12 +4,15 @@
#include "frontends/common2/speed.h"
#include <SDL.h>
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;
};