19 #define kPollEveryNFrames 5 //Poll input only every this many frames
20 #define kPollOssoEveryNFrames 10 //Poll dbus only every this many frames
22 #define TRACE printf("trace: %s:%s\n", __FILE__, __func__);
23 #define DIE(format, ...) do { \
24 fprintf(stderr, "Died at %s:%d: ", __FILE__, __LINE__ ); \
25 fprintf(stderr, format "\n", ## __VA_ARGS__); \
29 void S9xMessage(int type, int number, const char * message)
31 printf("%s\n", message);
34 void S9xAutoSaveSRAM()
36 Memory.SaveSRAM(S9xGetFilename(FILE_SRAM));
41 if (!Memory.Init () || !S9xInitAPU())
42 DIE("Memory or APU failed");
46 S9xSetSoundMute (TRUE);
48 // TODO: PAL/NTSC something better than this
49 Settings.PAL = Settings.ForcePAL;
51 Settings.FrameTime = Settings.PAL?Settings.FrameTimePAL:Settings.FrameTimeNTSC;
52 Memory.ROMFramesPerSecond = Settings.PAL?50:60;
54 IPPU.RenderThisFrame = TRUE;
59 const char * file = S9xGetFilename(FILE_ROM);
61 printf("ROM: %s\n", file);
63 if (!Memory.LoadROM(file))
64 DIE("Loading ROM failed");
66 file = S9xGetFilename(FILE_SRAM);
67 printf("SRAM: %s\n", file);
68 Memory.LoadSRAM(file);
71 static void resumeGame()
73 if (!Config.snapshotLoad) return;
75 const char * file = S9xGetFilename(FILE_FREEZE);
76 int result = S9xUnfreezeGame(file);
78 printf("Unfreeze: %s", file);
82 FILE* fp = fopen(file, "rb");
84 if (Config.snapshotSave) {
85 puts(", but the file exists, so I'm not going to overwrite it");
86 Config.snapshotSave = false;
92 puts(" (file does not exist)");
99 static void pauseGame()
101 if (!Config.snapshotSave) return;
103 const char * file = S9xGetFilename(FILE_FREEZE);
104 int result = S9xFreezeGame(file);
106 printf("Freeze: %s", file);
109 Config.snapshotSave = false; // Serves as a flag to Hgw
116 /* This comes nearly straight from snes9x */
117 /** Calculates framerate, enables frame skip if to low, sleeps if too high, etc. */
118 static void frameSync() {
119 Uint32 now = SDL_GetTicks();
121 if (Settings.TurboMode)
123 // In Turbo mode, just skip as many frames as desired, but don't sleep.
124 if(Settings.SkipFrames == AUTO_FRAMERATE ||
125 ++IPPU.FrameSkip >= Settings.SkipFrames)
128 IPPU.SkippedFrames = 0;
129 IPPU.RenderThisFrame = TRUE;
133 ++IPPU.SkippedFrames;
134 IPPU.RenderThisFrame = FALSE;
137 // Take care of framerate display
138 if (Settings.DisplayFrameRate) {
139 static Uint32 last = 0;
140 // Update framecounter every second
141 if (now > last && (now - last > 1000)) {
142 IPPU.DisplayedRenderedFrameCount =
143 IPPU.RenderedFramesCount;
144 IPPU.RenderedFramesCount = 0;
149 static Uint32 next1 = 0;
151 // If there is no known "next" frame, initialize it now
156 // If we're on AUTO_FRAMERATE, we'll display frames always
157 // only if there's excess time.
158 // Otherwise we'll display around 1 frame every 10.
159 unsigned limit = Settings.SkipFrames == AUTO_FRAMERATE
160 ? (next1 < now ? 10 : 1)
161 : Settings.SkipFrames;
163 IPPU.RenderThisFrame = ++IPPU.SkippedFrames >= limit;
164 if (IPPU.RenderThisFrame) {
165 IPPU.SkippedFrames = 0;
167 // If we were behind the schedule, check how much it is
170 unsigned long lag = now - next1;
173 // More than a half-second behind means probably
174 // pause. The next line prevents the magic
175 // fast-forward effect.
181 // If we're now ahead of time, sleep a while
184 SDL_Delay(next1 - now);
185 // SDL will take care if a signal arrives, restarting sleep.
188 // Calculate the timestamp of the next frame.
189 next1 += Settings.FrameTime;
191 // Take care of framerate display
192 if (Settings.DisplayFrameRate) {
193 // Update every theoretical 60 frames
194 if (IPPU.FrameCount % Memory.ROMFramesPerSecond == 0) {
195 IPPU.DisplayedRenderedFrameCount =
196 IPPU.RenderedFramesCount;
197 IPPU.RenderedFramesCount = 0;
203 /** Wraps s9xProcessEvents, taking care of kPollEveryNFrames */
204 static inline void pollEvents() {
205 static int frames = 0;
207 if (++frames > kPollEveryNFrames) {
208 S9xProcessEvents(false);
214 /** Wraps OssoPollEvents, taking care of kPollOssoEveryNFrames */
215 static inline void pollOssoEvents() {
216 static int frames = 0;
218 if (!OssoOk()) return;
220 if (++frames > kPollOssoEveryNFrames) {
227 int main(int argc, char ** argv) {
230 DIE("SDL_Init: %s", SDL_GetError());
234 OssoInit(); // Hildon-games-wrapper initialization.
236 S9xLoadConfig(argc, argv); // Load config files and parse cmd line.
238 OssoConfig(); // Apply specific hildon-games config.
241 // S9x initialization
242 S9xInitDisplay(argc, argv);
243 S9xInitAudioOutput();
244 S9xInitInputDevices();
248 // Load rom and related files: state, unfreeze if needed
252 // Late initialization
253 sprintf(String, "DrNokSnes - %s", Memory.ROMName);
255 S9xHacksLoadFile(Config.hacksFile);
256 if (!S9xGraphicsInit())
257 DIE("S9xGraphicsInit failed");
258 S9xAudioOutputEnable(true);
261 frameSync(); // May block, or set frameskip to true.
262 S9xMainLoop(); // Does CPU things, renders if needed.
267 } while (!Config.quitting);
270 S9xAudioOutputEnable(false);
271 S9xDeinitInputDevices();
272 S9xDeinitAudioOutput();
276 Memory.SaveSRAM(S9xGetFilename(FILE_SRAM));
279 // Late deinitialization
292 void S9xDoAction(unsigned char action)
294 if (action & kActionQuit)
295 Config.quitting = true;
297 if (action & kActionToggleFullscreen) {
298 S9xVideoToggleFullscreen();
301 if (action & kActionQuickLoad1) {
302 const char * file = S9xGetQuickSaveFilename(1);
303 int result = S9xUnfreezeGame(file);
304 S9xSetInfoString("Load slot %u: %s", 1,
305 (result ? "done" : "failed"));
308 if (action & kActionQuickSave1) {
309 const char * file = S9xGetQuickSaveFilename(1);
310 int result = S9xFreezeGame(file);
311 S9xSetInfoString("Save slot %u: %s", 1,
312 (result ? "done" : "failed"));
315 if (action & kActionQuickLoad2) {
316 const char * file = S9xGetQuickSaveFilename(2);
317 int result = S9xUnfreezeGame(file);
318 S9xSetInfoString("Load slot %u: %s", 2,
319 (result ? "done" : "failed"));
322 if (action & kActionQuickSave2) {
323 const char * file = S9xGetQuickSaveFilename(2);
324 int result = S9xFreezeGame(file);
325 S9xSetInfoString("Save slot %u: %s", 2,
326 (result ? "done" : "failed"));