1 
2 #include "../nx.h"
3 #include "../game.fdh"
4 #include "title.fdh"
5 
6 // music and character selections for the different Counter times
7 static struct
8 {
9 	uint32_t timetobeat;
10 	int sprite;
11 	int songtrack;
12 } titlescreens[] =
13 {
14 	(3*3000),	SPR_CS_SUE,    2,		// 3 mins	- Sue & Safety
15 	(4*3000),	SPR_CS_KING,   41,		// 4 mins	- King & White
16 	(5*3000),	SPR_CS_TOROKO, 40,		// 5 mins	- Toroko & Toroko's Theme
17 	(6*3000),	SPR_CS_CURLY,  36,		// 6 mins	- Curly & Running Hell
18 	0xFFFFFFFF, SPR_CS_MYCHAR, 24		// default
19 };
20 
21 // artifical fake "loading" delay between selecting an option and it being executed,
22 // because it actually doesn't look good if we respond instantly.
23 #define SELECT_DELAY			30
24 #define SELECT_LOAD_DELAY		20		// delay when leaving the multisave Load dialog
25 #define SELECT_MENU_DELAY		8		// delay from Load to load menu
26 
27 static struct
28 {
29 	int sprite;
30 	int cursel;
31 	int selframe, seltimer;
32 	int selchoice, seldelay;
33 	int kc_pos;
34 	bool in_multiload;
35 
36 	uint32_t besttime;		// Nikumaru display
37 } title;
38 
39 
title_init(int param)40 bool title_init(int param)
41 {
42 	memset(&title, 0, sizeof(title));
43 	game.switchstage.mapno = 0;
44 	game.switchstage.eventonentry = 0;
45 	game.showmapnametime = 0;
46 	textbox.SetVisible(false);
47 
48 	if (niku_load(&title.besttime))
49 		title.besttime = 0xffffffff;
50 
51 	// select a title screen based on Nikumaru time
52 	int t;
53 	for(t=0;;t++)
54 	{
55 		if (title.besttime < titlescreens[t].timetobeat || \
56 			titlescreens[t].timetobeat == 0xffffffff)
57 		{
58 			break;
59 		}
60 	}
61 
62 	title.sprite = titlescreens[t].sprite;
63 	music(titlescreens[t].songtrack);
64 
65 	if (AnyProfileExists())
66 		title.cursel = 1;	// Load Game
67 	else
68 		title.cursel = 0;	// New Game
69 
70 	return 0;
71 }
72 
title_tick()73 void title_tick()
74 {
75 	if (!title.in_multiload)
76 	{
77 		if (title.seldelay > 0)
78 		{
79 			ClearScreen(BLACK);
80 
81 			title.seldelay--;
82 			if (!title.seldelay)
83 				selectoption(title.selchoice);
84 
85 			return;
86 		}
87 
88 		handle_input();
89 		draw_title();
90 	}
91 	else
92 	{
93 		ClearScreen(BLACK);
94 
95 		if (!textbox.SaveSelect.IsVisible())
96 		{	// selection was made, and settings.last_save_slot is now set appropriately
97 
98 			sound(SND_MENU_SELECT);
99 
100 			textbox.SetVisible(false);
101 			title.selchoice = 1;
102 			title.seldelay = SELECT_LOAD_DELAY;
103 			title.in_multiload = false;
104 		}
105 		else
106 		{
107 			textbox.Draw();
108 		}
109 	}
110 }
111 
112 
113 /*
114 void c------------------------------() {}
115 */
116 
selectoption(int index)117 static void selectoption(int index)
118 {
119 	switch(index)
120 	{
121 		case 0:		// New
122 		{
123 			music(0);
124 
125 			game.switchstage.mapno = NEW_GAME_FROM_MENU;
126 			game.setmode(GM_NORMAL);
127 		}
128 		break;
129 
130 		case 1:		// Load
131 		{
132 			music(0);
133 
134 			game.switchstage.mapno = LOAD_GAME_FROM_MENU;
135 			game.setmode(GM_NORMAL);
136 		}
137 		break;
138 
139 		case 2:		// Load Menu (multisave)
140 		{
141 			textbox.SetVisible(true);
142 			textbox.SaveSelect.SetVisible(true, SS_LOADING);
143 			title.in_multiload = true;
144 		}
145 		break;
146 	}
147 }
148 
149 
handle_input()150 static void handle_input()
151 {
152 	if (justpushed(DOWNKEY))
153 	{
154 		sound(SND_MENU_MOVE);
155 		if (++title.cursel >= sprites[SPR_MENU].nframes)
156 			title.cursel = 0;
157 	}
158 	else if (justpushed(UPKEY))
159 	{
160 		sound(SND_MENU_MOVE);
161 		if (--title.cursel < 0)
162 			title.cursel = sprites[SPR_MENU].nframes - 1;
163 	}
164 
165 	if (buttonjustpushed())
166 	{
167 		sound(SND_MENU_SELECT);
168 		int choice = title.cursel;
169 
170 		// handle case where user selects Load but there is no savefile,
171 		// or the last_save_file is deleted.
172 		if (title.cursel == 1)
173 		{
174 			if (!ProfileExists(settings->last_save_slot))
175 			{
176 				bool foundslot = false;
177 				for(int i=0;i<MAX_SAVE_SLOTS;i++)
178 				{
179 					if (ProfileExists(i))
180 					{
181 						NX_WARN("Last save file %d missing. Defaulting to %d instead.\n", settings->last_save_slot, i);
182 						settings->last_save_slot = i;
183 						foundslot = true;
184 					}
185 				}
186 
187 				// there are no save files. Start a new game instead.
188 				if (!foundslot)
189 				{
190 					NX_WARN("No save files found. Starting new game instead.\n");
191 					choice = 0;
192 				}
193 			}
194 		}
195 
196 		if (choice == 1 && settings->multisave)
197 		{
198 			title.selchoice = 2;
199 			title.seldelay = SELECT_MENU_DELAY;
200 		}
201 		else
202 		{
203 			title.selchoice = choice;
204 			title.seldelay = SELECT_DELAY;
205 			music(0);
206 		}
207 	}
208 
209 	run_konami_code();
210 }
211 
draw_title()212 static void draw_title()
213 {
214 	// background is dk grey, not pure black
215 	ClearScreen(0x20, 0x20, 0x20);
216    map_draw_backdrop();
217 
218 	// top logo
219 	int tx = (SCREEN_WIDTH / 2) - (sprites[SPR_TITLE].w / 2) - 2;
220 	draw_sprite(tx, 40, SPR_TITLE);
221 
222 	// draw menu
223 	int cx = (SCREEN_WIDTH / 2) - (sprites[SPR_MENU].w / 2) - 8;
224 	int cy = (SCREEN_HEIGHT / 2) + 8;
225 	for(int i=0;i<sprites[SPR_MENU].nframes;i++)
226 	{
227 		draw_sprite(cx, cy, SPR_MENU, i);
228 		if (i == title.cursel)
229 		{
230 			draw_sprite(cx - 16, cy - 1, title.sprite, title.selframe);
231 		}
232 
233 		cy += (sprites[SPR_MENU].h + 4);
234 	}
235 
236 	// animate character
237 	if (++title.seltimer > 8)
238 	{
239 		title.seltimer = 0;
240 		if (++title.selframe >= sprites[title.sprite].nframes)
241 			title.selframe = 0;
242 	}
243 
244 	// accreditation
245 	cx = (SCREEN_WIDTH / 2) - (sprites[SPR_PIXEL_FOREVER].w / 2);
246 	int acc_y = SCREEN_HEIGHT - 48;
247 	draw_sprite(cx, acc_y, SPR_PIXEL_FOREVER);
248 
249 	// version
250 	static const char *VERSION = "NXEngine v. 1.0.0.6";
251 	static const int SPACING = 5;
252 	int wd = GetFontWidth(VERSION, SPACING);
253 	cx = (SCREEN_WIDTH / 2) - (wd / 2);
254 	font_draw(cx, acc_y + sprites[SPR_PIXEL_FOREVER].h + 4, VERSION, SPACING);
255    font_draw(cx, acc_y + sprites[SPR_PIXEL_FOREVER].h + 16, "Libretro v. 1.0", SPACING);
256 
257 	// draw Nikumaru display
258 	if (title.besttime != 0xffffffff)
259 		niku_draw(title.besttime, true);
260 }
261 
262 
263 
264 static int kc_table[] = { UPKEY, UPKEY, DOWNKEY, DOWNKEY,
265 						  LEFTKEY, RIGHTKEY, LEFTKEY, RIGHTKEY, -1 };
266 
run_konami_code()267 void run_konami_code()
268 {
269 	if (justpushed(UPKEY) || justpushed(DOWNKEY) || \
270 		justpushed(LEFTKEY) || justpushed(RIGHTKEY))
271 	{
272 		if (justpushed(kc_table[title.kc_pos]))
273 		{
274 			title.kc_pos++;
275 			if (kc_table[title.kc_pos] == -1)
276 			{
277 				sound(SND_MENU_SELECT);
278 				title.kc_pos = 0;
279 			}
280 		}
281 		else
282 		{
283 			title.kc_pos = 0;
284 		}
285 	}
286 }
287 
288 
289 
290 
291 
292 
293 
294 
295 
296 
297 
298 
299