1 
2 #include "../nx.h"
3 #include "../main.fdh"
4 #include "libretro_shared.h"
5 #include "extract-auto/cachefiles.h"
6 
7 #ifdef _WIN32
8 #include "msvc_compat.h"
9 #endif
10 
11 const char *data_dir = "data";
12 #ifdef _WIN32
13 const char *stage_dir = "data\\Stage";
14 #else
15 const char *stage_dir = "data/Stage";
16 #endif
17 const char *pic_dir = "endpic";
18 const char *nxdata_dir = ".";
19 
20 int fps = 0;
21 static int fps_so_far = 0;
22 static uint32_t fpstimer = 0;
23 
24 #define GAME_WAIT			(1000/GAME_FPS)	// sets framerate
25 #define VISFLAGS			(SDL_APPACTIVE | SDL_APPINPUTFOCUS)
26 int framecount = 0;
27 bool freezeframe = false;
28 
29 static bool inhibit_loadfade = false;
30 static bool freshstart;
31 
32 //extern bool extract_files(FILE *exefp);
33 extern bool extract_stages(FILE *exefp);
34 
pre_main(void)35 bool pre_main(void)
36 {
37    char filename[1024];
38    FILE *fp;
39 
40 #ifdef DEBUG_LOG
41    char debug_fname[1024];
42    retro_create_path_string(debug_fname, sizeof(debug_fname), g_dir, "debug.txt");
43    SetLogFilename(debug_fname);
44 #endif
45    // start up inputs first thing because settings_load may remap them
46    input_init();
47 
48    // load settings, or at least get the defaults,
49    // so we know the initial screen resolution.
50    settings_load();
51 
52    NX_LOG("= Extracting Files =\n");
53 
54    retro_create_path_string(filename, sizeof(filename), g_dir, "Doukutsu.exe");
55    fp = fopen(filename, "rb");
56 
57    //extract_files(fp);
58    if (!cachefiles_init(fp))
59       return 1;
60 
61    if (sound_init(fp))
62    {
63       fatal("Failed to initialize sound.");
64       return 1;
65    }
66 
67    if (extract_stages(fp))
68    {
69       fclose(fp);
70       return 1;
71    }
72 
73    fclose(fp);
74 
75    settings->files_extracted = true;
76    settings_save();
77 
78    if (Graphics::init(settings->resolution))
79    {
80       NX_ERR("Failed to initialize graphics.\n");
81       return 1;
82    }
83    if (font_init())
84    {
85       NX_ERR("Failed to load font.\n");
86       return 1;
87    }
88 
89    //return error;
90 
91    if (check_data_exists())
92       return 1;
93 
94    if (trig_init())
95    {
96       fatal("Failed trig module init.");
97       return 1;
98    }
99 
100    if (tsc_init())
101    {
102       fatal("Failed to initialize script engine.");
103       return 1;
104    }
105 
106    if (textbox.Init())
107    {
108       fatal("Failed to initialize textboxes.");
109       return 1;
110    }
111    if (Carets::init())
112    {
113       fatal("Failed to initialize carets.");
114       return 1;
115    }
116 
117    if (game.init())
118       return 1;
119 
120    game.setmode(GM_NORMAL);
121    // set null stage just to have something to do while we go to intro
122    game.switchstage.mapno = 0;
123 
124    //game.switchstage.mapno = LOAD_GAME;
125    //game.pause(GP_OPTIONS);
126 
127    if (settings->skip_intro && file_exists(GetProfileName(settings->last_save_slot)))
128       game.switchstage.mapno = LOAD_GAME;
129    else
130       game.setmode(GM_INTRO);
131 
132    // for debug
133    if (game.paused) { game.switchstage.mapno = 0; game.switchstage.eventonentry = 0; }
134    if (game.switchstage.mapno == LOAD_GAME) inhibit_loadfade = true;
135 
136    game.running = true;
137    freshstart = true;
138 
139    NX_LOG("Entering main loop...\n");
140 
141    return 0;
142 }
143 
post_main(void)144 void post_main(void)
145 {
146    if (game.close)
147       game.close();
148 	Carets::close();
149 
150 	Graphics::close();
151 	input_close();
152 	font_close();
153 	sound_close();
154 	tsc_close();
155 	textbox.Deinit();
156 }
157 
gameloop(void)158 static bool gameloop(void)
159 {
160 	//uint32_t gametimer;
161 
162 	//gametimer = -GAME_WAIT*10;
163 
164 	if(game.switchstage.mapno < 0)
165 	{
166 		run_tick();
167 		return true;
168 	}
169 	else
170 		return false;
171 }
172 
173 static bool in_gameloop = false;
174 
run_main(void)175 bool run_main(void)
176 {
177 	if (in_gameloop)
178 		goto loop;
179 	// SSS/SPS persists across stage transitions until explicitly
180 	// stopped, or you die & reload. It seems a bit risky to me,
181 	// but that's the spec.
182 	if (game.switchstage.mapno >= MAPNO_SPECIALS)
183 	{
184 		StopLoopSounds();
185 	}
186 
187 	// enter next stage, whatever it may be
188 	if (game.switchstage.mapno == LOAD_GAME || \
189 			game.switchstage.mapno == LOAD_GAME_FROM_MENU)
190 	{
191 		if (game.switchstage.mapno == LOAD_GAME_FROM_MENU)
192 			freshstart = true;
193 
194 		NX_LOG("= Loading game =\n");
195 		if (game_load(settings->last_save_slot))
196 		{
197 			fatal("savefile error");
198 			game.running = false;
199 			return 1;
200 		}
201 
202 		if (!inhibit_loadfade) fade.Start(FADE_IN, FADE_CENTER);
203 		else inhibit_loadfade = false;
204 	}
205 	else
206 	{
207 		if (game.switchstage.mapno == NEW_GAME || \
208 				game.switchstage.mapno == NEW_GAME_FROM_MENU)
209 		{
210 			static bool show_intro = (game.switchstage.mapno == NEW_GAME_FROM_MENU);
211 			InitNewGame(show_intro);
212 		}
213 
214 		// slide weapon bar on first intro to Start Point
215 		if (game.switchstage.mapno == STAGE_START_POINT && \
216 				game.switchstage.eventonentry == 91)
217 		{
218 			freshstart = true;
219 		}
220 
221 		// switch maps
222 		if (load_stage(game.switchstage.mapno))
223 		{
224 			game.running = false;
225 			return 1;
226 		}
227 
228 		player->x = (game.switchstage.playerx * TILE_W) << CSF;
229 		player->y = (game.switchstage.playery * TILE_H) << CSF;
230 	}
231 
232 	// start the level
233 	if (game.initlevel())
234 	{
235 		game.running = false;
236 		return 1;
237 	}
238 
239 	if (freshstart)
240 		weapon_introslide();
241 
242 	game.switchstage.mapno = -1;
243 loop:
244 	in_gameloop = true;
245 	if (gameloop())
246 		return true;
247 	in_gameloop = false;
248 
249 	game.stageboss.OnMapExit();
250 	freshstart = false;
251 	return false;
252 }
253 
run_tick()254 static inline void run_tick()
255 {
256 	input_poll();
257 
258 	// input handling for a few global things
259 	if (justpushed(ESCKEY))
260 	{
261 		if (settings->instant_quit)
262 		{
263 			game.running = false;
264 		}
265 		else if (!game.paused)		// no pause from Options
266 		{
267 			game.pause(GP_PAUSED);
268 		}
269 	}
270 	else if (justpushed(F3KEY))
271 	{
272 		game.pause(GP_OPTIONS);
273 	}
274 
275 	// freeze frame
276 	game.tick();
277 
278 	org_run();
279 
280 	memcpy(lastinputs, inputs, sizeof(lastinputs));
281 }
282 
InitNewGame(bool with_intro)283 void InitNewGame(bool with_intro)
284 {
285 	NX_LOG("= Beginning new game =\n");
286 
287 	memset(game.flags, 0, sizeof(game.flags));
288 	memset(game.skipflags, 0, sizeof(game.skipflags));
289 	textbox.StageSelect.ClearSlots();
290 
291 	game.quaketime = game.megaquaketime = 0;
292 	game.showmapnametime = 0;
293 	game.debug.god = 0;
294 	game.running = true;
295 	game.frozen = false;
296 
297 	// fully re-init the player object
298 	Objects::DestroyAll(true);
299 	game.createplayer();
300 
301 	player->maxHealth = 3;
302 	player->hp = player->maxHealth;
303 
304 	game.switchstage.mapno = STAGE_START_POINT;
305 	game.switchstage.playerx = 10;
306 	game.switchstage.playery = 8;
307 	game.switchstage.eventonentry = (with_intro) ? 200 : 91;
308 
309 	fade.set_full(FADE_OUT);
310 }
311 
312 /*
313 void c------------------------------() {}
314 */
315 
fatal(const char * str)316 static void fatal(const char *str)
317 {
318 	NX_ERR("Fatal error: '%s'\n", str);
319 }
320 
check_data_exists()321 static bool check_data_exists()
322 {
323    char fname[1024];
324 	retro_create_subpath_string(fname, sizeof(fname), g_dir, data_dir, "npc.tbl");
325 	NX_LOG("check_data_exists: %s\n", fname);
326 
327 	if (file_exists(fname))
328       return 0;
329 
330    NX_ERR("Fatal Error\n");
331 
332    NX_ERR("Missing \"%s\" directory.\n", data_dir);
333    NX_ERR("Please copy it over from a Doukutsu installation.\n");
334 
335 	return 1;
336 }
337 
visible_warning(const char * fmt,...)338 void visible_warning(const char *fmt, ...)
339 {
340 #if defined(_MSC_VER) && _MSC_VER <= 1310
341 #else
342    va_list ar;
343    char buffer[80];
344 
345 	va_start(ar, fmt);
346 	vsnprintf(buffer, sizeof(buffer), fmt, ar);
347 	va_end(ar);
348 #endif
349 }
350