16 #include "screenshot.h"
18 #define kPollEveryNFrames 2 //Poll input only every this many frames
22 #define kPollOssoEveryNFrames 10 //Poll dbus only every this many frames
25 #define TRACE printf("trace: %s:%s\n", __FILE__, __func__);
26 #define DIE(format, ...) do { \
27 fprintf(stderr, "Died at %s:%d: ", __FILE__, __LINE__ ); \
28 fprintf(stderr, format "\n", ## __VA_ARGS__); \
32 void S9xMessage(int type, int number, const char * message)
34 printf("%s\n", message);
37 void S9xAutoSaveSRAM()
39 Memory.SaveSRAM(S9xGetFilename(FILE_SRAM));
44 if (!Memory.Init () || !S9xInitAPU())
45 DIE("Memory or APU failed");
49 S9xSetSoundMute (TRUE);
51 // TODO: PAL/NTSC something better than this
52 Settings.PAL = Settings.ForcePAL;
54 Settings.FrameTime = Settings.PAL?Settings.FrameTimePAL:Settings.FrameTimeNTSC;
55 Memory.ROMFramesPerSecond = Settings.PAL?50:60;
57 IPPU.RenderThisFrame = TRUE;
62 const char * file = S9xGetFilename(FILE_ROM);
64 printf("ROM: %s\n", file);
66 if (!Memory.LoadROM(file))
67 DIE("Loading ROM failed");
69 file = S9xGetFilename(FILE_SRAM);
70 printf("SRAM: %s\n", file);
71 Memory.LoadSRAM(file);
74 static void resumeGame()
76 if (!Config.snapshotLoad) return;
78 const char * file = S9xGetFilename(FILE_FREEZE);
79 int result = S9xUnfreezeGame(file);
81 printf("Unfreeze: %s", file);
85 FILE* fp = fopen(file, "rb");
87 if (Config.snapshotSave) {
88 puts(", but the file exists, so I'm not going to overwrite it");
89 Config.snapshotSave = false;
95 puts(" (file does not exist)");
102 static void pauseGame()
104 if (!Config.snapshotSave) return;
106 const char * file = S9xGetFilename(FILE_FREEZE);
107 int result = S9xFreezeGame(file);
109 printf("Freeze: %s", file);
112 Config.snapshotSave = false; // Serves as a flag to Hgw
119 /* This comes nearly straight from snes9x */
120 /** Calculates framerate, enables frame skip if to low, sleeps if too high, etc. */
121 static void frameSync() {
122 Uint32 now = SDL_GetTicks();
124 if (Settings.TurboMode)
126 // In Turbo mode, just skip as many frames as desired, but don't sleep.
127 if(Settings.SkipFrames == AUTO_FRAMERATE ||
128 ++IPPU.FrameSkip >= Settings.SkipFrames)
131 IPPU.SkippedFrames = 0;
132 IPPU.RenderThisFrame = TRUE;
136 ++IPPU.SkippedFrames;
137 IPPU.RenderThisFrame = FALSE;
140 // Take care of framerate display
141 if (Settings.DisplayFrameRate) {
142 static Uint32 last = 0;
143 // Update framecounter every second
144 if (now > last && (now - last > 1000)) {
145 IPPU.DisplayedRenderedFrameCount =
146 IPPU.RenderedFramesCount;
147 IPPU.RenderedFramesCount = 0;
152 static Uint32 next1 = 0;
154 // If there is no known "next" frame, initialize it now
159 // If we're on AUTO_FRAMERATE, we'll display frames always
160 // only if there's excess time.
161 // Otherwise we'll display around 1 frame every 10.
162 unsigned limit = Settings.SkipFrames == AUTO_FRAMERATE
163 ? (next1 < now ? 10 : 1)
164 : Settings.SkipFrames;
166 IPPU.RenderThisFrame = ++IPPU.SkippedFrames >= limit;
167 if (IPPU.RenderThisFrame) {
168 IPPU.SkippedFrames = 0;
170 // If we were behind the schedule, check how much it is
173 unsigned long lag = now - next1;
176 // More than a half-second behind means probably
177 // pause. The next line prevents the magic
178 // fast-forward effect.
184 // If we're now ahead of time, sleep a while
187 SDL_Delay(next1 - now);
188 // SDL will take care if a signal arrives, restarting sleep.
191 // Calculate the timestamp of the next frame.
192 next1 += Settings.FrameTime;
194 // Take care of framerate display
195 if (Settings.DisplayFrameRate) {
196 // Update every theoretical 60 frames
197 if (IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) {
198 IPPU.DisplayedRenderedFrameCount =
199 IPPU.RenderedFramesCount;
200 IPPU.RenderedFramesCount = 0;
206 /** Wraps s9xProcessEvents, taking care of kPollEveryNFrames */
207 static inline void pollEvents() {
208 static int frames = 0;
210 if (++frames > kPollEveryNFrames) {
211 S9xProcessEvents(false);
217 /** Wraps OssoPollEvents, taking care of kPollOssoEveryNFrames */
218 static inline void pollOssoEvents() {
219 static int frames = 0;
221 if (!OssoOk()) return;
223 if (++frames > kPollOssoEveryNFrames) {
230 int main(int argc, char ** argv) {
233 DIE("SDL_Init: %s", SDL_GetError());
237 OssoInit(); // Hildon-games-wrapper initialization.
239 S9xLoadConfig(argc, argv); // Load config files and parse cmd line.
241 OssoConfig(); // Apply specific hildon-games config.
244 // S9x initialization
245 S9xInitDisplay(argc, argv);
246 S9xInitAudioOutput();
247 S9xInitInputDevices();
251 // Load rom and related files: state, unfreeze if needed
255 // Late initialization
256 sprintf(String, "DrNokSnes - %s", Memory.ROMName);
258 S9xHacksLoadFile(Config.hacksFile);
259 if (!S9xGraphicsInit())
260 DIE("S9xGraphicsInit failed");
261 S9xAudioOutputEnable(true);
264 frameSync(); // May block, or set frameskip to true.
265 S9xMainLoop(); // Does CPU things, renders if needed.
270 } while (!Config.quitting);
273 S9xAudioOutputEnable(false);
274 S9xDeinitInputDevices();
277 Memory.SaveSRAM(S9xGetFilename(FILE_SRAM));
281 S9xDeinitAudioOutput();
295 void S9xDoAction(unsigned char action)
297 if (action & kActionQuit)
298 Config.quitting = true;
300 if (action & kActionToggleFullscreen) {
301 S9xVideoToggleFullscreen();
305 if (action & kActionScreenshot) {
306 S9xSaveScreenshot(S9xGetFilename(FILE_SCREENSHOT));
307 S9xSetInfoString("Screenshot taken");
311 if (action & kActionQuickLoad1) {
312 const char * file = S9xGetQuickSaveFilename(1);
313 int result = S9xUnfreezeGame(file);
314 S9xSetInfoString("Load slot %u: %s", 1,
315 (result ? "done" : "failed"));
318 if (action & kActionQuickSave1) {
319 const char * file = S9xGetQuickSaveFilename(1);
320 int result = S9xFreezeGame(file);
321 S9xSetInfoString("Save slot %u: %s", 1,
322 (result ? "done" : "failed"));
325 if (action & kActionQuickLoad2) {
326 const char * file = S9xGetQuickSaveFilename(2);
327 int result = S9xUnfreezeGame(file);
328 S9xSetInfoString("Load slot %u: %s", 2,
329 (result ? "done" : "failed"));
332 if (action & kActionQuickSave2) {
333 const char * file = S9xGetQuickSaveFilename(2);
334 int result = S9xFreezeGame(file);
335 S9xSetInfoString("Save slot %u: %s", 2,
336 (result ? "done" : "failed"));