19 #define kPollEveryNFrames 5 //Poll input only every this many frames
20 #define kPollHgwEveryNFrames 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 S9xLoadSDD1Data()
36 Settings.SDD1Pack=FALSE;
39 void S9xAutoSaveSRAM()
41 Memory.SaveSRAM(S9xGetFilename(FILE_SRAM));
46 if (!Memory.Init () || !S9xInitAPU())
47 DIE("Memory or APU failed");
51 S9xSetSoundMute (TRUE);
53 // TODO: PAL/NTSC something better than this
54 Settings.PAL = Settings.ForcePAL;
56 Settings.FrameTime = Settings.PAL?Settings.FrameTimePAL:Settings.FrameTimeNTSC;
57 Memory.ROMFramesPerSecond = Settings.PAL?50:60;
59 IPPU.RenderThisFrame = TRUE;
64 const char * file = S9xGetFilename(FILE_ROM);
66 printf("ROM: %s\n", file);
68 if (!Memory.LoadROM(file))
69 DIE("Loading ROM failed");
71 file = S9xGetFilename(FILE_SRAM);
72 printf("SRAM: %s\n", file);
73 Memory.LoadSRAM(file);
76 static void resumeGame()
78 if (!Config.snapshotLoad) return;
80 const char * file = S9xGetFilename(FILE_FREEZE);
81 int result = S9xUnfreezeGame(file);
83 printf("Unfreeze: %s", file);
87 FILE* fp = fopen(file, "rb");
89 if (Config.snapshotSave) {
90 puts(", but the file exists, so I'm not going to overwrite it");
91 Config.snapshotSave = false;
97 puts(" (file does not exist)");
104 static void pauseGame()
106 if (!Config.snapshotSave) return;
108 const char * file = S9xGetFilename(FILE_FREEZE);
109 int result = S9xFreezeGame(file);
111 printf("Freeze: %s", file);
114 Config.snapshotSave = false; // Serves as a flag to Hgw
121 /* This comes nearly straight from snes9x */
122 static void frameSync() {
123 if (Settings.TurboMode)
125 if(Settings.SkipFrames == AUTO_FRAMERATE ||
126 ++IPPU.FrameSkip >= Settings.SkipFrames)
129 IPPU.SkippedFrames = 0;
130 IPPU.RenderThisFrame = TRUE;
134 ++IPPU.SkippedFrames;
135 IPPU.RenderThisFrame = FALSE;
139 static Uint32 next1 = 0;
140 Uint32 now = SDL_GetTicks();
142 // If there is no known "next" frame, initialize it now
147 // If we're on AUTO_FRAMERATE, we'll display frames always
148 // only if there's excess time.
149 // Otherwise we'll display around 1 frame every 10.
150 unsigned limit = Settings.SkipFrames == AUTO_FRAMERATE
151 ? (next1 < now ? 10 : 1)
152 : Settings.SkipFrames;
154 IPPU.RenderThisFrame = ++IPPU.SkippedFrames >= limit;
155 if (IPPU.RenderThisFrame) {
156 IPPU.SkippedFrames = 0;
158 // If we were behind the schedule, check how much it is
161 unsigned long lag = now - next1;
164 // More than a half-second behind means probably
165 // pause. The next line prevents the magic
166 // fast-forward effect.
172 // If we're now ahead of time, sleep a while
175 SDL_Delay(next1 - now);
176 // SDL will take care if a signal arrives, restarting sleep.
179 // Calculate the timestamp of the next frame.
180 next1 += Settings.FrameTime;
184 /** Wraps s9xProcessEvents, taking care of kPollEveryNFrames */
185 static inline void pollEvents() {
186 static int frames = 0;
188 if (++frames > kPollEveryNFrames) {
189 S9xProcessEvents(FALSE);
194 /** Wraps HgwPollEvents, taking care of kPollHgwEveryNFrames */
195 static inline void pollHgwEvents() {
196 static int frames = 0;
198 if (!hgwLaunched) return;
200 if (++frames > kPollHgwEveryNFrames) {
206 int main(int argc, const char ** argv) {
209 DIE("SDL_Init: %s", SDL_GetError());
212 HgwInit(); // Hildon-games-wrapper initialization.
213 S9xLoadConfig(argc, argv); // Load config files and parse cmd line.
214 HgwConfig(); // Apply specific hildon-games config.
216 // S9x initialization
217 S9xInitDisplay(argc, argv);
218 S9xInitAudioOutput();
219 S9xInitInputDevices();
223 // Load rom and related files: state, unfreeze if needed
227 // Late initialization
228 sprintf(String, "DrNokSnes - %s", Memory.ROMName);
230 S9xHacksLoadFile(Config.hacksFile);
231 if (!S9xGraphicsInit())
232 DIE("S9xGraphicsInit failed");
233 S9xAudioOutputEnable(true);
236 frameSync(); // May block, or set frameskip to true.
237 S9xMainLoop(); // Does CPU things, renders if needed.
240 } while (!Config.quitting);
243 S9xAudioOutputEnable(false);
244 S9xDeinitInputDevices();
245 S9xDeinitAudioOutput();
249 Memory.SaveSRAM(S9xGetFilename(FILE_SRAM));
252 // Late deinitialization
263 void S9xDoAction(unsigned char action)
265 if (action & kActionQuit)
266 Config.quitting = true;
268 if (action & kActionToggleFullscreen) {
269 S9xVideoToggleFullscreen();
272 if (action & kActionQuickLoad1) {
273 const char * file = S9xGetQuickSaveFilename(1);
274 int result = S9xUnfreezeGame(file);
275 S9xSetInfoString("Load slot %u: %s", 1,
276 (result ? "done" : "failed"));
279 if (action & kActionQuickSave1) {
280 const char * file = S9xGetQuickSaveFilename(1);
281 int result = S9xFreezeGame(file);
282 S9xSetInfoString("Save slot %u: %s", 1,
283 (result ? "done" : "failed"));
286 if (action & kActionQuickLoad2) {
287 const char * file = S9xGetQuickSaveFilename(2);
288 int result = S9xUnfreezeGame(file);
289 S9xSetInfoString("Load slot %u: %s", 2,
290 (result ? "done" : "failed"));
293 if (action & kActionQuickSave2) {
294 const char * file = S9xGetQuickSaveFilename(2);
295 int result = S9xFreezeGame(file);
296 S9xSetInfoString("Save slot %u: %s", 2,
297 (result ? "done" : "failed"));