1 /*
2  * OpenBOR - http://www.chronocrash.com
3  * -----------------------------------------------------------------------
4  * All rights reserved, see LICENSE in OpenBOR root for details.
5  *
6  * Copyright (c) 2004 - 2014 OpenBOR Team
7  */
8 #include <unistd.h>
9 #include "SDL.h"
10 #include "sdlport.h"
11 #include "video.h"
12 #include "openbor.h"
13 #include "soundmix.h"
14 #include "packfile.h"
15 #include "gfx.h"
16 #include "hankaku.h"
17 #include "stristr.h"
18 #include "stringptr.h"
19 
20 #include "pngdec.h"
21 #include "../resources/OpenBOR_Logo_480x272_png.h"
22 #include "../resources/OpenBOR_Logo_320x240_png.h"
23 #include "../resources/OpenBOR_Menu_480x272_png.h"
24 #include "../resources/OpenBOR_Menu_320x240_png.h"
25 // CRxTRDude - Added the log screen pngs
26 #include "../resources/logviewer_480x272_png.h"
27 #include "../resources/logviewer_320x240_png.h"
28 
29 #include <dirent.h>
30 
31 extern s_videomodes videomodes;
32 extern s_screen* vscreen;
33 extern int nativeHeight;
34 extern int nativeWidth;
35 s_screen* bgscreen;
36 // CRxTRDude - Added the log screen variable.
37 s_screen* logscreen;
38 
39 #define RGB32(R,G,B) ((R) | ((G) << 8) | ((B) << 16))
40 #define RGB16(R,G,B) ((B&0xF8)<<8) | ((G&0xFC)<<3) | (R>>3)
41 #define RGB(R,G,B)   (bpp==16?RGB16(R,G,B):RGB32(R,G,B))
42 
43 #define BLACK		RGB(  0,   0,   0)
44 #define WHITE		RGB(255, 255, 255)
45 #define RED			RGB(255,   0,   0)
46 #define	GREEN		RGB(  0, 255,   0)
47 #define BLUE		RGB(  0,   0, 255)
48 #define YELLOW		RGB(255, 255,   0)
49 #define PURPLE		RGB(255,   0, 255)
50 #define ORANGE		RGB(255, 128,   0)
51 #define GRAY		RGB(112, 128, 144)
52 #define LIGHT_GRAY  RGB(223, 223, 223)
53 #define DARK_RED	RGB(128,   0,   0)
54 #define DARK_GREEN	RGB(  0, 128,   0)
55 #define DARK_BLUE	RGB(  0,   0, 128)
56 
57 #define LOG_SCREEN_TOP 2
58 #define LOG_SCREEN_END (isWide ? 26 : 23)
59 
60 int bpp = 32;
61 int isWide = 0;
62 int isFull = 0;
63 int flags;
64 int dListTotal;
65 int dListCurrentPosition;
66 int dListScrollPosition;
67 int which_logfile = OPENBOR_LOG;
68 FILE *bgmFile = NULL;
69 unsigned int bgmPlay = 0, bgmLoop = 0, bgmCycle = 0, bgmCurrent = 0, bgmStatus = 0;
70 extern u32 bothkeys, bothnewkeys;
71 fileliststruct *filelist;
72 extern const s_drawmethod plainmethod;
73 
74 typedef struct{
75 	stringptr *buf;
76 	int *pos;
77 	int line;
78 	int rows;
79 	char ready;
80 }s_logfile;
81 s_logfile logfile[2];
82 
83 typedef int (*ControlInput)();
84 
85 int ControlMenu();
86 int ControlBGM();
87 void PlayBGM();
88 void StopBGM();
89 static ControlInput pControl;
90 
Control()91 int Control()
92 {
93 	return pControl();
94 }
95 
getAllLogs()96 void getAllLogs()
97 {
98 	ptrdiff_t i, j, k;
99 	for(i=0; i<2; i++)
100 	{
101 		logfile[i].buf = readFromLogFile(i);
102 		if(logfile[i].buf != NULL)
103 		{
104 			logfile[i].pos = malloc(++logfile[i].rows * sizeof(int));
105 			if(logfile[i].pos == NULL) return;
106 			memset(logfile[i].pos, 0, logfile[i].rows * sizeof(int));
107 
108 			for(k=0, j=0; j<logfile[i].buf->size; j++)
109 			{
110 				if(!k)
111 				{
112 					logfile[i].pos[logfile[i].rows - 1] = j;
113 					k = 1;
114 				}
115 				if(logfile[i].buf->ptr[j]=='\n')
116 				{
117 					int *_pos = malloc(++logfile[i].rows * sizeof(int));
118 					if(_pos == NULL) return;
119 					memcpy(_pos, logfile[i].pos, (logfile[i].rows - 1) * sizeof(int));
120 					_pos[logfile[i].rows - 1] = 0;
121 					free(logfile[i].pos);
122 					logfile[i].pos = NULL;
123 					logfile[i].pos = malloc(logfile[i].rows * sizeof(int));
124 					if(logfile[i].pos == NULL) return;
125 					memcpy(logfile[i].pos, _pos, logfile[i].rows * sizeof(int));
126 					free(_pos);
127 					_pos = NULL;
128 					logfile[i].buf->ptr[j] = 0;
129 					k = 0;
130 				}
131 				if(logfile[i].buf->ptr[j]=='\r') logfile[i].buf->ptr[j] = 0;
132 				if(logfile[i].rows>0xFFFFFFFE) break;
133 			}
134 			logfile[i].ready = 1;
135 		}
136 	}
137 }
138 
freeAllLogs()139 void freeAllLogs()
140 {
141 	int i;
142 	for(i=0; i<2; i++)
143 	{
144 		if(logfile[i].ready)
145 		{
146 			free_string(logfile[i].buf);
147 			logfile[i].buf = NULL;
148 			free(logfile[i].pos);
149 			logfile[i].pos = NULL;
150 		}
151 	}
152 }
153 
sortList()154 void sortList()
155 {
156 	int i, j;
157 	fileliststruct temp;
158 	if(dListTotal<2) return;
159 	for(j=dListTotal-1; j>0; j--)
160 	{
161 		for(i=0; i<j; i++)
162 		{
163 			if(stricmp(filelist[i].filename, filelist[i+1].filename)>0)
164 			{
165 				temp = filelist[i];
166 				filelist[i] = filelist[i+1];
167 				filelist[i+1] = temp;
168 			}
169 		}
170 	}
171 }
172 
findPaks(void)173 int findPaks(void)
174 {
175 	int i = 0;
176 	DIR* dp = NULL;
177 	struct dirent* ds;
178 	dp = opendir(paksDir);
179 	if(dp != NULL)
180    	{
181 		while((ds = readdir(dp)) != NULL)
182 		{
183 			if(packfile_supported(ds))
184 			{
185 				fileliststruct *copy = NULL;
186 				if(filelist == NULL) filelist = malloc(sizeof(fileliststruct));
187 				else
188 				{
189 					copy = malloc(i * sizeof(fileliststruct));
190 					memcpy(copy, filelist, i * sizeof(fileliststruct));
191 					free(filelist);
192 					filelist = malloc((i + 1) * sizeof(fileliststruct));
193 					memcpy(filelist, copy, i * sizeof(fileliststruct));
194 					free(copy); copy = NULL;
195 				}
196 				memset(&filelist[i], 0, sizeof(fileliststruct));
197 				strncpy(filelist[i].filename, ds->d_name, strlen(ds->d_name));
198 				i++;
199 			}
200 		}
201 		closedir(dp);
202    	}
203 	return i;
204 }
205 
drawScreens(s_screen * Image)206 void drawScreens(s_screen *Image)
207 {
208 	putscreen(vscreen, Image, 0, 0, NULL);
209 	video_copy_screen(vscreen);
210 }
211 
printText(int x,int y,int col,int backcol,int fill,char * format,...)212 void printText(int x, int y, int col, int backcol, int fill, char *format, ...)
213 {
214 	int x1, y1, i;
215 	u32 data;
216 	u16 *line16 = NULL;
217 	u32 *line32 = NULL;
218 	u8 *font;
219 	u8 ch = 0;
220 	char buf[128] = {""};
221 	int pitch = vscreen->width*bpp/8;
222 	va_list arglist;
223 		va_start(arglist, format);
224 		vsprintf(buf, format, arglist);
225 		va_end(arglist);
226 
227 	for(i=0; i<sizeof(buf); i++)
228 	{
229 		ch = buf[i];
230 		// mapping
231 		if (ch<0x20) ch = 0;
232 		else if (ch<0x80) { ch -= 0x20; }
233 		else if (ch<0xa0) {	ch = 0;	}
234 		else ch -= 0x40;
235 		font = (u8 *)&hankaku_font10[ch*10];
236 		// draw
237 		if (bpp == 16) line16 = (u16*)(vscreen->data + x*2 + y * pitch);
238 		else           line32 = (u32*)(vscreen->data + x*4 + y * pitch);
239 
240 		for (y1=0; y1<10; y1++)
241 		{
242 			data = *font++;
243 			for (x1=0; x1<5; x1++)
244 			{
245 				if (data & 1)
246 				{
247 					if (bpp == 16) *line16 = col;
248 				    else           *line32 = col;
249 				}
250 				else if (fill)
251 				{
252 					if (bpp == 16) *line16 = backcol;
253 					else           *line32 = backcol;
254 				}
255 
256 				if (bpp == 16) line16++;
257 				else           line32++;
258 
259 				data = data >> 1;
260 			}
261 			if (bpp == 16) line16 += pitch/2-5;
262 			else           line32 += pitch/4-5;
263 		}
264 		x+=5;
265 	}
266 }
267 
getPreview(char * filename)268 s_screen *getPreview(char *filename)
269 {
270 	s_screen *title = NULL;
271 	s_screen *scale = NULL;
272 	// Grab current path and filename
273 	getBasePath(packfile, filename, 1);
274 	// Create & Load & Scale Image
275 	if(!loadscreen("data/bgs/title", packfile, NULL, PIXEL_x8, &title)) return NULL;
276 	scale = allocscreen(160, 120, PIXEL_x8);
277 	scalescreen(scale, title);
278 	memcpy(scale->palette, title->palette, PAL_BYTES);
279 	// ScreenShots within Menu will be saved as "Menu"
280 	strncpy(packfile,"Menu.xxx",128);
281 	freescreen(&title);
282 	return scale;
283 }
284 
StopBGM()285 void StopBGM()
286 {
287 	sound_close_music();
288 	if (bgmFile)
289 	{
290 		fclose(bgmFile);
291 		bgmFile = NULL;
292 	}
293 	bgmPlay = 0;
294 }
295 
PlayBGM()296 void PlayBGM()
297 {
298 	bgmPlay = packfile_music_play(filelist, bgmFile, bgmLoop, dListCurrentPosition, dListScrollPosition);
299 }
300 
ControlMenu()301 int ControlMenu()
302 {
303 	int status = -1;
304 	int dListMaxDisplay = 17;
305 	bothnewkeys = 0;
306 	inputrefresh();
307 	switch(bothnewkeys)
308 	{
309 		case FLAG_MOVEUP:
310 			dListScrollPosition--;
311 			if(dListScrollPosition < 0)
312 			{
313 				dListScrollPosition = 0;
314 				dListCurrentPosition--;
315 			}
316 			if(dListCurrentPosition < 0) dListCurrentPosition = 0;
317 			break;
318 
319 		case FLAG_MOVEDOWN:
320 			dListCurrentPosition++;
321 			if(dListCurrentPosition > dListTotal - 1) dListCurrentPosition = dListTotal - 1;
322 			if(dListCurrentPosition > dListMaxDisplay)
323 	        {
324 		        if((dListCurrentPosition+dListScrollPosition) < dListTotal) dListScrollPosition++;
325 			    dListCurrentPosition = dListMaxDisplay;
326 			}
327 			break;
328 
329 		case FLAG_MOVELEFT:
330 			break;
331 
332 		case FLAG_MOVERIGHT:
333 			break;
334 
335 		case FLAG_START:
336 		case FLAG_ATTACK:
337 			// Start Engine!
338 			status = 1;
339 			break;
340 
341 		case FLAG_ATTACK2:
342 			pControl = ControlBGM;
343 			status = -2;
344 			break;
345 
346 		case FLAG_SPECIAL:
347 		case FLAG_ESC:
348 			// Exit Engine!
349 			status = 2;
350 			break;
351 
352 		case FLAG_JUMP:
353 			//drawLogs();
354 			status = 3;
355 			break;
356 
357 		default:
358 			// No Update Needed!
359 			status = 0;
360 			break;
361 	}
362 	return status;
363 }
364 
ControlBGM()365 int ControlBGM()
366 {
367 	int status = -2;
368 	int dListMaxDisplay = 17;
369 	bothnewkeys = 0;
370 	inputrefresh();
371 	switch(bothnewkeys)
372 	{
373 		case FLAG_MOVEUP:
374 			dListScrollPosition--;
375 			if(dListScrollPosition < 0)
376 			{
377 				dListScrollPosition = 0;
378 				dListCurrentPosition--;
379 			}
380 			if(dListCurrentPosition < 0) dListCurrentPosition = 0;
381 			break;
382 
383 		case FLAG_MOVEDOWN:
384 			dListCurrentPosition++;
385 			if(dListCurrentPosition > dListTotal - 1) dListCurrentPosition = dListTotal - 1;
386 			if(dListCurrentPosition > dListMaxDisplay)
387 	        {
388 		        if((dListCurrentPosition+dListScrollPosition) < dListTotal) dListScrollPosition++;
389 			    dListCurrentPosition = dListMaxDisplay;
390 			}
391 			break;
392 
393 		case FLAG_MOVELEFT:
394 			if(!bgmStatus || (bgmPlay && bgmCurrent == dListCurrentPosition+dListScrollPosition))
395 			{
396 				filelist[bgmCurrent].bgmTrack--;
397 				if(filelist[bgmCurrent].bgmTrack < 0) filelist[bgmCurrent].bgmTrack = filelist[bgmCurrent].nTracks-1;
398 				if(bgmStatus) PlayBGM();
399 			}
400 			break;
401 
402 		case FLAG_MOVERIGHT:
403 			if(!bgmStatus || (bgmPlay && bgmCurrent == dListCurrentPosition+dListScrollPosition))
404 			{
405 				filelist[bgmCurrent].bgmTrack++;
406 				if(filelist[bgmCurrent].bgmTrack > filelist[bgmCurrent].nTracks - 1) filelist[bgmCurrent].bgmTrack = 0;
407 				if(bgmStatus) PlayBGM();
408 			}
409 			break;
410 
411 		case FLAG_START:
412 		case FLAG_ATTACK:
413 			if(bgmPlay) StopBGM();
414 			else PlayBGM();
415 			break;
416 
417 		case FLAG_ATTACK2:
418 			if(!bgmPlay)
419 			{
420 				if(bgmLoop) bgmLoop = 0;
421 				else bgmLoop = 1;
422 			}
423 			break;
424 
425 		case FLAG_JUMP:
426 			if(!bgmPlay)
427 			{
428 				if(bgmCycle) bgmCycle = 0;
429 				else bgmCycle = 1;
430 			}
431 			break;
432 
433 		case FLAG_SPECIAL:
434 		case FLAG_ESC:
435 			pControl = ControlMenu;
436 			status = -1;
437 			break;
438 
439 		default:
440 			// No Update Needed!
441 			status = 0;
442 			break;
443 	}
444 	return status;
445 }
446 
initMenu(int type)447 void initMenu(int type)
448 {
449 
450 #ifdef ANDROID
451 	isWide = (float)nativeHeight/(float)nativeWidth < 3.0f/4.0f;
452 	isFull = 1;
453 	bpp = 32;
454 	savedata.glscale = 0.0f;
455 	screenformat = PIXEL_32;
456 #endif
457 
458 	screenformat = bpp==32?PIXEL_32:PIXEL_16;
459 	pixelformat = PIXEL_x8;
460 
461 	savedata.fullscreen = isFull;
462 	video_stretch(savedata.stretch);
463 	videomodes.hRes = isWide ? 480 :320;
464 	videomodes.vRes = isWide ? 272 :240;
465 	videomodes.pixel = pixelbytes[PIXEL_32];
466 	vscreen = allocscreen(videomodes.hRes, videomodes.vRes, screenformat);
467 
468 	video_set_mode(videomodes);
469 
470 	// Read Logo or Menu from Array.
471 	if(!type)
472 		bgscreen = pngToScreen(isWide ? (void*) openbor_logo_480x272_png.data : (void*) openbor_logo_320x240_png.data);
473 	else
474 		bgscreen = pngToScreen(isWide ? (void*) openbor_menu_480x272_png.data : (void*) openbor_menu_320x240_png.data);
475 	// CRxTRDude - Initialize log screen images
476 	logscreen = pngToScreen(isWide ? (void*) logviewer_480x272_png.data : (void*) logviewer_320x240_png.data);
477 
478 	control_init(2);
479 	apply_controls();
480 	sound_init(12);
481 	sound_start_playback(savedata.soundbits,savedata.soundrate);
482 }
483 
termMenu()484 void termMenu()
485 {
486 	videomodes.hRes = videomodes.vRes = 0;
487 	video_set_mode(videomodes);
488 	if(bgscreen) freescreen(&bgscreen);
489 	// CRxTRDude - Log screen must also be removed as well.
490 	if(logscreen) freescreen(&logscreen);
491 	if(vscreen) freescreen(&vscreen);
492 	sound_exit();
493 	control_exit();
494 }
495 
drawMenu()496 void drawMenu()
497 {
498 	char listing[45] = {""};
499 	int list = 0;
500 	int shift = 0;
501 	int colors = 0;
502 	s_screen* Image = NULL;
503 
504 	putscreen(vscreen,bgscreen,0,0,NULL);
505 	if(dListTotal < 1) printText((isWide ? 30 : 8), (isWide ? 33 : 24), RED, 0, 0, "No Mods In Paks Folder!");
506 	for(list=0; list<dListTotal; list++)
507 	{
508 		if(list<18)
509 		{
510 			shift = 0;
511 			colors = GRAY;
512 			strncpy(listing, "", (isWide ? 44 : 28));
513 			if(strlen(filelist[list+dListScrollPosition].filename)-4 < (isWide ? 44 : 28))
514 				strncpy(listing, filelist[list+dListScrollPosition].filename, strlen(filelist[list+dListScrollPosition].filename)-4);
515 			if(strlen(filelist[list+dListScrollPosition].filename)-4 > (isWide ? 44 : 28))
516 				strncpy(listing, filelist[list+dListScrollPosition].filename, (isWide ? 44 : 28));
517 			if(list == dListCurrentPosition)
518 			{
519 				shift = 2;
520 				colors = RED;
521 				Image = getPreview(filelist[list+dListScrollPosition].filename);
522 
523 			}
524 			printText((isWide ? 30 : 7) + shift, (isWide ? 33 : 22)+(11*list) , colors, 0, 0, "%s", listing);
525 		}
526 	}
527 
528 	printText((isWide ? 26 : 5), (isWide ? 11 : 4), WHITE, 0, 0, "OpenBoR %s", VERSION);
529 	printText((isWide ? 392 : 261),(isWide ? 11 : 4), WHITE, 0, 0, __DATE__);
530 		//CRxTRDude - Fix for Android's text - Main menu
531 #ifdef ANDROID
532 	printText((isWide ? 23 : 4),(isWide ? 251 : 226), WHITE, 0, 0, "A1: Start Game");
533 	printText((isWide ? 150 : 84),(isWide ? 251 : 226), WHITE, 0, 0, "A2: BGM Player");
534 	printText((isWide ? 270 : 164),(isWide ? 251 : 226), WHITE, 0, 0, "J: View Logs");
535 	printText((isWide ? 390 : 244),(isWide ? 251 : 226), WHITE, 0, 0, "S: Quit Game");
536 #else
537 	printText((isWide ? 23 : 4),(isWide ? 251 : 226), WHITE, 0, 0, "%s: Start Game", control_getkeyname(savedata.keys[0][SDID_ATTACK]));
538 	printText((isWide ? 150 : 84),(isWide ? 251 : 226), WHITE, 0, 0, "%s: BGM Player", control_getkeyname(savedata.keys[0][SDID_ATTACK2]));
539 	printText((isWide ? 270 : 164),(isWide ? 251 : 226), WHITE, 0, 0, "%s: View Logs", control_getkeyname(savedata.keys[0][SDID_JUMP]));
540 	printText((isWide ? 390 : 244),(isWide ? 251 : 226), WHITE, 0, 0, "%s: Quit Game", control_getkeyname(savedata.keys[0][SDID_SPECIAL]));
541 #endif
542 	//CRxTRDude - Fixed the placement of these texts and appropriately changed the site for Chrono Crash
543   printText((isWide ? 320 : 188),(isWide ? 175 : 158), BLACK, 0, 0, "www.chronocrash.com");
544 	printText((isWide ? 322 : 190),(isWide ? 185 : 168), BLACK, 0, 0, "www.SenileTeam.com");
545 
546 #ifdef SPK_SUPPORTED
547 	printText((isWide ? 324 : 192),(isWide ? 191 : 176), DARK_RED, 0, 0, "SecurePAK Edition");
548 #endif
549 
550 	if(Image)
551 	{
552 		putscreen(vscreen, Image, isWide ? 286 : 155, isWide ? 32:21, NULL);
553 		freescreen(&Image);
554 	}
555 	else
556 		printText((isWide ? 288 : 157), (isWide ? 141 : 130), RED, 0, 0, "No Preview Available!");
557 
558 	video_copy_screen(vscreen);
559 }
560 
drawBGMPlayer()561 void drawBGMPlayer()
562 {
563 	char listing[45] = {""}, bgmListing[25] = {""};
564 	char t1[64] = "", t2[25] = "Unknown";
565 	char a1[64] = "", a2[25] = "Unknown";
566 	int list = 0, colors = 0, shift = 0;
567 
568 	// Allocate Preview Box for Music Text Info.
569 	putscreen(vscreen,bgscreen,0,0,NULL);
570 	putbox((isWide ? 286 : 155),(isWide ? 32 : 21),160,120,LIGHT_GRAY,vscreen,NULL);
571 
572 	for(list=0; list<dListTotal; list++)
573 	{
574 		if(list<18)
575 		{
576 			shift = 0;
577 			colors = GRAY;
578 			strncpy(listing, "", (isWide ? 44 : 28));
579 			if(strlen(filelist[list+dListScrollPosition].filename)-4 < (isWide ? 44 : 28))
580 				strncpy(listing, filelist[list+dListScrollPosition].filename, strlen(filelist[list+dListScrollPosition].filename)-4);
581 			if(strlen(filelist[list+dListScrollPosition].filename)-4 > (isWide ? 44 : 28))
582 				strncpy(listing, filelist[list+dListScrollPosition].filename, (isWide ? 44 : 28));
583 			if(list==dListCurrentPosition) { shift = 2; colors = RED; }
584 			printText((isWide ? 30 : 7) + shift, (isWide ? 33 : 22)+(11*list) , colors, 0, 0, "%s", listing);
585 		}
586 	}
587 
588 	printText((isWide ? 26 : 5), (isWide ? 11 : 4), WHITE, 0, 0, "OpenBoR %s", VERSION);
589 	printText((isWide ? 392 : 261),(isWide ? 11 : 4), WHITE, 0, 0, __DATE__);
590 //CRxTRDude - Fix for Android's text - BGM MODE
591 #ifdef ANDROID
592 	printText((isWide ? 23 : 4),(isWide ? 251 : 226), WHITE, 0, 0, "A1: %s", bgmPlay ? "Stop" : "Play");
593 	printText((isWide ? 150 : 84),(isWide ? 251 : 226), WHITE, 0, 0, "A2: %s", bgmLoop ? "Repeat On" : "Repeat Off");
594 	printText((isWide ? 270 : 164),(isWide ? 251 : 226), WHITE, 0, 0, "J: %s", bgmCycle ? "Cycle On" : "Cycle Off");
595 	printText((isWide ? 390 : 244),(isWide ? 251 : 226), WHITE, 0, 0, "S: Exit Player");
596 #else
597 	printText((isWide ? 23 : 4),(isWide ? 251 : 226), WHITE, 0, 0, "%s: %s", control_getkeyname(savedata.keys[0][SDID_ATTACK]), bgmPlay ? "Stop" : "Play");
598 	printText((isWide ? 150 : 84),(isWide ? 251 : 226), WHITE, 0, 0, "%s: %s", control_getkeyname(savedata.keys[0][SDID_ATTACK2]), bgmLoop ? "Repeat On" : "Repeat Off");
599 	printText((isWide ? 270 : 164),(isWide ? 251 : 226), WHITE, 0, 0, "%s: %s", control_getkeyname(savedata.keys[0][SDID_JUMP]), bgmCycle ? "Cycle On" : "Cycle Off");
600 	printText((isWide ? 390 : 244),(isWide ? 251 : 226), WHITE, 0, 0, "%s: Exit Player", control_getkeyname(savedata.keys[0][SDID_SPECIAL]));
601 #endif
602 	//CRxTRDude - Fixed the placement of these texts and appropriately changed the site for Chrono Crash
603   printText((isWide ? 320 : 188),(isWide ? 175 : 158), BLACK, 0, 0, "www.chronocrash.com");
604 	printText((isWide ? 322 : 190),(isWide ? 185 : 168), BLACK, 0, 0, "www.SenileTeam.com");
605 
606 #ifdef SPK_SUPPORTED
607 	printText((isWide ? 324 : 192),(isWide ? 191 : 176), DARK_RED, 0, 0, "SecurePAK Edition");
608 #endif
609 
610 	if(!bgmPlay) bgmCurrent = dListCurrentPosition+dListScrollPosition;
611 	if(strlen(filelist[bgmCurrent].filename)-4 < 24)
612 		strncpy(bgmListing, filelist[bgmCurrent].filename, strlen(filelist[bgmCurrent].filename)-4);
613 	if(strlen(filelist[bgmCurrent].filename)-4 > 24)
614 		strncpy(bgmListing, filelist[bgmCurrent].filename, 24);
615 	if(!sound_query_music(a1, t1))
616 	{
617 		PlayBGM();
618 		sound_query_music(a1, t1);
619 		StopBGM();
620 	}
621 	if(t1[0]) strncpy(t2, t1, 25);
622 	if(a1[0]) strncpy(a2, a1, 25);
623 	printText((isWide ? 288 : 157),(isWide ? 35 : 23) + (11 * 0), DARK_RED, 0, 0, "Game: %s", bgmListing);
624 	printText((isWide ? 288 : 157),(isWide ? 35 : 23) + (11 * 1), bgmPlay ? DARK_GREEN : DARK_BLUE, 0, 0, "Total Tracks: %d", filelist[bgmCurrent].nTracks-1);
625 	printText((isWide ? 288 : 157),(isWide ? 35 : 23) + (11 * 2), bgmPlay ? DARK_GREEN : DARK_BLUE, 0, 0, "Current Track: %d", filelist[bgmCurrent].bgmTrack);
626 	printText((isWide ? 288 : 157),(isWide ? 35 : 23) + (11 * 3), bgmPlay ? DARK_GREEN : DARK_BLUE, 0, 0, "File: %s", filelist[bgmCurrent].bgmFileName[filelist[bgmCurrent].bgmTrack]);
627 	printText((isWide ? 288 : 157),(isWide ? 35 : 23) + (11 * 4), bgmPlay ? DARK_GREEN : DARK_BLUE, 0, 0, "Track: %s", t2);
628 	printText((isWide ? 288 : 157),(isWide ? 35 : 23) + (11 * 5), bgmPlay ? DARK_GREEN : DARK_BLUE, 0, 0, "Artist: %s", a2);
629 
630 	video_copy_screen(vscreen);
631 }
632 
drawLogs()633 void drawLogs()
634 {
635 	int i=which_logfile, j, k, l, done=0;
636 	bothkeys = bothnewkeys = 0;
637 
638 	while(!done)
639 	{
640 		// CRxTRDude - replaced bg with a log screen
641 		putscreen(vscreen,logscreen,0,0,NULL);
642 	    inputrefresh();
643 	    sound_update_music();
644 #if OPENDINGUX
645 	    printText(250, 3, RED, 0, 0, "Quit : Select");
646 #else
647 	    printText((isWide ? 410 : 250), 3, RED, 0, 0, "Quit : Escape");
648 #endif
649 		if(bothnewkeys & FLAG_ESC) done = 1;
650 
651 		if(logfile[i].ready)
652 		{
653 			printText(5, 3, RED, 0, 0, "OpenBorLog.txt");
654 			if(bothkeys & FLAG_MOVEUP) --logfile[i].line;
655 	        if(bothkeys & FLAG_MOVEDOWN) ++logfile[i].line;
656 			if(bothkeys & FLAG_MOVELEFT) logfile[i].line = 0;
657 			if(bothkeys & FLAG_MOVERIGHT) logfile[i].line = logfile[i].rows - (LOG_SCREEN_END - LOG_SCREEN_TOP);
658 			if(logfile[i].line > logfile[i].rows - (LOG_SCREEN_END - LOG_SCREEN_TOP) - 1) logfile[i].line = logfile[i].rows - (LOG_SCREEN_END - LOG_SCREEN_TOP) - 1;
659 			if(logfile[i].line < 0) logfile[i].line = 0;
660 			for(l=LOG_SCREEN_TOP, j=logfile[i].line; j<logfile[i].rows-1; l++, j++)
661 			{
662 				if(l<LOG_SCREEN_END)
663 				{
664 					char textpad[480] = {""};
665 					for(k=0; k<480; k++)
666 					{
667 						if(!logfile[i].buf->ptr[logfile[i].pos[j]+k]) break;
668 						textpad[k] = logfile[i].buf->ptr[logfile[i].pos[j]+k];
669 					}
670 					if(logfile[i].rows>0xFFFF)
671 						printText(5, l*10, WHITE, 0, 0, "0x%08x:  %s", j, textpad);
672 					else
673 						printText(5, l*10, WHITE, 0, 0, "0x%04x:  %s", j, textpad);
674 				}
675 				else break;
676 			}
677 		}
678 		else if(i == SCRIPT_LOG) printText(5, 3, RED, 0, 0, "Log NOT Found: ScriptLog.txt");
679 		else                     printText(5, 3, RED, 0, 0, "Log NOT Found: OpenBorLog.txt");
680 
681 	    video_copy_screen(vscreen);
682 	}
683 	drawMenu();
684 }
685 
drawLogo()686 void drawLogo()
687 {
688     if(savedata.logo) return;
689 	initMenu(0);
690 	video_copy_screen(bgscreen);
691 	SDL_Delay(3000);
692 	termMenu();
693 }
694 
Menu()695 void Menu()
696 {
697 	int done = 0;
698 	int ctrl = 0;
699 	loadsettings();
700 	drawLogo();
701 	dListCurrentPosition = 0;
702 	if((dListTotal = findPaks()) != 1)
703 	{
704 		sortList();
705 		getAllLogs();
706 		packfile_music_read(filelist, dListTotal);
707 		initMenu(1);
708 		drawMenu();
709 		pControl = ControlMenu;
710 
711 		while(!done)
712 		{
713 			sound_update_music();
714 			bgmStatus = sound_query_music(NULL, NULL);
715 			if(bgmPlay && !bgmStatus)
716 			{
717 				if(bgmCycle)
718 				{
719 					filelist[bgmCurrent].bgmTrack++;
720 					if(filelist[bgmCurrent].bgmTrack > filelist[bgmCurrent].nTracks - 1) filelist[bgmCurrent].bgmTrack = 0;
721 					PlayBGM();
722 				}
723 				else StopBGM();
724 				drawBGMPlayer();
725 			}
726 
727 			ctrl = Control();
728 			switch(ctrl)
729 			{
730 				case 1:
731 				case 2:
732 					done = 1;
733 					break;
734 
735 				case 3:
736 					drawLogs();
737 					break;
738 
739 				case -1:
740 					drawMenu();
741 					break;
742 
743 				case -2:
744 					drawBGMPlayer();
745 					break;
746 			}
747 		}
748 		freeAllLogs();
749 		termMenu();
750 		if(dListTotal == 0 || ctrl == 2)
751 		{
752 			if (filelist)
753 			{
754 				free(filelist);
755 				filelist = NULL;
756 			}
757 			borExit(0);
758 		}
759 	}
760 	getBasePath(packfile, filelist[dListCurrentPosition+dListScrollPosition].filename, 1);
761 	free(filelist);
762 
763 	// Restore screenformat and pixelformat to their default values
764 	screenformat = PIXEL_8;
765 	pixelformat = PIXEL_8;
766 }
767