mirror of
https://github.com/devinacker/bsnes-plus.git
synced 2025-04-02 10:52:46 -04:00
263 lines
6.5 KiB
C++
263 lines
6.5 KiB
C++
#include "application.moc"
|
|
VideoDisplay display;
|
|
Application application;
|
|
|
|
#include "init.cpp"
|
|
#include "arguments.cpp"
|
|
|
|
VideoDisplay::VideoDisplay() {
|
|
outputWidth = 0;
|
|
outputHeight = 0;
|
|
|
|
cropLeft = 0;
|
|
cropTop = 0;
|
|
cropRight = 0;
|
|
cropBottom = 0;
|
|
}
|
|
|
|
void Application::initPaths(const char *basename) {
|
|
char temp[PATH_MAX];
|
|
|
|
if(realpath(basename, temp)) {
|
|
//remove program name
|
|
strtr(temp, "\\", "/");
|
|
for(signed i = strlen(temp) - 1; i >= 0; i--) {
|
|
if(temp[i] == '/') {
|
|
temp[i] = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(strend(temp, "/") == false) strcat(temp, "/");
|
|
config().path.base = temp;
|
|
} else {
|
|
config().path.base = "";
|
|
}
|
|
|
|
if(userpath(temp)) {
|
|
strtr(temp, "\\", "/");
|
|
if(strend(temp, "/") == false) strcat(temp, "/");
|
|
config().path.user = temp;
|
|
} else {
|
|
config().path.user = "";
|
|
}
|
|
|
|
char cwd[PATH_MAX];
|
|
config().path.startup = getcwd(cwd);
|
|
}
|
|
|
|
bool Application::singleUserMode() {
|
|
//check if config file exists in executable directory (single-user mode)
|
|
string temp = string() << config().path.base << "bsnes-qt.cfg";
|
|
return file::exists(temp);
|
|
}
|
|
|
|
void Application::locateFile(string &filename, bool createDataDirectory, bool createFile) {
|
|
string temp;
|
|
|
|
if(singleUserMode()) {
|
|
temp = string() << config().path.base << filename;
|
|
} else {
|
|
//if not, use user data path (multi-user mode)
|
|
temp = config().path.user;
|
|
temp << ".bsnes";
|
|
if(createDataDirectory) mkdir(temp, 0755); //ensure directory exists
|
|
temp << "/" << filename;
|
|
}
|
|
|
|
if(createFile && !QFile::exists(temp)) {
|
|
QFile::copy(QString(":/") + filename(), temp);
|
|
}
|
|
|
|
filename = temp;
|
|
}
|
|
|
|
void Application::loadCartridge(const string &filename) {
|
|
if(striend(filename, ".bs")) {
|
|
if(config().path.bsx == "") {
|
|
loaderWindow->loadBsxCartridge("", filename);
|
|
} else {
|
|
cartridge.loadBsx(config().path.bsx, filename);
|
|
}
|
|
|
|
} else if(striend(filename, ".st")) {
|
|
if(config().path.st == "") {
|
|
loaderWindow->loadSufamiTurboCartridge("", filename, "");
|
|
} else {
|
|
cartridge.loadSufamiTurbo(config().path.st, filename, "");
|
|
}
|
|
|
|
} else if(striend(filename, ".gb") || striend(filename, ".sgb") || striend(filename, ".gbc")) {
|
|
if(config().path.sgb == "") {
|
|
loaderWindow->loadSuperGameBoyCartridge("", filename);
|
|
} else {
|
|
cartridge.loadSuperGameBoy(config().path.sgb, filename);
|
|
}
|
|
|
|
} else if(striend(filename, ".spc")) {
|
|
cartridge.loadSpc(filename);
|
|
|
|
} else if(striend(filename, ".snsf") || striend(filename, ".minisnsf")) {
|
|
cartridge.loadSnsf(filename);
|
|
|
|
} else {
|
|
cartridge.loadNormal(filename);
|
|
|
|
}
|
|
}
|
|
|
|
void Application::reloadCartridge() {
|
|
switch (SNES::cartridge.mode()) {
|
|
case SNES::Cartridge::Mode::Normal:
|
|
loadCartridge(cartridge.baseName);
|
|
break;
|
|
|
|
case SNES::Cartridge::Mode::BsxSlotted:
|
|
cartridge.loadBsxSlotted(cartridge.baseName, cartridge.slotAName);
|
|
break;
|
|
|
|
case SNES::Cartridge::Mode::Bsx:
|
|
cartridge.loadBsx(cartridge.baseName, cartridge.slotAName);
|
|
break;
|
|
|
|
case SNES::Cartridge::Mode::SufamiTurbo:
|
|
cartridge.loadSufamiTurbo(cartridge.baseName, cartridge.slotAName, cartridge.slotBName);
|
|
break;
|
|
|
|
case SNES::Cartridge::Mode::SuperGameBoy:
|
|
cartridge.loadSuperGameBoy(cartridge.baseName, cartridge.slotAName);
|
|
break;
|
|
}
|
|
}
|
|
|
|
int Application::main(int &argc, char **argv) {
|
|
app = new App(argc, argv);
|
|
#if !defined(PLATFORM_WIN)
|
|
#if defined(PLATFORM_OSX)
|
|
app->setWindowIcon(QIcon(":/bsnes_512.png"));
|
|
#else
|
|
app->setWindowIcon(QIcon(":/bsnes.png"));
|
|
#endif
|
|
#else
|
|
//Windows port uses 256x256 icon from resource file
|
|
CoInitialize(0);
|
|
utf8_args(argc, argv);
|
|
#endif
|
|
|
|
initPaths(argv[0]);
|
|
locateFile(configFilename = "bsnes-qt.cfg", true);
|
|
locateFile(styleSheetFilename = "style.qss");
|
|
locateFile(cheatsFilename = "cheats.xml", true, true);
|
|
|
|
string customStylesheet;
|
|
if(customStylesheet.readfile(styleSheetFilename) == true) {
|
|
app->setStyleSheet((const char*)customStylesheet);
|
|
} else {
|
|
app->setStyleSheet(defaultStylesheet);
|
|
}
|
|
|
|
config().load(configFilename);
|
|
mapper().bind();
|
|
init();
|
|
SNES::system.init(&interface);
|
|
mainWindow->system_loadSpecial_superGameBoy->setVisible(SNES::supergameboy.opened());
|
|
|
|
parseArguments();
|
|
|
|
timer = new QTimer(this);
|
|
connect(timer, SIGNAL(timeout()), this, SLOT(run()));
|
|
timer->start(0);
|
|
app->exec();
|
|
|
|
//QbWindow::close() saves window geometry for next run
|
|
for(unsigned i = 0; i < windowList.size(); i++) {
|
|
windowList[i]->close();
|
|
}
|
|
|
|
cartridge.unload();
|
|
config().save(configFilename);
|
|
return 0;
|
|
}
|
|
|
|
void Application::run() {
|
|
if(terminate == true) {
|
|
timer->stop();
|
|
app->quit();
|
|
return;
|
|
}
|
|
|
|
utility.updateSystemState();
|
|
mapper().poll();
|
|
|
|
if(config().input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation) {
|
|
bool active = mainWindow->isActive();
|
|
if(!autopause && !active) {
|
|
autopause = true;
|
|
audio.clear();
|
|
} else if(autopause && active) {
|
|
autopause = false;
|
|
}
|
|
} else {
|
|
autopause = false;
|
|
}
|
|
|
|
if(SNES::cartridge.loaded() && !pause && !autopause && (!debug || debugrun)) {
|
|
SNES::system.run();
|
|
#if defined(DEBUGGER)
|
|
if(SNES::debugger.break_event != SNES::Debugger::BreakEvent::None) {
|
|
debug = !SNES::debugger.log_without_break;
|
|
debugrun = false;
|
|
debugger->synchronize();
|
|
debugger->event();
|
|
SNES::debugger.break_event = SNES::Debugger::BreakEvent::None;
|
|
}
|
|
#endif
|
|
if(frameAdvance && SNES::scheduler.exit_reason() == SNES::Scheduler::ExitReason::FrameEvent) {
|
|
pause = true;
|
|
}
|
|
} else {
|
|
usleep(1000);
|
|
if (frameAdvance) {
|
|
audio.clear();
|
|
frameAdvance = false;
|
|
}
|
|
}
|
|
|
|
clock_t currentTime = clock();
|
|
autosaveTime += currentTime - clockTime;
|
|
screensaverTime += currentTime - clockTime;
|
|
clockTime = currentTime;
|
|
|
|
if(autosaveTime >= CLOCKS_PER_SEC * 60) {
|
|
//auto-save RAM once per minute in case of emulator crash
|
|
autosaveTime = 0;
|
|
if(config().system.autoSaveMemory == true) cartridge.saveMemory();
|
|
}
|
|
}
|
|
|
|
Application::Application() : timer(0) {
|
|
terminate = false;
|
|
power = false;
|
|
frameAdvance = false;
|
|
pause = false;
|
|
autopause = false;
|
|
debug = false;
|
|
debugrun = false;
|
|
|
|
clockTime = clock();
|
|
autosaveTime = 0;
|
|
screensaverTime = 0;
|
|
|
|
loadType = SNES::Cartridge::Mode::Normal;
|
|
|
|
#ifdef PLATFORM_X
|
|
app->inhibitScreenSaver();
|
|
#endif
|
|
}
|
|
|
|
Application::~Application() {
|
|
delete timer;
|
|
|
|
//deleting (QApplication)app will segfault the application upon exit
|
|
//delete app;
|
|
}
|