4 #include "graphics/safemode.h"
7 const char *data_dir
= "data";
8 const char *stage_dir
= "data/Stage";
9 const char *pic_dir
= "endpic";
10 const char *nxdata_dir
= ".";
13 static int fps_so_far
= 0;
14 static uint32_t fpstimer
= 0;
16 #define GAME_WAIT (1000/GAME_FPS) // sets framerate
18 bool freezeframe
= false;
19 int flipacceltime
= 0;
21 int main(int argc
, char *argv
[])
23 bool inhibit_loadfade
= false;
27 SetLogFilename("debug.txt");
28 if (SDL_Init(SDL_INIT_VIDEO
| SDL_INIT_AUDIO
) < 0)
30 staterr("ack, sdl_init failed: %s.", SDL_GetError());
35 // start up inputs first thing because settings_load may remap them
38 // load settings, or at least get the defaults,
39 // so we know the initial screen resolution.
42 if (Graphics::init(settings
->resolution
)) { staterr("Failed to initilize graphics."); return 1; }
43 if (font_init()) { staterr("Failed to load font."); return 1; }
45 if (!settings
->files_extracted
)
55 settings
->files_extracted
= true;
60 if (check_data_exists())
65 //Graphics::ShowLoadingScreen();
66 if (sound_init()) { fatal("Failed to initilize sound."); return 1; }
67 if (trig_init()) { fatal("Failed trig module init."); return 1; }
69 if (tsc_init()) { fatal("Failed to initilize script engine."); return 1; }
70 if (textbox
.Init()) { fatal("Failed to initialize textboxes."); return 1; }
71 if (Carets::init()) { fatal("Failed to initialize carets."); return 1; }
73 if (game
.init()) return 1;
74 game
.setmode(GM_NORMAL
);
75 // set null stage just to have something to do while we go to intro
76 game
.switchstage
.mapno
= 0;
80 game
.switchstage
.mapno
= START_REPLAY
;
81 Replay::set_ffwd(23400);
82 //Replay::set_stopat(3500);
84 //game.switchstage.mapno = LOAD_GAME;
85 //game.pause(GP_OPTIONS);
87 if (settings
->skip_intro
&& file_exists(GetProfileName(settings
->last_save_slot
)))
88 game
.switchstage
.mapno
= LOAD_GAME
;
90 game
.setmode(GM_INTRO
);
94 if (game
.paused
) { game
.switchstage
.mapno
= 0; game
.switchstage
.eventonentry
= 0; }
95 if (game
.switchstage
.mapno
== LOAD_GAME
) inhibit_loadfade
= true;
101 // SSS/SPS persists across stage transitions until explicitly
102 // stopped, or you die & reload. It seems a bit risky to me,
103 // but that's the spec.
104 if (game
.switchstage
.mapno
>= MAPNO_SPECIALS
)
109 // enter next stage, whatever it may be
110 if (game
.switchstage
.mapno
== LOAD_GAME
|| \
111 game
.switchstage
.mapno
== LOAD_GAME_FROM_MENU
)
113 if (game
.switchstage
.mapno
== LOAD_GAME_FROM_MENU
)
116 stat("= Loading game =");
117 if (game_load(settings
->last_save_slot
))
119 fatal("savefile error");
123 Replay::OnGameStarting();
125 if (!inhibit_loadfade
) fade
.Start(FADE_IN
, FADE_CENTER
);
126 else inhibit_loadfade
= false;
128 else if (game
.switchstage
.mapno
== START_REPLAY
)
130 stat(">> beginning replay '%s'", GetReplayName(game
.switchstage
.param
));
133 if (Replay::begin_playback(GetReplayName(game
.switchstage
.param
)))
135 fatal("error starting playback");
141 if (game
.switchstage
.mapno
== NEW_GAME
|| \
142 game
.switchstage
.mapno
== NEW_GAME_FROM_MENU
)
144 bool show_intro
= (game
.switchstage
.mapno
== NEW_GAME_FROM_MENU
);
145 InitNewGame(show_intro
);
148 // slide weapon bar on first intro to Start Point
149 if (game
.switchstage
.mapno
== STAGE_START_POINT
&& \
150 game
.switchstage
.eventonentry
== 91)
156 if (load_stage(game
.switchstage
.mapno
)) goto ingame_error
;
158 player
->x
= (game
.switchstage
.playerx
* TILE_W
) << CSF
;
159 player
->y
= (game
.switchstage
.playery
* TILE_H
) << CSF
;
163 if (game
.initlevel()) return 1;
169 game
.stageboss
.OnMapExit();
188 stat(" ************************************************");
189 stat(" * An in-game error occurred. Game shutting down.");
190 stat(" ************************************************");
200 gametimer
= -GAME_WAIT
*10;
201 game
.switchstage
.mapno
= -1;
203 while(game
.running
&& game
.switchstage
.mapno
< 0)
205 uint32_t curtime
= SDL_GetTicks();
207 if ((curtime
- gametimer
>= GAME_WAIT
) || game
.ffwdtime
)
211 // try to "catch up" if something else on the system bogs us down for a moment.
212 // but if we get really far behind, it's ok to start dropping frames
218 else if ((curtime
- gametimer
> (GAME_WAIT
* 3)))
224 gametimer
+= GAME_WAIT
;
231 static inline void run_tick()
233 static bool can_tick
= true;
234 static bool last_freezekey
= false;
235 static bool last_framekey
= false;
236 static int frameskip
= 0;
240 // input handling for a few global things
241 if (justpushed(ESCKEY
))
243 if (settings
->instant_quit
)
245 game
.running
= false;
247 else if (!game
.paused
) // no pause from Options
249 game
.pause(GP_PAUSED
);
252 else if (justpushed(F3KEY
))
254 game
.pause(GP_OPTIONS
);
258 if (settings
->enable_debug_keys
)
260 if (inputs
[FREEZE_FRAME_KEY
] && !last_freezekey
)
267 if (inputs
[FRAME_ADVANCE_KEY
] && !last_framekey
)
277 last_freezekey
= inputs
[FREEZE_FRAME_KEY
];
278 last_framekey
= inputs
[FRAME_ADVANCE_KEY
];
281 // fast-forward key (F5)
282 if (inputs
[FFWDKEY
] && (settings
->enable_debug_keys
|| Replay::IsPlaying()))
294 sprintf(buf
, "[] Tick %d", framecount
++);
295 font_draw_shaded(4, (SCREEN_HEIGHT
-GetFontHeight()-4), buf
, 0, &greenfont
);
300 Replay::DrawStatus();
303 if (settings
->show_fps
)
322 memcpy(lastinputs
, inputs
, sizeof(lastinputs
));
325 { // frame is frozen; don't hog CPU
329 // immediately after a game tick is when we have the most amount of time before
330 // the game needs to run again. so now's as good a time as any for some
331 // BGM audio processing, wouldn't you say?
339 if ((SDL_GetTicks() - fpstimer
) >= 500)
341 fpstimer
= SDL_GetTicks();
342 fps
= (fps_so_far
<< 1);
347 sprintf(fpstext
, "%d fps", fps
);
349 int x
= (SCREEN_WIDTH
- 4) - GetFontWidth(fpstext
, 0, true);
350 font_draw_shaded(x
, 4, fpstext
, 0, &greenfont
);
354 void InitNewGame(bool with_intro
)
356 stat("= Beginning new game =");
358 memset(game
.flags
, 0, sizeof(game
.flags
));
359 memset(game
.skipflags
, 0, sizeof(game
.skipflags
));
360 textbox
.StageSelect
.ClearSlots();
362 game
.quaketime
= game
.megaquaketime
= 0;
363 game
.showmapnametime
= 0;
368 // fully re-init the player object
369 Objects::DestroyAll(true);
372 player
->maxHealth
= 3;
373 player
->hp
= player
->maxHealth
;
375 game
.switchstage
.mapno
= STAGE_START_POINT
;
376 game
.switchstage
.playerx
= 10;
377 game
.switchstage
.playery
= 8;
378 game
.switchstage
.eventonentry
= (with_intro
) ? 200 : 91;
380 fade
.set_full(FADE_OUT
);
384 void c------------------------------() {}
387 static void fatal(const char *str
)
389 staterr("fatal: '%s'", str
);
391 if (!safemode::init())
393 safemode::moveto(SM_UPPER_THIRD
);
394 safemode::print("Fatal Error");
396 safemode::moveto(SM_CENTER
);
397 safemode::print("%s", str
);
399 safemode::run_until_key();
404 static bool check_data_exists()
406 char fname
[MAXPATHLEN
];
408 sprintf(fname
, "%s/npc.tbl", data_dir
);
409 if (file_exists(fname
)) return 0;
411 if (!safemode::init())
413 safemode::moveto(SM_UPPER_THIRD
);
414 safemode::print("Fatal Error");
416 safemode::moveto(SM_CENTER
);
417 safemode::print("Missing \"%s\" directory.", data_dir
);
418 safemode::print("Please copy it over from a Doukutsu installation.");
420 safemode::run_until_key();
427 void visible_warning(const char *fmt
, ...)
433 vsnprintf(buffer
, sizeof(buffer
), fmt
, ar
);
436 console
.Print(buffer
);