1 #include "application.moc"
2 Application application;
3
4 #include "init.cpp"
5 #include "qb.cpp"
6
initPaths(const char * basename)7 void Application::initPaths(const char *basename) {
8 char temp[PATH_MAX];
9
10 if(realpath(basename, temp)) {
11 //remove program name
12 strtr(temp, "\\", "/");
13 for(signed i = strlen(temp) - 1; i >= 0; i--) {
14 if(temp[i] == '/') {
15 temp[i] = 0;
16 break;
17 }
18 }
19
20 if(strend(temp, "/") == false) strcat(temp, "/");
21 config().path.base = temp;
22 } else {
23 config().path.base = "";
24 }
25
26 if(userpath(temp)) {
27 strtr(temp, "\\", "/");
28 if(strend(temp, "/") == false) strcat(temp, "/");
29 config().path.user = temp;
30 } else {
31 config().path.user = "";
32 }
33
34 char cwd[PATH_MAX];
35 config().path.startup = getcwd(cwd);
36 }
37
locateFile(string & filename,bool createDataDirectory)38 void Application::locateFile(string &filename, bool createDataDirectory) {
39 //first, check if file exists in executable directory (single-user mode)
40 string temp = string() << config().path.base << filename;
41
42 if(file::exists(temp) == false) {
43 //if not, use user data path (multi-user mode)
44 temp = config().path.user;
45 temp << ".bsnes";
46 if(createDataDirectory) mkdir(temp); //ensure directory exists
47 temp << "/" << filename;
48 }
49
50 filename = temp;
51 }
52
main(int & argc,char ** argv)53 int Application::main(int &argc, char **argv) {
54 app = new App(argc, argv);
55 #if !defined(PLATFORM_WIN)
56 //Windows port uses 256x256 icon from resource file
57 app->setWindowIcon(QIcon(":/bsnes.png"));
58 #endif
59
60 initargs(argc, argv); //ensure argv[]s are in UTF-8 format
61 initPaths(argv[0]);
62 locateFile(configFilename = "bsnes.cfg", true);
63 locateFile(styleSheetFilename = "style.qss", false);
64
65 string customStylesheet;
66 if(customStylesheet.readfile(styleSheetFilename) == true) {
67 app->setStyleSheet((const char*)customStylesheet);
68 } else {
69 app->setStyleSheet(defaultStylesheet);
70 }
71
72 config().load(configFilename);
73 mapper().bind();
74 init();
75 SNES::system.init(&interface);
76 mainWindow->system_loadSpecial_superGameBoy->setVisible(SNES::supergameboy.opened());
77
78 if(argc == 2) {
79 //if valid file was specified on the command-line, attempt to load it now
80 cartridge.loadNormal(argv[1]);
81 }
82
83 timer = new QTimer(this);
84 connect(timer, SIGNAL(timeout()), this, SLOT(run()));
85 timer->start(0);
86 app->exec();
87
88 //QbWindow::hide() saves window geometry for next run
89 for(unsigned i = 0; i < windowList.size(); i++) {
90 windowList[i]->hide();
91 }
92
93 cartridge.unload();
94 config().save(configFilename);
95 return 0;
96 }
97
run()98 void Application::run() {
99 if(terminate == true) {
100 timer->stop();
101 app->quit();
102 return;
103 }
104
105 QApplication::processEvents();
106 utility.updateSystemState();
107 mapper().poll();
108
109 if(config().input.focusPolicy == Configuration::Input::FocusPolicyPauseEmulation) {
110 bool active = mainWindow->isActive();
111 if(!autopause && !active) {
112 autopause = true;
113 audio.clear();
114 } else if(autopause && active) {
115 autopause = false;
116 }
117 } else {
118 autopause = false;
119 }
120
121 if(SNES::cartridge.loaded() && !pause && !autopause && (!debug || debugrun)) {
122 SNES::system.run();
123 #if defined(DEBUGGER)
124 if(SNES::debugger.break_event != SNES::Debugger::None) {
125 debug = true;
126 debugrun = false;
127 debugger->synchronize();
128 debugger->event();
129 SNES::debugger.break_event = SNES::Debugger::None;
130 }
131 #endif
132 } else {
133 usleep(20 * 1000);
134 }
135
136 clock_t currentTime = clock();
137 autosaveTime += currentTime - clockTime;
138 screensaverTime += currentTime - clockTime;
139 clockTime = currentTime;
140
141 if(autosaveTime >= CLOCKS_PER_SEC * 60) {
142 //auto-save RAM once per minute in case of emulator crash
143 autosaveTime = 0;
144 if(config().system.autoSaveMemory == true) cartridge.saveMemory();
145 }
146
147 if(screensaverTime >= CLOCKS_PER_SEC * 30) {
148 //supress screen saver every 30 seconds so it will not trigger during gameplay
149 screensaverTime = 0;
150 supressScreenSaver();
151 }
152 }
153
Application()154 Application::Application() : timer(0) {
155 terminate = false;
156 power = false;
157 pause = false;
158 autopause = false;
159 debug = false;
160 debugrun = false;
161
162 clockTime = clock();
163 autosaveTime = 0;
164 screensaverTime = 0;
165 }
166
~Application()167 Application::~Application() {
168 delete timer;
169
170 //deleting (QApplication)app will segfault the application upon exit
171 //delete app;
172 }
173