mirror of
https://github.com/cmosher01/Epple-II.git
synced 2024-06-14 09:29:34 +00:00
extra conf search; default TV display
This commit is contained in:
parent
b54de32a5e
commit
5ecc59d37e
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -12,7 +12,7 @@ Makefile.in
|
||||||
/install-sh
|
/install-sh
|
||||||
/missing
|
/missing
|
||||||
/config.h.in*
|
/config.h.in*
|
||||||
|
/test-driver
|
||||||
|
|
||||||
|
|
||||||
# need these for non-VPATH builds
|
# need these for non-VPATH builds
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# epple2, The Emulated Apple ][
|
# epple2, The Emulated Apple ][
|
||||||
|
|
||||||
Copyright © 2008–2019, Christopher Alan Mosher, Shelton, Connecticut, USA, <cmosher01@gmail.com>. GPLv3.
|
Copyright © 2008–2019, Christopher Alan Mosher, Shelton, Connecticut, USA, <cmosher01@gmail.com>. [GPLv3](https://www.gnu.org/licenses/gpl.md).
|
||||||
|
|
||||||
[![Website](https://img.shields.io/website/https/cmosher01.github.io/Epple-II.svg)](https://cmosher01.github.io/Epple-II)
|
[![Website](https://img.shields.io/website/https/cmosher01.github.io/Epple-II.svg)](https://cmosher01.github.io/Epple-II)
|
||||||
[![Latest Release](https://img.shields.io/github/release/cmosher01/Epple-II.svg)](https://github.com/cmosher01/Epple-II/releases/latest)
|
[![Latest Release](https://img.shields.io/github/release/cmosher01/Epple-II.svg)](https://github.com/cmosher01/Epple-II/releases/latest)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- Autoconf -*-
|
# -*- Autoconf -*-
|
||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
AC_INIT(epple2, v1.0.3)
|
AC_INIT(epple2, v1.0.4)
|
||||||
AC_PREREQ(2.68)
|
AC_PREREQ(2.68)
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/apple2.cpp])
|
AC_CONFIG_SRCDIR([src/apple2.cpp])
|
||||||
|
|
|
@ -34,9 +34,9 @@ class AnalogTV
|
||||||
public:
|
public:
|
||||||
enum DisplayType
|
enum DisplayType
|
||||||
{
|
{
|
||||||
|
TV_OLD_COLOR,
|
||||||
MONITOR_COLOR,
|
MONITOR_COLOR,
|
||||||
MONITOR_GREEN,
|
MONITOR_GREEN,
|
||||||
TV_OLD_COLOR,
|
|
||||||
|
|
||||||
NUM_DISPLAY_TYPES
|
NUM_DISPLAY_TYPES
|
||||||
};
|
};
|
||||||
|
@ -89,7 +89,7 @@ public:
|
||||||
|
|
||||||
AnalogTV(ScreenImage& image);
|
AnalogTV(ScreenImage& image);
|
||||||
~AnalogTV();
|
~AnalogTV();
|
||||||
|
|
||||||
bool isOn() const
|
bool isOn() const
|
||||||
{
|
{
|
||||||
return this->on;
|
return this->on;
|
||||||
|
|
|
@ -59,7 +59,7 @@ static std::uint16_t memory_block_size(const std::string &block_size) {
|
||||||
unsigned char Config::disk_mask(0);
|
unsigned char Config::disk_mask(0);
|
||||||
|
|
||||||
Config::Config(const std::string& file_path):
|
Config::Config(const std::string& file_path):
|
||||||
file_path(file_path)
|
file_path(file_path)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,120 +70,141 @@ Config::~Config()
|
||||||
|
|
||||||
static void strip_comment(std::string& str)
|
static void strip_comment(std::string& str)
|
||||||
{
|
{
|
||||||
const size_t comment = str.find('#');
|
const size_t comment = str.find('#');
|
||||||
if (comment < std::string::npos)
|
if (comment < std::string::npos)
|
||||||
{
|
{
|
||||||
str.erase(comment);
|
str.erase(comment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void trim(std::string& str)
|
static void trim(std::string& str)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
const size_t p = str.find_first_not_of(" \t");
|
const size_t p = str.find_first_not_of(" \t");
|
||||||
if (p < std::string::npos)
|
if (p < std::string::npos)
|
||||||
{
|
{
|
||||||
str.erase(0,p);
|
str.erase(0,p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const size_t p = str.find_last_not_of(" \t");
|
const size_t p = str.find_last_not_of(" \t");
|
||||||
if (p+1 < std::string::npos)
|
if (p+1 < std::string::npos)
|
||||||
{
|
{
|
||||||
str.erase(p+1);
|
str.erase(p+1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
|
void Config::parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
|
||||||
{
|
{
|
||||||
std::ifstream* pConfig;
|
std::ifstream* pConfig;
|
||||||
|
|
||||||
std::string path(this->file_path);
|
std::string path(this->file_path);
|
||||||
|
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
{
|
{
|
||||||
pConfig = new std::ifstream(path.c_str());
|
pConfig = new std::ifstream(path.c_str());
|
||||||
if (!pConfig->is_open())
|
if (!pConfig->is_open())
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "Cannot open config file " << this->file_path.c_str();
|
ss << "Cannot open config file " << this->file_path.c_str();
|
||||||
throw std::runtime_error(ss.str());
|
throw std::runtime_error(ss.str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
On Windows, the default directory will be
|
On Windows, the default directory will be
|
||||||
C:\Program Files\Epple2 if they start the
|
C:\Program Files\Epple2 if they start the
|
||||||
program from the Start Menu; therefore
|
program from the Start Menu; therefore
|
||||||
etc/epple2/epple2.conf would be
|
etc/epple2/epple2.conf would be
|
||||||
C:\Program Files\epple2\etc\epple2\epple2.conf
|
C:\Program Files\epple2\etc\epple2\epple2.conf
|
||||||
On Linux... the current directory could be
|
On Linux... the current directory could be
|
||||||
anything, so this probably won't find it (unless
|
anything, so this probably won't find it (unless
|
||||||
the current directory is /).
|
the current directory is /).
|
||||||
*/
|
*/
|
||||||
path = "etc/epple2/epple2.conf";
|
path = "etc/epple2/epple2.conf";
|
||||||
pConfig = new std::ifstream(path.c_str());
|
pConfig = new std::ifstream(path.c_str());
|
||||||
if (!pConfig->is_open())
|
if (!pConfig->is_open())
|
||||||
path.clear();
|
path.clear();
|
||||||
}
|
}
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
This is primarily for Linux. If configured for
|
This is primarily for Linux. If configured for
|
||||||
a PREFIX of "/usr/local", then this would be
|
a PREFIX of "/usr/local", then this would be
|
||||||
/usr/local/etc/epple2/epple2.conf
|
/usr/local/etc/epple2/epple2.conf
|
||||||
*/
|
*/
|
||||||
path = ETCDIR "/epple2/epple2.conf";
|
path = ETCDIR "/epple2/epple2.conf";
|
||||||
pConfig = new std::ifstream(path.c_str());
|
pConfig = new std::ifstream(path.c_str());
|
||||||
if (!pConfig->is_open())
|
if (!pConfig->is_open())
|
||||||
path.clear();
|
path.clear();
|
||||||
}
|
}
|
||||||
if (path.empty())
|
if (path.empty())
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
Last effort to find it (most likely will
|
Try a likely linux location
|
||||||
only work on Linux).
|
*/
|
||||||
*/
|
path = "/etc/epple2/epple2.conf";
|
||||||
path = "/etc/epple2/epple2.conf";
|
pConfig = new std::ifstream(path.c_str());
|
||||||
pConfig = new std::ifstream(path.c_str());
|
if (!pConfig->is_open())
|
||||||
if (!pConfig->is_open())
|
path.clear();
|
||||||
path.clear();
|
}
|
||||||
}
|
if (path.empty())
|
||||||
if (path.empty())
|
{
|
||||||
{
|
/*
|
||||||
std::cerr << "Cannot open config file /etc/epple2/epple2.conf" << std::endl;
|
Try another likely linux location
|
||||||
return;
|
*/
|
||||||
}
|
path = "/etc/epple2.conf";
|
||||||
|
pConfig = new std::ifstream(path.c_str());
|
||||||
|
if (!pConfig->is_open())
|
||||||
|
path.clear();
|
||||||
|
}
|
||||||
|
if (path.empty())
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Last effort to find it.
|
||||||
|
*/
|
||||||
|
path = "epple2.conf";
|
||||||
|
pConfig = new std::ifstream(path.c_str());
|
||||||
|
if (!pConfig->is_open())
|
||||||
|
path.clear();
|
||||||
|
}
|
||||||
|
if (path.empty())
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot open config file /etc/epple2/epple2.conf" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::string line;
|
std::cout << "Reading configuration from file: " << path << std::endl;
|
||||||
std::getline(*pConfig,line);
|
|
||||||
while (!pConfig->eof())
|
std::string line;
|
||||||
{
|
std::getline(*pConfig,line);
|
||||||
strip_comment(line);
|
while (!pConfig->eof())
|
||||||
trim(line);
|
{
|
||||||
if (!line.empty())
|
strip_comment(line);
|
||||||
{
|
trim(line);
|
||||||
|
if (!line.empty())
|
||||||
|
{
|
||||||
parseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut);
|
parseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut);
|
||||||
}
|
}
|
||||||
std::getline(*pConfig,line);
|
std::getline(*pConfig,line);
|
||||||
}
|
}
|
||||||
pConfig->close();
|
pConfig->close();
|
||||||
delete pConfig;
|
delete pConfig;
|
||||||
|
|
||||||
// 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)
|
void Config::parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tryParseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut);
|
tryParseLine(line,ram,rom,slts,revision,gui,cassetteIn,cassetteOut);
|
||||||
}
|
}
|
||||||
catch (const ConfigException& err)
|
catch (const ConfigException& err)
|
||||||
{
|
{
|
||||||
std::cerr << err.msg.c_str() << std::endl;
|
std::cerr << err.msg.c_str() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string filter_row(const std::string &row) {
|
static std::string filter_row(const std::string &row) {
|
||||||
|
@ -195,18 +216,18 @@ static std::string filter_row(const std::string &row) {
|
||||||
|
|
||||||
void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
|
void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut)
|
||||||
{
|
{
|
||||||
std::istringstream tok(line);
|
std::istringstream tok(line);
|
||||||
|
|
||||||
std::string cmd;
|
std::string cmd;
|
||||||
tok >> cmd;
|
tok >> cmd;
|
||||||
if (cmd == "slot")
|
if (cmd == "slot")
|
||||||
{
|
{
|
||||||
int slot;
|
int slot;
|
||||||
std::string sCardType;
|
std::string sCardType;
|
||||||
tok >> slot >> sCardType;
|
tok >> slot >> sCardType;
|
||||||
|
|
||||||
insertCard(sCardType,slot,slts,gui);
|
insertCard(sCardType,slot,slts,gui);
|
||||||
}
|
}
|
||||||
else if (cmd == "motherboard") {
|
else if (cmd == "motherboard") {
|
||||||
std::string op;
|
std::string op;
|
||||||
tok >> op;
|
tok >> op;
|
||||||
|
@ -259,88 +280,88 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd == "import")
|
else if (cmd == "import")
|
||||||
{
|
{
|
||||||
std::string sm;
|
std::string sm;
|
||||||
tok >> sm;
|
tok >> sm;
|
||||||
|
|
||||||
int slot(-1);
|
int slot(-1);
|
||||||
if (sm == "slot")
|
if (sm == "slot")
|
||||||
{
|
{
|
||||||
tok >> slot;
|
tok >> slot;
|
||||||
}
|
}
|
||||||
else if (sm != "motherboard")
|
else if (sm != "motherboard")
|
||||||
{
|
{
|
||||||
throw ConfigException("error at \""+sm+"\"; expected \"slot #\" or \"motherboard\"");
|
throw ConfigException("error at \""+sm+"\"; expected \"slot #\" or \"motherboard\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string romtype;
|
std::string romtype;
|
||||||
tok >> romtype;
|
tok >> romtype;
|
||||||
|
|
||||||
unsigned short base(0);
|
unsigned short base(0);
|
||||||
tok >> std::hex >> base;
|
tok >> std::hex >> base;
|
||||||
|
|
||||||
std::string file;
|
std::string file;
|
||||||
std::getline(tok,file);
|
std::getline(tok,file);
|
||||||
trim(file);
|
trim(file);
|
||||||
std::ifstream memfile(file.c_str(),std::ios::binary);
|
std::ifstream memfile(file.c_str(),std::ios::binary);
|
||||||
if (!memfile.is_open())
|
if (!memfile.is_open())
|
||||||
{
|
{
|
||||||
throw ConfigException("cannot open file "+file);
|
throw ConfigException("cannot open file "+file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slot < 0) // motherboard
|
if (slot < 0) // motherboard
|
||||||
{
|
{
|
||||||
if (romtype == "rom")
|
if (romtype == "rom")
|
||||||
{
|
{
|
||||||
rom.load(base,memfile);
|
rom.load(base,memfile);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw ConfigException("error at \""+romtype+"\"; expected rom or ram");
|
throw ConfigException("error at \""+romtype+"\"; expected rom or ram");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (8 <= slot)
|
if (8 <= slot)
|
||||||
{
|
{
|
||||||
throw ConfigException("invalid slot number");
|
throw ConfigException("invalid slot number");
|
||||||
}
|
}
|
||||||
Card* card = slts.get(slot);
|
Card* card = slts.get(slot);
|
||||||
if (romtype == "rom")
|
if (romtype == "rom")
|
||||||
card->loadRom(base,memfile);
|
card->loadRom(base,memfile);
|
||||||
else if (romtype == "rom7")
|
else if (romtype == "rom7")
|
||||||
card->loadSeventhRom(base,memfile);
|
card->loadSeventhRom(base,memfile);
|
||||||
else if (romtype == "rombank")
|
else if (romtype == "rombank")
|
||||||
card->loadBankRom(base,memfile);
|
card->loadBankRom(base,memfile);
|
||||||
else
|
else
|
||||||
throw ConfigException("error at \""+romtype+"\"; expected rom, rom7, or rombank");
|
throw ConfigException("error at \""+romtype+"\"; expected rom, rom7, or rombank");
|
||||||
}
|
}
|
||||||
memfile.close();
|
memfile.close();
|
||||||
}
|
}
|
||||||
else if (cmd == "load" || cmd == "save" || cmd == "unload")
|
else if (cmd == "load" || cmd == "save" || cmd == "unload")
|
||||||
{
|
{
|
||||||
std::string slotk;
|
std::string slotk;
|
||||||
tok >> slotk;
|
tok >> slotk;
|
||||||
if (slotk != "slot")
|
if (slotk != "slot")
|
||||||
{
|
{
|
||||||
throw ConfigException("error at \""+slotk+"\"; expected \"slot\"");
|
throw ConfigException("error at \""+slotk+"\"; expected \"slot\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
int slot(-1);
|
int slot(-1);
|
||||||
tok >> slot;
|
tok >> slot;
|
||||||
|
|
||||||
std::string drivek;
|
std::string drivek;
|
||||||
tok >> drivek;
|
tok >> drivek;
|
||||||
if (drivek != "drive")
|
if (drivek != "drive")
|
||||||
{
|
{
|
||||||
throw ConfigException("error at \""+drivek+"\"; expected \"drive\"");
|
throw ConfigException("error at \""+drivek+"\"; expected \"drive\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
int drive(-1);
|
int drive(-1);
|
||||||
tok >> drive;
|
tok >> drive;
|
||||||
|
|
||||||
if (cmd == "load")
|
if (cmd == "load")
|
||||||
{
|
{
|
||||||
std::string fn_optional;
|
std::string fn_optional;
|
||||||
std::getline(tok,fn_optional);
|
std::getline(tok,fn_optional);
|
||||||
trim(fn_optional);
|
trim(fn_optional);
|
||||||
|
@ -356,43 +377,43 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo
|
||||||
loadDisk(slts,slot,drive,fn_optional);
|
loadDisk(slts,slot,drive,fn_optional);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd == "unload")
|
else if (cmd == "unload")
|
||||||
{
|
{
|
||||||
unloadDisk(slts,slot,drive);
|
unloadDisk(slts,slot,drive);
|
||||||
}
|
}
|
||||||
else if (cmd == "save")
|
else if (cmd == "save")
|
||||||
{
|
{
|
||||||
saveDisk(slts,slot,drive);
|
saveDisk(slts,slot,drive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cmd == "revision")
|
else if (cmd == "revision")
|
||||||
{
|
{
|
||||||
tok >> std::hex >> revision;
|
tok >> std::hex >> revision;
|
||||||
}
|
}
|
||||||
else if (cmd == "cassette")
|
else if (cmd == "cassette")
|
||||||
{
|
{
|
||||||
std::string cas;
|
std::string cas;
|
||||||
tok >> cas;
|
tok >> cas;
|
||||||
|
|
||||||
if (cas == "rewind")
|
if (cas == "rewind")
|
||||||
{
|
{
|
||||||
cassetteIn.rewind();
|
cassetteIn.rewind();
|
||||||
}
|
}
|
||||||
else if (cas == "tone")
|
else if (cas == "tone")
|
||||||
{
|
{
|
||||||
cassetteIn.tone();
|
cassetteIn.tone();
|
||||||
}
|
}
|
||||||
else if (cas == "blank")
|
else if (cas == "blank")
|
||||||
{
|
{
|
||||||
std::string fcas;
|
std::string fcas;
|
||||||
std::getline(tok,fcas);
|
std::getline(tok,fcas);
|
||||||
trim(fcas);
|
trim(fcas);
|
||||||
if (!fcas.empty()) {
|
if (!fcas.empty()) {
|
||||||
cassetteOut.blank(fcas);
|
cassetteOut.blank(fcas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cas == "load")
|
else if (cas == "load")
|
||||||
{
|
{
|
||||||
std::string fn_optional;
|
std::string fn_optional;
|
||||||
std::getline(tok,fn_optional);
|
std::getline(tok,fn_optional);
|
||||||
trim(fn_optional);
|
trim(fn_optional);
|
||||||
|
@ -407,9 +428,9 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo
|
||||||
if (fn_optional.length() > 0) {
|
if (fn_optional.length() > 0) {
|
||||||
cassetteIn.load(fn_optional);
|
cassetteIn.load(fn_optional);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cas == "eject")
|
else if (cas == "eject")
|
||||||
{
|
{
|
||||||
std::string eject;
|
std::string eject;
|
||||||
tok >> eject;
|
tok >> eject;
|
||||||
if (eject == "in") {
|
if (eject == "in") {
|
||||||
|
@ -420,119 +441,119 @@ void Config::tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memo
|
||||||
throw ConfigException("error: unknown cassette to eject: "+eject);
|
throw ConfigException("error: unknown cassette to eject: "+eject);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cas == "save")
|
else if (cas == "save")
|
||||||
{
|
{
|
||||||
cassetteOut.save();
|
cassetteOut.save();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw ConfigException("error: unknown cassette command: "+cas);
|
throw ConfigException("error: unknown cassette command: "+cas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw ConfigException("Invalid command: "+cmd);
|
throw ConfigException("Invalid command: "+cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
throw ConfigException("Invalid drive; must be 1 or 2");
|
throw ConfigException("Invalid drive; must be 1 or 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO if file doesn't exist, name still gets displayed, and there's no error message
|
// TODO if file doesn't exist, name still gets displayed, and there's no error message
|
||||||
Card* card = slts.get(slot);
|
Card* card = slts.get(slot);
|
||||||
if (!(disk_mask & (1 << slot)))
|
if (!(disk_mask & (1 << slot)))
|
||||||
{
|
{
|
||||||
std::cerr << "Slot " << slot << " doesn't have a disk controller card" << std::endl;
|
std::cerr << "Slot " << slot << " doesn't have a disk controller card" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskController* controller = (DiskController*)card;
|
DiskController* controller = (DiskController*)card;
|
||||||
controller->loadDisk(drive-1,fnib);
|
controller->loadDisk(drive-1,fnib);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::unloadDisk(Slots& slts, int slot, int drive)
|
void Config::unloadDisk(Slots& slts, int slot, int drive)
|
||||||
{
|
{
|
||||||
if (drive < 1 || 2 < drive)
|
if (drive < 1 || 2 < drive)
|
||||||
{
|
{
|
||||||
throw ConfigException("Invalid drive; must be 1 or 2");
|
throw ConfigException("Invalid drive; must be 1 or 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
Card* card = slts.get(slot);
|
Card* card = slts.get(slot);
|
||||||
if (!(disk_mask & (1 << slot)))
|
if (!(disk_mask & (1 << slot)))
|
||||||
{
|
{
|
||||||
std::cerr << "Slot " << slot << " doesn't have a disk controller card" << std::endl;
|
std::cerr << "Slot " << slot << " doesn't have a disk controller card" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
DiskController* controller = (DiskController*)card;
|
DiskController* controller = (DiskController*)card;
|
||||||
controller->unloadDisk(drive-1);
|
controller->unloadDisk(drive-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::saveDisk(Slots& slts, int slot, int drive)
|
void Config::saveDisk(Slots& slts, int slot, int drive)
|
||||||
{
|
{
|
||||||
if (drive < 1 || 2 < drive)
|
if (drive < 1 || 2 < drive)
|
||||||
{
|
{
|
||||||
throw ConfigException("Invalid drive; must be 1 or 2");
|
throw ConfigException("Invalid drive; must be 1 or 2");
|
||||||
}
|
}
|
||||||
slts.get(slot)->save(drive-1);
|
slts.get(slot)->save(drive-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::insertCard(const std::string& cardType, int slot, Slots& slts, ScreenImage& gui)
|
void Config::insertCard(const std::string& cardType, int slot, Slots& slts, ScreenImage& gui)
|
||||||
{
|
{
|
||||||
if (slot < 0 || 8 <= slot)
|
if (slot < 0 || 8 <= slot)
|
||||||
{
|
{
|
||||||
throw ConfigException("Invalid slot number");
|
throw ConfigException("Invalid slot number");
|
||||||
}
|
}
|
||||||
|
|
||||||
Card* card;
|
Card* card;
|
||||||
|
|
||||||
disk_mask &= ~(1 << slot);
|
disk_mask &= ~(1 << slot);
|
||||||
|
|
||||||
if (cardType == "language")
|
if (cardType == "language")
|
||||||
{
|
{
|
||||||
card = new LanguageCard(gui,slot);
|
card = new LanguageCard(gui,slot);
|
||||||
}
|
}
|
||||||
else if (cardType == "firmware")
|
else if (cardType == "firmware")
|
||||||
{
|
{
|
||||||
card = new FirmwareCard(gui,slot);
|
card = new FirmwareCard(gui,slot);
|
||||||
}
|
}
|
||||||
else if (cardType == "disk") // 16-sector LSS ROM
|
else if (cardType == "disk") // 16-sector LSS ROM
|
||||||
{
|
{
|
||||||
card = new DiskController(gui,slot,false);
|
card = new DiskController(gui,slot,false);
|
||||||
disk_mask |= (1 << slot);
|
disk_mask |= (1 << slot);
|
||||||
}
|
}
|
||||||
else if (cardType == "disk13") // 13-sector LSS ROM
|
else if (cardType == "disk13") // 13-sector LSS ROM
|
||||||
{
|
{
|
||||||
card = new DiskController(gui,slot,true);
|
card = new DiskController(gui,slot,true);
|
||||||
disk_mask |= (1 << slot);
|
disk_mask |= (1 << slot);
|
||||||
}
|
}
|
||||||
else if (cardType == "clock")
|
else if (cardType == "clock")
|
||||||
{
|
{
|
||||||
card = new ClockCard();
|
card = new ClockCard();
|
||||||
}
|
}
|
||||||
else if (cardType == "stdout")
|
else if (cardType == "stdout")
|
||||||
{
|
{
|
||||||
card = new StandardOut();
|
card = new StandardOut();
|
||||||
}
|
}
|
||||||
else if (cardType == "stdin")
|
else if (cardType == "stdin")
|
||||||
{
|
{
|
||||||
card = new StandardIn();
|
card = new StandardIn();
|
||||||
}
|
}
|
||||||
else if (cardType == "empty")
|
else if (cardType == "empty")
|
||||||
{
|
{
|
||||||
card = 0;
|
card = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw ConfigException("Invalid card type: "+cardType);
|
throw ConfigException("Invalid card type: "+cardType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (card)
|
if (card)
|
||||||
slts.set(slot,card);
|
slts.set(slot,card);
|
||||||
else
|
else
|
||||||
slts.remove(slot);
|
slts.remove(slot);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,31 +26,29 @@ class ScreenImage;
|
||||||
class CassetteIn;
|
class CassetteIn;
|
||||||
class CassetteOut;
|
class CassetteOut;
|
||||||
|
|
||||||
class ConfigException
|
class ConfigException {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
const std::string msg;
|
const std::string msg;
|
||||||
ConfigException(const std::string& msg) : msg(msg) {}
|
ConfigException(const std::string& msg) : msg(msg) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class Config
|
class Config {
|
||||||
{
|
|
||||||
private:
|
private:
|
||||||
const std::string& file_path;
|
const std::string& file_path;
|
||||||
static unsigned char disk_mask;
|
static unsigned char disk_mask;
|
||||||
|
|
||||||
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);
|
||||||
static void insertCard(const std::string& cardType, int slot, Slots& slts, ScreenImage& gui);
|
static void insertCard(const std::string& cardType, int slot, Slots& slts, ScreenImage& gui);
|
||||||
static void tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
|
static void tryParseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Config(const std::string& file_path);
|
Config(const std::string& file_path);
|
||||||
~Config();
|
~Config();
|
||||||
|
|
||||||
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
|
void parse(MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
|
||||||
static void parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
|
static void parseLine(const std::string& line, MemoryRandomAccess& ram, Memory& rom, Slots& slts, int& revision, ScreenImage& gui, CassetteIn& cassetteIn, CassetteOut& cassetteOut);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -78,7 +78,6 @@ void Emulator::config(Config& cfg) {
|
||||||
|
|
||||||
void Emulator::init() {
|
void Emulator::init() {
|
||||||
powerOffComputer();
|
powerOffComputer();
|
||||||
this->display.setType(AnalogTV::MONITOR_COLOR);
|
|
||||||
this->display.powerOn(true);
|
this->display.powerOn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
30
src/main.cpp
30
src/main.cpp
|
@ -35,16 +35,16 @@
|
||||||
|
|
||||||
|
|
||||||
static int run(const std::string& config_file) {
|
static int run(const std::string& config_file) {
|
||||||
GUI gui;
|
GUI gui;
|
||||||
|
|
||||||
std::unique_ptr<Emulator> emu(new Emulator());
|
std::unique_ptr<Emulator> emu(new Emulator());
|
||||||
|
|
||||||
Config cfg(config_file);
|
Config cfg(config_file);
|
||||||
emu->config(cfg);
|
emu->config(cfg);
|
||||||
|
|
||||||
emu->init();
|
emu->init();
|
||||||
|
|
||||||
return emu->run();
|
return emu->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -54,19 +54,19 @@ int main(int argc, char* argv[]) {
|
||||||
setbuf(stdout, NULL);
|
setbuf(stdout, NULL);
|
||||||
|
|
||||||
if (argc > 2) {
|
if (argc > 2) {
|
||||||
throw std::runtime_error("usage: epple2 [config-file]" );
|
throw std::runtime_error("usage: epple2 [config-file]" );
|
||||||
}
|
}
|
||||||
|
|
||||||
int x = E2Const::test();
|
int x = E2Const::test();
|
||||||
if (x != -1) {
|
if (x != -1) {
|
||||||
std::cerr << x << std::endl;
|
std::cerr << x << std::endl;
|
||||||
throw std::runtime_error("bad constant in e2const.h" );
|
throw std::runtime_error("bad constant in e2const.h" );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string config_file;
|
std::string config_file;
|
||||||
if (argc > 1) {
|
if (argc > 1) {
|
||||||
config_file = argv[1];
|
config_file = argv[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return run(config_file);
|
return run(config_file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ fullscreen(false),
|
||||||
hyper(false),
|
hyper(false),
|
||||||
buffer(true),
|
buffer(true),
|
||||||
fillLines(true),
|
fillLines(true),
|
||||||
display(AnalogTV::MONITOR_COLOR),
|
display(AnalogTV::TV_OLD_COLOR),
|
||||||
slotnames(8),
|
slotnames(8),
|
||||||
cassInName(32, ' '),
|
cassInName(32, ' '),
|
||||||
cassOutName(32, ' ') {
|
cassOutName(32, ' ') {
|
||||||
|
@ -155,9 +155,9 @@ void ScreenImage::drawCassette() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* displays[] = {
|
static const char* displays[] = {
|
||||||
|
"TELEVISION ",
|
||||||
"COLOR MONITOR ",
|
"COLOR MONITOR ",
|
||||||
"GREEN MONITOR ",
|
"GREEN MONITOR ",
|
||||||
"TELEVISION ",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void ScreenImage::drawFnKeys() {
|
void ScreenImage::drawFnKeys() {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user