AppleWin/source/frontends/ncurses/main.cpp
Andrea Odetti 3733da1af7 Remove configuration from libappleii and delegate it to the frontends.
In qapple we use QSettings.


Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
2017-10-14 19:18:44 +01:00

322 lines
7.2 KiB
C++

#include "StdAfx.h"
#include <chrono>
#include <iostream>
#include <unistd.h>
#include <ncurses.h>
#include <boost/program_options.hpp>
#include "Common.h"
#include "Applewin.h"
#include "Disk.h"
#include "Harddisk.h"
#include "Log.h"
#include "CPU.h"
#include "Frame.h"
#include "Memory.h"
#include "ParallelPrinter.h"
#include "Video.h"
#include "SaveState.h"
#include "linux/data.h"
#include "linux/benchmark.h"
#include "frontends/ncurses/configuration.h"
#include "frontends/ncurses/world.h"
namespace
{
namespace po = boost::program_options;
struct EmulatorOptions
{
std::string disk1;
std::string disk2;
bool createMissingDisks;
std::string snapshot;
int memclear;
bool benchmark;
bool saveConfigurationOnExit;
bool run; // false if options include "-h"
};
bool getEmulatorOptions(int argc, const char * argv [], EmulatorOptions & options)
{
po::options_description desc("AppleWin ncurses");
desc.add_options()
("help,h", "Print this help message")
("conf", "Save configuration on exit");
po::options_description diskDesc("Disk");
diskDesc.add_options()
("d1,1", po::value<std::string>(), "Mount disk image in first drive")
("d2,2", po::value<std::string>(), "Mount disk image in second drive")
("create,c", "Create missing disks");
desc.add(diskDesc);
po::options_description snapshotDesc("Snapshot");
snapshotDesc.add_options()
("load-state,ls", po::value<std::string>(), "Load snapshot from file");
desc.add(snapshotDesc);
po::options_description memoryDesc("Memory");
memoryDesc.add_options()
("memclear,m", po::value<int>(), "Memory initialization pattern [0..7]");
desc.add(memoryDesc);
po::options_description emulatorDesc("Emulator");
emulatorDesc.add_options()
("benchmark,b", "Benchmark emulator");
desc.add(emulatorDesc);
po::variables_map vm;
try
{
po::store(po::parse_command_line(argc, argv, desc), vm);
if (vm.count("help"))
{
std::cout << "AppleWin ncurses edition" << std::endl << std::endl << desc << std::endl;
return false;
}
options.saveConfigurationOnExit = vm.count("conf");
if (vm.count("d1"))
{
options.disk1 = vm["d1"].as<std::string>();
}
if (vm.count("d2"))
{
options.disk2 = vm["d2"].as<std::string>();
}
options.createMissingDisks = vm.count("create") > 0;
if (vm.count("load-state"))
{
options.snapshot = vm["load-state"].as<std::string>();
}
if (vm.count("memclear"))
{
const int memclear = vm["memclear"].as<int>();
if (memclear >=0 && memclear < NUM_MIP)
options.memclear = memclear;
}
options.benchmark = vm.count("benchmark") > 0;
return true;
}
catch (const po::error& e)
{
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 ContinueExecution()
{
const auto start = std::chrono::steady_clock::now();
const double fUsecPerSec = 1.e6;
#if 1
const UINT nExecutionPeriodUsec = 1000000 / 60; // 60 FPS
// const UINT nExecutionPeriodUsec = 100; // 0.1ms
const double fExecutionPeriodClks = g_fCurrentCLK6502 * ((double)nExecutionPeriodUsec / fUsecPerSec);
#else
const double fExecutionPeriodClks = 1800.0;
const UINT nExecutionPeriodUsec = (UINT) (fUsecPerSec * (fExecutionPeriodClks / g_fCurrentCLK6502));
#endif
const DWORD uCyclesToExecute = fExecutionPeriodClks;
const bool bVideoUpdate = false;
const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate);
g_dwCyclesThisFrame += uActualCyclesExecuted;
DiskUpdatePosition(uActualCyclesExecuted);
const int key = ProcessKeyboard();
switch (key)
{
case KEY_F(2):
{
return false;
}
case KEY_F(12):
{
// F12: as F11 is already Fullscreen in the terminal
// To load an image, use command line options
Snapshot_SetFilename("");
Snapshot_SaveState();
break;
}
}
ProcessInput();
if (g_dwCyclesThisFrame >= dwClksPerFrame)
{
g_dwCyclesThisFrame -= dwClksPerFrame;
VideoRedrawScreen();
}
const auto end = std::chrono::steady_clock::now();
const auto diff = end - start;
const long us = std::chrono::duration_cast<std::chrono::microseconds>(diff).count();
const double coeff = exp(-0.000001 * nExecutionPeriodUsec); // 0.36 after 1 second
g_relativeSpeed = g_relativeSpeed * coeff + double(us) / double(nExecutionPeriodUsec) * (1.0 - coeff);
if (!DiskIsSpinning())
{
if (us < nExecutionPeriodUsec)
{
usleep(nExecutionPeriodUsec - us);
}
}
return true;
}
void EnterMessageLoop()
{
while (ContinueExecution())
{
}
}
bool DoDiskInsert(const int nDrive, const std::string & fileName, const bool createMissingDisk)
{
std::string strPathName;
if (fileName.empty())
{
return false;
}
if (fileName[0] == '/')
{
// Abs pathname
strPathName = fileName;
}
else
{
// Rel pathname
char szCWD[MAX_PATH] = {0};
if (!GetCurrentDirectory(sizeof(szCWD), szCWD))
return false;
strPathName = szCWD;
strPathName.append("/");
strPathName.append(fileName);
}
ImageError_e Error = DiskInsert(nDrive, strPathName.c_str(), IMAGE_USE_FILES_WRITE_PROTECT_STATUS, createMissingDisk);
return Error == eIMAGE_ERROR_NONE;
}
int foo(int argc, const char * argv [])
{
g_fh = fopen("/tmp/applewin.txt", "w");
setbuf(g_fh, NULL);
EmulatorOptions options;
options.memclear = g_nMemoryClearType;
const bool run = getEmulatorOptions(argc, argv, options);
if (!run)
return 1;
InitializeRegistry("applen.conf");
g_nMemoryClearType = options.memclear;
LogFileOutput("Initialisation\n");
ImageInitialize();
DiskInitialize();
bool disksOk = true;
if (!options.disk1.empty())
{
const bool ok = DoDiskInsert(DRIVE_1, options.disk1, options.createMissingDisks);
disksOk = disksOk && ok;
LogFileOutput("Init: DoDiskInsert(D1), res=%d\n", ok);
}
if (!options.disk2.empty())
{
const bool ok = DoDiskInsert(DRIVE_2, options.disk2, options.createMissingDisks);
disksOk = disksOk && ok;
LogFileOutput("Init: DoDiskInsert(D2), res=%d\n", ok);
}
if (disksOk)
{
// AFTER a restart
do
{
LoadConfiguration();
CheckCpu();
FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
MemInitialize();
VideoInitialize();
DiskReset();
if (!options.snapshot.empty())
{
Snapshot_SetFilename(options.snapshot.c_str());
Snapshot_LoadState();
}
if (options.benchmark)
{
VideoBenchmark(&VideoRedrawScreen);
g_bRestart = false;
}
else
{
EnterMessageLoop();
}
}
while (g_bRestart);
VideoUninitialize();
}
else
{
LogOutput("Disk error.");
}
HD_Destroy();
PrintDestroy();
CpuDestroy();
MemDestroy();
DiskDestroy();
ImageDestroy();
return 0;
}
}
int main(int argc, const char * argv [])
{
return foo(argc, argv);
}