new configuration file location algorithm
This commit is contained in:
parent
28048d7087
commit
ddf97fff28
|
@ -221,6 +221,7 @@ if(APPLE)
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
BUNDLE DESTINATION .)
|
BUNDLE DESTINATION .)
|
||||||
configure_file(share/FixBundle.cmake.in ${PROJECT_BINARY_DIR}/FixBundle.cmake @ONLY)
|
configure_file(share/FixBundle.cmake.in ${PROJECT_BINARY_DIR}/FixBundle.cmake @ONLY)
|
||||||
|
# TODO: how to make resources read-only (on Mac)
|
||||||
install(SCRIPT ${PROJECT_BINARY_DIR}/FixBundle.cmake)
|
install(SCRIPT ${PROJECT_BINARY_DIR}/FixBundle.cmake)
|
||||||
elseif(WIN32)
|
elseif(WIN32)
|
||||||
install(TARGETS ${APP_NAME}
|
install(TARGETS ${APP_NAME}
|
||||||
|
|
|
@ -178,7 +178,7 @@ bool E2wxApp::OnInit() {
|
||||||
|
|
||||||
|
|
||||||
this->emu = new Emulator();
|
this->emu = new Emulator();
|
||||||
Config cfg(this->arg_configfile);
|
Config cfg(this->arg_configfile, this->opt_config_from_prefs_only);
|
||||||
this->emu->config(cfg);
|
this->emu->config(cfg);
|
||||||
this->emu->init();
|
this->emu->init();
|
||||||
this->emu_timer = new EmuTimer(this->emu);
|
this->emu_timer = new EmuTimer(this->emu);
|
||||||
|
@ -215,8 +215,8 @@ void E2wxApp::OnFatalException() {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const wxCmdLineEntryDesc cmdLineDesc[] =
|
static const wxCmdLineEntryDesc cmdLineDesc[] = {
|
||||||
{
|
{ wxCMD_LINE_SWITCH, "p", "prefs", "Read config only from preferences, never an external file.", wxCMD_LINE_VAL_NONE },
|
||||||
{ wxCMD_LINE_PARAM, NULL, NULL, "config-file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
{ wxCMD_LINE_PARAM, NULL, NULL, "config-file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL },
|
||||||
wxCMD_LINE_DESC_END
|
wxCMD_LINE_DESC_END
|
||||||
};
|
};
|
||||||
|
@ -231,6 +231,8 @@ bool E2wxApp::OnCmdLineParsed(wxCmdLineParser& parser) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this->opt_config_from_prefs_only = parser.Found("p");
|
||||||
|
|
||||||
const int n = parser.GetParamCount();
|
const int n = parser.GetParamCount();
|
||||||
|
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
|
|
|
@ -59,6 +59,7 @@ class E2wxApp : public wxApp {
|
||||||
std::filesystem::path confdir;
|
std::filesystem::path confdir;
|
||||||
std::filesystem::path docsdir;
|
std::filesystem::path docsdir;
|
||||||
std::filesystem::path arg_configfile;
|
std::filesystem::path arg_configfile;
|
||||||
|
bool opt_config_from_prefs_only;
|
||||||
EmuTimer *emu_timer;
|
EmuTimer *emu_timer;
|
||||||
Emulator *emu;
|
Emulator *emu;
|
||||||
|
|
||||||
|
|
|
@ -134,13 +134,7 @@ void PreferencesDialog::BuildItemTree() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PreferencesDialog::OnInit() {
|
void PreferencesDialog::OnInit() {
|
||||||
wxConfigBase *appconf = wxConfigBase::Get();
|
wxConfigBase::Get()->Read("/ActivePreferences/name", &this->active, "");
|
||||||
if (!appconf->Read("/ActivePreferences/name", &this->active)) {
|
|
||||||
// TODO what to do when no config?
|
|
||||||
this->active = "epple2";
|
|
||||||
appconf->Write("/ActivePreferences/name", this->active);
|
|
||||||
appconf->Flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
wxXmlResource::Get()->LoadDialog(this, this->parent, "Preferences");
|
wxXmlResource::Get()->LoadDialog(this, this->parent, "Preferences");
|
||||||
|
|
||||||
|
@ -163,6 +157,8 @@ void PreferencesDialog::Save(const std::filesystem::path& to) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: enable/disable the various buttons, etc. (currently all are enabled even if not functional)
|
||||||
|
|
||||||
void PreferencesDialog::OnTreeSelectionChanged(wxTreeEvent& evt) {
|
void PreferencesDialog::OnTreeSelectionChanged(wxTreeEvent& evt) {
|
||||||
// note: we don't get the first select upon dialog creation,
|
// note: we don't get the first select upon dialog creation,
|
||||||
// nor the final de-select upon dialog destruction
|
// nor the final de-select upon dialog destruction
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "configep2.h"
|
#include "configep2.h"
|
||||||
|
|
||||||
#include "E2wxApp.h"
|
#include "E2wxApp.h"
|
||||||
|
#include "e2filesystem.h"
|
||||||
#include "apple2.h"
|
#include "apple2.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "memoryrandomaccess.h"
|
#include "memoryrandomaccess.h"
|
||||||
|
@ -36,6 +36,8 @@
|
||||||
#include <wx/config.h>
|
#include <wx/config.h>
|
||||||
#include <wx/string.h>
|
#include <wx/string.h>
|
||||||
|
|
||||||
|
#include <boost/log/trivial.hpp>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -47,6 +49,10 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static const wxString DEFAULT_CONFIG_NAME{"epple2"};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define K 1024u
|
#define K 1024u
|
||||||
|
|
||||||
static std::uint16_t memory_block_size(const std::string &block_size) {
|
static std::uint16_t memory_block_size(const std::string &block_size) {
|
||||||
|
@ -61,15 +67,11 @@ static std::uint16_t memory_block_size(const std::string &block_size) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
unsigned char Config::disk_mask(0);
|
|
||||||
|
|
||||||
Config::Config(const std::filesystem::path& f):
|
Config::Config(const std::filesystem::path& f, bool p): file_path {f}, prefs_only {p} {
|
||||||
file_path(f)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Config::~Config()
|
Config::~Config() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void strip_comment(std::string& str)
|
static void strip_comment(std::string& str)
|
||||||
|
@ -99,140 +101,211 @@ static void trim(std::string& str)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2)
|
|
||||||
{
|
|
||||||
std::ifstream* pConfig;
|
|
||||||
|
|
||||||
std::filesystem::path path(this->file_path);
|
|
||||||
|
|
||||||
if (!path.empty())
|
/*
|
||||||
{
|
* Searches for config file with the given name in the preferences areas.
|
||||||
pConfig = new std::ifstream(path);
|
* The name must not be a filesystem path.
|
||||||
if (!pConfig->is_open())
|
* The actual config files themselves have ".conf" extension.
|
||||||
{
|
* The preferences areas are searched in this order:
|
||||||
// TODO use filename only and look in standard resources
|
* user area
|
||||||
std::stringstream ss;
|
* built-in area
|
||||||
ss << "Cannot open config file " << this->file_path;
|
*
|
||||||
throw std::runtime_error(ss.str());
|
* If successful, returns an open stream, caller is responsible for deleting it
|
||||||
|
* Otherwise, returns null
|
||||||
|
*/
|
||||||
|
std::ifstream *Config::openFilePref(const wxString& s_name) {
|
||||||
|
std::ifstream *ret = nullptr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "config file name was specified as: " << s_name;
|
||||||
|
std::filesystem::path path_name = path_from_string(s_name);
|
||||||
|
if (path_name.has_parent_path()) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "invalid name for config file (paths are not allowed): " << path_name.c_str();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path_name.empty()) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "invalid: empty name for config file";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// required file extension for any file to be recognized as a config file
|
||||||
|
path_name = path_from_string(s_name+".conf");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::filesystem::path path;
|
||||||
|
|
||||||
|
path = valid_input_file(path_name, wxGetApp().GetConfigDir());
|
||||||
|
if (!path.empty()) {
|
||||||
|
ret = new std::ifstream(path);
|
||||||
|
if (ret->is_open()) {
|
||||||
|
return ret; // Found specified config file in user area of preferences
|
||||||
}
|
}
|
||||||
|
delete ret;
|
||||||
|
ret = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
path = valid_input_file(path_name, wxGetApp().GetResDir());
|
||||||
|
if (!path.empty()) {
|
||||||
|
ret = new std::ifstream(path);
|
||||||
|
if (ret->is_open()) {
|
||||||
|
return ret; // Found specified config file in built-in area of preferences
|
||||||
|
}
|
||||||
|
delete ret;
|
||||||
|
ret = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (path.empty())
|
return ret;
|
||||||
{
|
}
|
||||||
// TODO config file location, how to be backwardly compatible?
|
|
||||||
wxString user_config;
|
|
||||||
if (!wxConfigBase::Get()->Read("/ActivePreferences/name", &user_config)) {
|
|
||||||
// TODO what to do when no config?
|
|
||||||
user_config = "epple2";
|
|
||||||
}
|
|
||||||
user_config += ".conf";
|
|
||||||
std::filesystem::path user_path{user_config.wc_str()};
|
|
||||||
|
|
||||||
path = wxGetApp().GetConfigDir() / user_path;
|
std::ifstream *Config::openFileExternal(const std::filesystem::path& path) {
|
||||||
std::cout << "looking for config file: " << path << std::endl;
|
std::ifstream *ret = nullptr;
|
||||||
pConfig = new std::ifstream(path);
|
|
||||||
if (!pConfig->is_open()) {
|
const std::filesystem::path p = valid_input_file(path);
|
||||||
path = wxGetApp().GetResDir() / user_path;
|
if (!p.empty()) {
|
||||||
std::cout << "looking for config file: " << path << std::endl;
|
ret = new std::ifstream(p);
|
||||||
pConfig = new std::ifstream(path);
|
if (ret->is_open()) {
|
||||||
if (!pConfig->is_open()) {
|
return ret;
|
||||||
path.clear();
|
}
|
||||||
|
delete ret;
|
||||||
|
ret = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const std::array rs_path_legacy{
|
||||||
|
"./etc/epple2/epple2.conf",
|
||||||
|
ETCDIR "/epple2/epple2.conf",
|
||||||
|
"/etc/epple2/epple2.conf",
|
||||||
|
"/etc/epple2.conf",
|
||||||
|
"./epple2.conf",
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ifstream *Config::openFileLegacy() {
|
||||||
|
std::ifstream *ret = nullptr;
|
||||||
|
|
||||||
|
for (const auto &s_path_legacy : rs_path_legacy) {
|
||||||
|
if ((ret = openFileExternal(std::filesystem::path{s_path_legacy})) != nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Algorithm to locate and open the configuration file, as specified by
|
||||||
|
* the user, either on command line, or via preferences, allowing for
|
||||||
|
* backward compatibility with legacy file locations.
|
||||||
|
*/
|
||||||
|
std::ifstream *Config::openFile() {
|
||||||
|
std::ifstream *ret = nullptr;
|
||||||
|
|
||||||
|
if (this->file_path.empty()) {
|
||||||
|
wxString cname{};
|
||||||
|
const bool stored_prefs_found = wxConfigBase::Get()->Read("/ActivePreferences/name", &cname, DEFAULT_CONFIG_NAME);
|
||||||
|
|
||||||
|
if (stored_prefs_found) {
|
||||||
|
ret = openFilePref(cname);
|
||||||
|
if (ret != nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this->prefs_only) {
|
||||||
|
ret = openFileLegacy();
|
||||||
|
if (ret != nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!this->prefs_only) {
|
||||||
|
ret = openFileLegacy();
|
||||||
|
if (ret != nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = openFilePref(cname);
|
||||||
|
if (ret != nullptr) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!this->prefs_only) {
|
||||||
|
ret = openFileExternal(this->file_path);
|
||||||
|
if (ret != nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = openFilePref(this->file_path.c_str());
|
||||||
|
if (ret != nullptr) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2) {
|
||||||
|
std::ifstream *p_ifstream_config = openFile();
|
||||||
|
|
||||||
if (path.empty())
|
if (p_ifstream_config == nullptr) {
|
||||||
{
|
|
||||||
std::cout << "standard config file location: " ETCDIR "/epple2/epple2.conf" << std::endl;
|
|
||||||
|
|
||||||
/*
|
|
||||||
On Windows, the default directory will be
|
|
||||||
C:\Program Files\Epple2 if they start the
|
|
||||||
program from the Start Menu; therefore
|
|
||||||
etc/epple2/epple2.conf would be
|
|
||||||
C:\Program Files\epple2\etc\epple2\epple2.conf
|
|
||||||
On Linux... the current directory could be
|
|
||||||
anything, so this probably won't find it (unless
|
|
||||||
the current directory is /).
|
|
||||||
*/
|
|
||||||
path = "etc/epple2/epple2.conf";
|
|
||||||
pConfig = new std::ifstream(path);
|
|
||||||
if (!pConfig->is_open())
|
|
||||||
path.clear();
|
|
||||||
}
|
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
This is primarily for Linux. If configured for
|
|
||||||
a PREFIX of "/usr/local", then this would be
|
|
||||||
/usr/local/etc/epple2/epple2.conf
|
|
||||||
*/
|
|
||||||
path = ETCDIR "/epple2/epple2.conf";
|
|
||||||
pConfig = new std::ifstream(path);
|
|
||||||
if (!pConfig->is_open())
|
|
||||||
path.clear();
|
|
||||||
}
|
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Try a likely linux location
|
|
||||||
*/
|
|
||||||
path = "/etc/epple2/epple2.conf";
|
|
||||||
pConfig = new std::ifstream(path);
|
|
||||||
if (!pConfig->is_open())
|
|
||||||
path.clear();
|
|
||||||
}
|
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Try another likely linux location
|
|
||||||
*/
|
|
||||||
path = "/etc/epple2.conf";
|
|
||||||
pConfig = new std::ifstream(path);
|
|
||||||
if (!pConfig->is_open())
|
|
||||||
path.clear();
|
|
||||||
}
|
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
Last effort to find it.
|
|
||||||
*/
|
|
||||||
path = "epple2.conf";
|
|
||||||
pConfig = new std::ifstream(path);
|
|
||||||
if (!pConfig->is_open())
|
|
||||||
path.clear();
|
|
||||||
}
|
|
||||||
if (path.empty())
|
|
||||||
{
|
|
||||||
std::cerr << "Cannot find config file. Running without any RAM, ROM, or cards." << std::endl;
|
std::cerr << "Cannot find config file. Running without any RAM, ROM, or cards." << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Reading configuration from file: " << path << std::endl;
|
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(*pConfig,line);
|
std::getline(*p_ifstream_config, line);
|
||||||
while (!pConfig->eof())
|
while (!p_ifstream_config->eof()) {
|
||||||
{
|
|
||||||
strip_comment(line);
|
strip_comment(line);
|
||||||
trim(line);
|
trim(line);
|
||||||
if (!line.empty())
|
if (!line.empty()) {
|
||||||
{
|
// TODO "parseLine" will become Command::execute, or similar
|
||||||
parseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut,apple2);
|
parseLine(line, ram, rom, slts, revision, gui, cassetteIn, cassetteOut, apple2);
|
||||||
}
|
}
|
||||||
std::getline(*pConfig,line);
|
std::getline(*p_ifstream_config, line);
|
||||||
}
|
}
|
||||||
pConfig->close();
|
|
||||||
delete pConfig;
|
delete p_ifstream_config;
|
||||||
|
|
||||||
// TODO: make sure there is no more than ONE stdin and/or ONE stdout card
|
// TODO: make sure there is no more than ONE stdin and/or ONE stdout card
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Config::parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2)
|
void Config::parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -519,6 +592,12 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
unsigned char Config::disk_mask(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void Config::loadDisk(Slots& slts, int slot, int drive, const std::string& fnib)
|
void Config::loadDisk(Slots& slts, int slot, int drive, const std::string& fnib)
|
||||||
{
|
{
|
||||||
if (drive < 1 || 2 < drive)
|
if (drive < 1 || 2 < drive)
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#ifndef CONFIGEP2_H
|
#ifndef CONFIGEP2_H
|
||||||
#define CONFIGEP2_H
|
#define CONFIGEP2_H
|
||||||
|
|
||||||
|
#include <wx/string.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
class Memory;
|
class Memory;
|
||||||
|
@ -34,11 +35,19 @@ public:
|
||||||
ConfigException(const std::string& msg) : msg(msg) {}
|
ConfigException(const std::string& msg) : msg(msg) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO split out all static things into their own class (and don't make them static)
|
||||||
|
// Remember that, besides config, also command line entry calls parseLine
|
||||||
|
// This will also help with adding menu items in place of commands
|
||||||
class Config {
|
class Config {
|
||||||
private:
|
private:
|
||||||
const std::filesystem::path file_path;
|
const std::filesystem::path file_path;
|
||||||
|
const bool prefs_only;
|
||||||
static unsigned char disk_mask;
|
static unsigned char disk_mask;
|
||||||
|
|
||||||
|
std::ifstream *openFile();
|
||||||
|
std::ifstream *openFilePref(const wxString& s_name);
|
||||||
|
std::ifstream *openFileExternal(const std::filesystem::path& path);
|
||||||
|
std::ifstream *openFileLegacy();
|
||||||
static void loadDisk(Slots& slts, int slot, int drive, const std::string& fnib);
|
static void loadDisk(Slots& slts, int slot, int drive, const std::string& fnib);
|
||||||
static void unloadDisk(Slots& slts, int slot, int drive);
|
static void unloadDisk(Slots& slts, int slot, int drive);
|
||||||
static void saveDisk(Slots& slts, int slot, int drive);
|
static void saveDisk(Slots& slts, int slot, int drive);
|
||||||
|
@ -46,7 +55,7 @@ private:
|
||||||
static void tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
|
static void tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Config(const std::filesystem::path& f);
|
Config(const std::filesystem::path& f, bool p);
|
||||||
~Config();
|
~Config();
|
||||||
|
|
||||||
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
|
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut, Apple2* apple2);
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
|
||||||
std::filesystem::path valid_input_file(const std::filesystem::path path, const std::filesystem::path base);
|
std::filesystem::path valid_input_file(const std::filesystem::path path, const std::filesystem::path base = std::filesystem::path{});
|
||||||
std::filesystem::path path_from_string(const wxString& s);
|
std::filesystem::path path_from_string(const wxString& s);
|
||||||
|
|
||||||
#endif /* E2FILESYSTEM_H */
|
#endif /* E2FILESYSTEM_H */
|
||||||
|
|
|
@ -116,6 +116,10 @@ bool WozFile::load(const std::filesystem::path& orig_file) {
|
||||||
printf("Reading WOZ 2.0 file: %s\n", orig_file.c_str());
|
printf("Reading WOZ 2.0 file: %s\n", orig_file.c_str());
|
||||||
|
|
||||||
std::filesystem::path filePath = valid_input_file(orig_file, wxGetApp().GetResDir());
|
std::filesystem::path filePath = valid_input_file(orig_file, wxGetApp().GetResDir());
|
||||||
|
if (filePath.empty()) {
|
||||||
|
printf("Error opening WOZ file.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
std::ifstream *in = new std::ifstream(filePath, std::ios::binary|std::ios::in);
|
std::ifstream *in = new std::ifstream(filePath, std::ios::binary|std::ios::in);
|
||||||
if (!in->is_open()) {
|
if (!in->is_open()) {
|
||||||
printf("Error opening file: %d\n", errno);
|
printf("Error opening file: %d\n", errno);
|
||||||
|
|
Loading…
Reference in New Issue