NXEngine v1.0.0.6
[NXEngine.git] / intro / title.cpp
blobf6db2167911910b7cf87499bfcf11edeb85ec8db
2 #include "../nx.h"
3 #include "title.fdh"
5 // music and character selections for the different Counter times
6 static struct
8 uint32_t timetobeat;
9 int sprite;
10 int songtrack;
11 } titlescreens[] =
13 (3*3000), SPR_CS_SUE, 2, // 3 mins - Sue & Safety
14 (4*3000), SPR_CS_KING, 41, // 4 mins - King & White
15 (5*3000), SPR_CS_TOROKO, 40, // 5 mins - Toroko & Toroko's Theme
16 (6*3000), SPR_CS_CURLY, 36, // 6 mins - Curly & Running Hell
17 0xFFFFFFFF, SPR_CS_MYCHAR, 24 // default
20 // artifical fake "loading" delay between selecting an option and it being executed,
21 // because it actually doesn't look good if we respond instantly.
22 #define SELECT_DELAY 30
23 #define SELECT_LOAD_DELAY 20 // delay when leaving the multisave Load dialog
24 #define SELECT_MENU_DELAY 8 // delay from Load to load menu
26 static struct
28 int sprite;
29 int cursel;
30 int selframe, seltimer;
31 int selchoice, seldelay;
32 int kc_pos;
33 bool in_multiload;
35 uint32_t besttime; // Nikumaru display
36 } title;
39 bool title_init(int param)
41 memset(&title, 0, sizeof(title));
42 game.switchstage.mapno = 0;
43 game.switchstage.eventonentry = 0;
44 game.showmapnametime = 0;
45 textbox.SetVisible(false);
47 if (niku_load(&title.besttime))
48 title.besttime = 0xffffffff;
50 // select a title screen based on Nikumaru time
51 int t;
52 for(t=0;;t++)
54 if (title.besttime < titlescreens[t].timetobeat || \
55 titlescreens[t].timetobeat == 0xffffffff)
57 break;
61 title.sprite = titlescreens[t].sprite;
62 music(titlescreens[t].songtrack);
64 if (AnyProfileExists())
65 title.cursel = 1; // Load Game
66 else
67 title.cursel = 0; // New Game
69 return 0;
72 void title_tick()
74 if (!title.in_multiload)
76 if (title.seldelay > 0)
78 ClearScreen(BLACK);
80 title.seldelay--;
81 if (!title.seldelay)
82 selectoption(title.selchoice);
84 return;
87 handle_input();
88 draw_title();
90 else
92 ClearScreen(BLACK);
94 if (!textbox.SaveSelect.IsVisible())
95 { // selection was made, and settings.last_save_slot is now set appropriately
97 sound(SND_MENU_SELECT);
99 textbox.SetVisible(false);
100 title.selchoice = 1;
101 title.seldelay = SELECT_LOAD_DELAY;
102 title.in_multiload = false;
104 else
106 textbox.Draw();
113 void c------------------------------() {}
116 static void selectoption(int index)
118 switch(index)
120 case 0: // New
122 music(0);
124 game.switchstage.mapno = NEW_GAME_FROM_MENU;
125 game.setmode(GM_NORMAL);
127 break;
129 case 1: // Load
131 music(0);
133 game.switchstage.mapno = LOAD_GAME_FROM_MENU;
134 game.setmode(GM_NORMAL);
136 break;
138 case 2: // Load Menu (multisave)
140 textbox.SetVisible(true);
141 textbox.SaveSelect.SetVisible(true, SS_LOADING);
142 title.in_multiload = true;
144 break;
149 static void handle_input()
151 if (justpushed(DOWNKEY))
153 sound(SND_MENU_MOVE);
154 if (++title.cursel >= sprites[SPR_MENU].nframes)
155 title.cursel = 0;
157 else if (justpushed(UPKEY))
159 sound(SND_MENU_MOVE);
160 if (--title.cursel < 0)
161 title.cursel = sprites[SPR_MENU].nframes - 1;
164 if (buttonjustpushed())
166 sound(SND_MENU_SELECT);
167 int choice = title.cursel;
169 // handle case where user selects Load but there is no savefile,
170 // or the last_save_file is deleted.
171 if (title.cursel == 1)
173 if (!ProfileExists(settings->last_save_slot))
175 bool foundslot = false;
176 for(int i=0;i<MAX_SAVE_SLOTS;i++)
178 if (ProfileExists(i))
180 stat("Last save file %d missing. Defaulting to %d instead.", settings->last_save_slot, i);
181 settings->last_save_slot = i;
182 foundslot = true;
186 // there are no save files. Start a new game instead.
187 if (!foundslot)
189 stat("No save files found. Starting new game instead.");
190 choice = 0;
195 if (choice == 1 && settings->multisave)
197 title.selchoice = 2;
198 title.seldelay = SELECT_MENU_DELAY;
200 else
202 title.selchoice = choice;
203 title.seldelay = SELECT_DELAY;
204 music(0);
208 run_konami_code();
211 static void draw_title()
213 // background is dk grey, not pure black
214 ClearScreen(0x20, 0x20, 0x20);
216 // top logo
217 int tx = (SCREEN_WIDTH / 2) - (sprites[SPR_TITLE].w / 2) - 2;
218 draw_sprite(tx, 40, SPR_TITLE);
220 // draw menu
221 int cx = (SCREEN_WIDTH / 2) - (sprites[SPR_MENU].w / 2) - 8;
222 int cy = (SCREEN_HEIGHT / 2) + 8;
223 for(int i=0;i<sprites[SPR_MENU].nframes;i++)
225 draw_sprite(cx, cy, SPR_MENU, i);
226 if (i == title.cursel)
228 draw_sprite(cx - 16, cy - 1, title.sprite, title.selframe);
231 cy += (sprites[SPR_MENU].h + 4);
234 // animate character
235 if (++title.seltimer > 8)
237 title.seltimer = 0;
238 if (++title.selframe >= sprites[title.sprite].nframes)
239 title.selframe = 0;
242 // accreditation
243 cx = (SCREEN_WIDTH / 2) - (sprites[SPR_PIXEL_FOREVER].w / 2);
244 int acc_y = SCREEN_HEIGHT - 48;
245 draw_sprite(cx, acc_y, SPR_PIXEL_FOREVER);
247 // version
248 static const char *VERSION = "NXEngine v. 1.0.0.6";
249 static const int SPACING = 5;
250 int wd = GetFontWidth(VERSION, SPACING);
251 cx = (SCREEN_WIDTH / 2) - (wd / 2);
252 font_draw(cx, acc_y + sprites[SPR_PIXEL_FOREVER].h + 4, VERSION, SPACING);
254 // draw Nikumaru display
255 if (title.besttime != 0xffffffff)
256 niku_draw(title.besttime, true);
261 static int kc_table[] = { UPKEY, UPKEY, DOWNKEY, DOWNKEY,
262 LEFTKEY, RIGHTKEY, LEFTKEY, RIGHTKEY, -1 };
264 void run_konami_code()
266 if (justpushed(UPKEY) || justpushed(DOWNKEY) || \
267 justpushed(LEFTKEY) || justpushed(RIGHTKEY))
269 if (justpushed(kc_table[title.kc_pos]))
271 title.kc_pos++;
272 if (kc_table[title.kc_pos] == -1)
274 sound(SND_MENU_SELECT);
275 title.kc_pos = 0;
278 else
280 title.kc_pos = 0;