1 /* ------------------------------------------------------------- */
2 /* 								 */
3 /* Maelstrom							 */
4 /* By Andrew Welch						 */
5 /* 								 */
6 /* Ported to Linux  (Spring 1995)				 */
7 /* Ported to Win95  (Fall   1996) -- not releasable		 */
8 /* Ported to SDL    (Fall   1997)                                */
9 /* By Sam Lantinga  (slouken@devolution.com)			 */
10 /* 								 */
11 /* ------------------------------------------------------------- */
12 
13 #include "Maelstrom_Globals.h"
14 #include "buttonlist.h"
15 #include "load.h"
16 #include "fastrand.h"
17 #include "checksum.h"
18 
19 /* External functions used in this file */
20 extern int DoInitializations(Uint32 video_flags);		/* init.cc */
21 
22 static char *Version =
23 "Maelstrom v1.4.3 (GPL version 3.0.6) -- 10/19/2002 by Sam Lantinga\n";
24 
25 // Global variables set in this file...
26 int	gStartLives;
27 int	gStartLevel;
28 Bool	gUpdateBuffer;
29 Bool	gRunning;
30 int	gNoDelay;
31 
32 // Local variables in this file...
33 static ButtonList buttons;
34 
35 // Local functions in this file...
36 static void DrawMainScreen(void);
37 static void DrawSoundLevel(void);
38 static void DrawKey(MPoint *pt, char *ch, char *str, void (*callback)(void));
39 
40 // Main Menu actions:
RunDoAbout(void)41 static void RunDoAbout(void)
42 {
43 	gNoDelay = 0;
44 	Delay(SOUND_DELAY);
45 	sound->PlaySound(gNovaAppears, 5);
46 	DoAbout();
47 }
RunConfigureControls(void)48 static void RunConfigureControls(void)
49 {
50 	Delay(SOUND_DELAY);
51 	sound->PlaySound(gHomingAppears, 5);
52 	ConfigureControls();
53 }
RunPlayGame(void)54 static void RunPlayGame(void)
55 {
56 	gStartLives = 3;
57 	gStartLevel = 1;
58 	gNoDelay = 0;
59 	sound->PlaySound(gNewLife, 5);
60 	Delay(SOUND_DELAY);
61 	NewGame();
62 	Message(NULL);		/* Clear any messages */
63 }
RunQuitGame(void)64 static void RunQuitGame(void)
65 {
66 	Delay(SOUND_DELAY);
67 	sound->PlaySound(gMultiplierGone, 5);
68 	while ( sound->Playing() )
69 		Delay(SOUND_DELAY);
70 	gRunning = false;
71 }
IncrementSound(void)72 static void IncrementSound(void)
73 {
74 	if ( gSoundLevel < 8 ) {
75 		sound->Volume(++gSoundLevel);
76 		sound->PlaySound(gNewLife, 5);
77 
78 		/* -- Draw the new sound level */
79 		DrawSoundLevel();
80 	}
81 }
DecrementSound(void)82 static void DecrementSound(void)
83 {
84 	if ( gSoundLevel > 0 ) {
85 		sound->Volume(--gSoundLevel);
86 		sound->PlaySound(gNewLife, 5);
87 
88 		/* -- Draw the new sound level */
89 		DrawSoundLevel();
90 	}
91 }
SetSoundLevel(int volume)92 static void SetSoundLevel(int volume)
93 {
94 	/* Make sure the device is working */
95 	sound->Volume(volume);
96 
97 	/* Set the new sound level! */
98 	gSoundLevel = volume;
99 	sound->PlaySound(gNewLife, 5);
100 
101 	/* -- Draw the new sound level */
102 	DrawSoundLevel();
103 }
104 
RunZapScores(void)105 static void RunZapScores(void)
106 {
107 	Delay(SOUND_DELAY);
108 	sound->PlaySound(gMultShotSound, 5);
109 	if ( ZapHighScores() ) {
110 		/* Fade the screen and redisplay scores */
111 		screen->Fade();
112 		Delay(SOUND_DELAY);
113 		sound->PlaySound(gExplosionSound, 5);
114 		gUpdateBuffer = true;
115 	}
116 }
117 
118 /* ----------------------------------------------------------------- */
119 /* -- Run a graphics speed test.                                     */
RunSpeedTest(void)120 static void RunSpeedTest(void)
121 {
122 	const int test_reps = 100;	/* How many full cycles to run */
123 
124 	Uint32 then, now;
125 	int i, frame, x=((640/2)-16), y=((480/2)-16), onscreen=0;
126 
127 	screen->Clear();
128 	then = SDL_GetTicks();
129 	for ( i=0; i<test_reps; ++i ) {
130 		for ( frame=0; frame<SHIP_FRAMES; ++frame ) {
131 			if ( onscreen ) {
132 				screen->Clear(x, y, 32, 32);
133 			} else {
134 				onscreen = 1;
135 			}
136 			screen->QueueBlit(x, y, gPlayerShip->sprite[frame]);
137 			screen->Update();
138 		}
139 	}
140 	now = SDL_GetTicks();
141 	mesg("Graphics speed test took %d microseconds per cycle.\r\n",
142 						((now-then)/test_reps));
143 }
144 
145 /* ----------------------------------------------------------------- */
146 /* -- Print a Usage message and quit.
147       In several places we depend on this function exiting.
148  */
149 static char *progname;
PrintUsage(void)150 void PrintUsage(void)
151 {
152 	error("\nUsage: %s [-netscores] -printscores\n", progname);
153 	error("or\n");
154 	error("Usage: %s <options>\n\n", progname);
155 	error("Where <options> can be any of:\n\n"
156 "	-fullscreen		# Run Maelstrom in full-screen mode\n"
157 "	-gamma [0-8]		# Set the gamma correction\n"
158 "	-volume [0-8]		# Set the sound volume\n"
159 "	-netscores		# Use the world-wide network score server\n"
160 	);
161 	LogicUsage();
162 	error("\n");
163 	exit(1);
164 }
165 
166 /* ----------------------------------------------------------------- */
167 /* -- Blitter main program */
main(int argc,char * argv[])168 int main(int argc, char *argv[])
169 {
170 	/* Command line flags */
171 	int doprinthigh = 0;
172 	int speedtest = 0;
173 	Uint32 video_flags = SDL_SWSURFACE;
174 
175 	/* Normal variables */
176 	SDL_Event event;
177 	LibPath::SetExePath(argv[0]);
178 
179 #ifndef __WIN95__
180 	/* The first thing we do is calculate our checksum */
181 	(void) checksum();
182 #endif /* ! Win95 */
183 
184 	/* Seed the random number generator */
185 	SeedRandom(0L);
186 	/* Initialize the controls */
187 	LoadControls();
188 
189 	/* Initialize game logic data structures */
190 	if ( InitLogicData() < 0 ) {
191 		exit(1);
192 	}
193 
194 	/* Parse command line arguments */
195 	for ( progname=argv[0]; --argc; ++argv ) {
196 		if ( strcmp(argv[1], "-fullscreen") == 0 ) {
197 			video_flags |= SDL_FULLSCREEN;
198 		} else
199 		if ( strcmp(argv[1], "-gamma") == 0 ) {
200 			int gammacorrect;
201 
202 			if ( ! argv[2] ) {  /* Print the current gamma */
203 				mesg("Current Gamma correction level: %d\n",
204 								gGammaCorrect);
205 				exit(0);
206 			}
207 			if ( (gammacorrect=atoi(argv[2])) < 0 ||
208 							gammacorrect > 8 ) {
209 				error(
210 	"Gamma correction value must be between 0 and 8. -- Exiting.\n");
211 				exit(1);
212 			}
213 			/* We need to update the gamma */
214 			gGammaCorrect = gammacorrect;
215 			SaveControls();
216 
217 			++argv;
218 			--argc;
219 		}
220 		else if ( strcmp(argv[1], "-volume") == 0 ) {
221 			int volume;
222 
223 			if ( ! argv[2] ) {  /* Print the current volume */
224 				mesg("Current volume level: %d\n",
225 								gSoundLevel);
226 				exit(0);
227 			}
228 			if ( (volume=atoi(argv[2])) < 0 || volume > 8 ) {
229 				error(
230 	"Volume must be a number between 0 and 8. -- Exiting.\n");
231 				exit(1);
232 			}
233 			/* We need to update the volume */
234 			gSoundLevel = volume;
235 			SaveControls();
236 
237 			++argv;
238 			--argc;
239 		}
240 #define CHECKSUM_DEBUG
241 #ifdef CHECKSUM_DEBUG
242 		else if ( strcmp(argv[1], "-checksum") == 0 ) {
243 			mesg("Checksum = %s\n", get_checksum(NULL, 0));
244 			exit(0);
245 		}
246 #endif /* CHECKSUM_DEBUG */
247 		else if ( strcmp(argv[1], "-printscores") == 0 )
248 			doprinthigh = 1;
249 		else if ( strcmp(argv[1], "-netscores") == 0 )
250 			gNetScores = 1;
251 		else if ( strcmp(argv[1], "-speedtest") == 0 )
252 			speedtest = 1;
253 		else if ( LogicParseArgs(&argv, &argc) == 0 ) {
254 			/* LogicParseArgs() took care of everything */;
255 		} else if ( strcmp(argv[1], "-version") == 0 ) {
256 			error("%s", Version);
257 			exit(0);
258 		} else {
259 			PrintUsage();
260 		}
261 	}
262 
263 	/* Do we just want the high scores? */
264 	if ( doprinthigh ) {
265 		PrintHighScores();
266 		exit(0);
267 	}
268 
269 	/* Make sure we have a valid player list (netlogic) */
270 	if ( InitLogic() < 0 )
271 		exit(1);
272 
273 	/* Initialize everything. :) */
274 	if ( DoInitializations(video_flags) < 0 ) {
275 		/* An error message was already printed */
276 		exit(1);
277 	}
278 
279 	if ( speedtest ) {
280 		RunSpeedTest();
281 		exit(0);
282 	}
283 
284 	gRunning = true;
285 	sound->PlaySound(gNovaBoom, 5);
286 	screen->Fade();		/* Fade-out */
287 	Delay(SOUND_DELAY);
288 	gUpdateBuffer = true;
289 	while ( sound->Playing() )
290 		Delay(SOUND_DELAY);
291 
292 	while ( gRunning ) {
293 
294 		/* Update the screen if necessary */
295 		if ( gUpdateBuffer )
296 			DrawMainScreen();
297 
298 		/* -- Get an event */
299 		screen->WaitEvent(&event);
300 
301 		/* -- Handle it! */
302 		if ( event.type == SDL_KEYDOWN ) {
303 			switch (event.key.keysym.sym) {
304 
305 				/* -- Toggle fullscreen */
306 				case SDLK_RETURN:
307 					if ( event.key.keysym.mod & KMOD_ALT )
308 						screen->ToggleFullScreen();
309 					break;
310 
311 				/* -- About the game...*/
312 				case SDLK_a:
313 					RunDoAbout();
314 					break;
315 
316 				/* -- Configure the controls */
317 				case SDLK_c:
318 					RunConfigureControls();
319 					break;
320 
321 				/* -- Start the game */
322 				case SDLK_p:
323 					RunPlayGame();
324 					break;
325 
326 				/* -- Start the game */
327 				case SDLK_l:
328 					Delay(SOUND_DELAY);
329 					sound->PlaySound(gLuckySound, 5);
330 					gStartLevel = GetStartLevel();
331 					if ( gStartLevel > 0 ) {
332 						Delay(SOUND_DELAY);
333 						sound->PlaySound(gNewLife, 5);
334 						Delay(SOUND_DELAY);
335 						NewGame();
336 					}
337 					break;
338 
339 				/* -- Let them leave */
340 				case SDLK_q:
341 					RunQuitGame();
342 					break;
343 
344 				/* -- Set the volume */
345 				/* (SDLK_0 - SDLK_8 are contiguous) */
346 				case SDLK_0:
347 				case SDLK_1:
348 				case SDLK_2:
349 				case SDLK_3:
350 				case SDLK_4:
351 				case SDLK_5:
352 				case SDLK_6:
353 				case SDLK_7:
354 				case SDLK_8:
355 					SetSoundLevel(event.key.keysym.sym
356 								- SDLK_0);
357 					break;
358 
359 				/* -- Give 'em a little taste of the peppers */
360 				case SDLK_x:
361 					Delay(SOUND_DELAY);
362 					sound->PlaySound(gEnemyAppears, 5);
363 					ShowDawn();
364 					break;
365 
366 				/* -- Zap the high scores */
367 				case SDLK_z:
368 					RunZapScores();
369 					break;
370 
371 				/* -- Create a screen dump of high scores */
372 				case SDLK_F3:
373 					screen->ScreenDump("ScoreDump",
374 							64, 48, 298, 384);
375 					break;
376 
377 				// Ignore Shift, Ctrl, Alt keys
378 				case SDLK_LSHIFT:
379 				case SDLK_RSHIFT:
380 				case SDLK_LCTRL:
381 				case SDLK_RCTRL:
382 				case SDLK_LALT:
383 				case SDLK_RALT:
384 					break;
385 
386 				// Dink! :-)
387 				default:
388 					Delay(SOUND_DELAY);
389 					sound->PlaySound(gSteelHit, 5);
390 					break;
391 			}
392 		} else
393 		/* -- Handle mouse clicks */
394 		if ( event.type == SDL_MOUSEBUTTONDOWN ) {
395 			buttons.Activate_Button(event.button.x,
396 						event.button.y);
397 		} else
398 		/* -- Handle window close requests */
399 		if ( event.type == SDL_QUIT ) {
400 			RunQuitGame();
401 		}
402 	}
403 	screen->Fade();
404 	Delay(60);
405 	return(0);
406 }	/* -- main */
407 
408 
DrawText(int x,int y,char * text,MFont * font,Uint8 style,Uint8 R,Uint8 G,Uint8 B)409 int DrawText(int x, int y, char *text, MFont *font, Uint8 style,
410 					Uint8 R, Uint8 G, Uint8 B)
411 {
412 	SDL_Surface *textimage;
413 	int width;
414 
415 	textimage = fontserv->TextImage(text, font, style, R, G, B);
416 	if ( textimage == NULL ) {
417 		width = 0;
418 	} else {
419 		screen->QueueBlit(x, y-textimage->h+2, textimage, NOCLIP);
420 		width = textimage->w;
421 		fontserv->FreeText(textimage);
422 	}
423 	return(width);
424 }
425 
426 
427 /* ----------------------------------------------------------------- */
428 /* -- Draw the current sound volume */
DrawSoundLevel(void)429 static void DrawSoundLevel(void)
430 {
431 	static int need_init=1;
432 	static MFont *geneva;
433 	static char text[12];
434 	static int xOff, yOff;
435 
436 	if ( need_init ) {
437 		if ( (geneva = fontserv->NewFont("Geneva", 9)) == NULL ) {
438 			error("Can't use Geneva font! -- Exiting.\n");
439 			exit(255);
440 		}
441 		xOff = (SCREEN_WIDTH - 512) / 2;
442 		yOff = (SCREEN_HEIGHT - 384) / 2;
443 		need_init = 0;
444 	} else {
445 		DrawText(xOff+309-7, yOff+240-6, text, geneva, STYLE_BOLD,
446 							0x00, 0x00, 0x00);
447 	}
448 	snprintf(text, sizeof(text), "%d", gSoundLevel);
449 	DrawText(xOff+309-7, yOff+240-6, text, geneva, STYLE_BOLD,
450 						30000>>8, 30000>>8, 0xFF);
451 	screen->Update();
452 }	/* -- DrawSoundLevel */
453 
454 
455 /* ----------------------------------------------------------------- */
456 /* -- Draw the main screen */
457 
DrawMainScreen(void)458 void DrawMainScreen(void)
459 {
460 	SDL_Surface *title;
461 	MFont  *font, *bigfont;
462 	MPoint  pt;
463 	Uint16	width, height;
464 	Uint16  xOff, yOff, botDiv, rightDiv;
465 	Uint16  index, sRt, wRt, sw;
466 	Uint32  clr, ltClr, ltrClr;
467 	char buffer[128];
468 	int offset;
469 
470 	gUpdateBuffer = false;
471 	buttons.Delete_Buttons();
472 
473 	width = 512;
474 	height = 384;
475 	xOff = (SCREEN_WIDTH - width) / 2;
476 	yOff = (SCREEN_HEIGHT - height) / 2;
477 
478 	title = Load_Title(screen, 129);
479 	if ( title == NULL ) {
480 		error("Can't load 'title' title! (ID=%d)\n", 129);
481 		exit(255);
482         }
483 
484 	clr = screen->MapRGB(30000>>8, 30000>>8, 0xFF);
485 	ltClr = screen->MapRGB(40000>>8, 40000>>8, 0xFF);
486 	ltrClr = screen->MapRGB(50000>>8, 50000>>8, 0xFF);
487 
488 	screen->Lock();
489 	screen->Clear();
490 	/* -- Draw the screen frame */
491 	screen->DrawRect(xOff-1, yOff-1, width+2, height+2, clr);
492 	screen->DrawRect(xOff-2, yOff-2, width+4, height+4, clr);
493 	screen->DrawRect(xOff-3, yOff-3, width+6, height+6, ltClr);
494 	screen->DrawRect(xOff-4, yOff-4, width+8, height+8, ltClr);
495 	screen->DrawRect(xOff-5, yOff-5, width+10, height+10, ltrClr);
496 	screen->DrawRect(xOff-6, yOff-6, width+12, height+12, ltClr);
497 	screen->DrawRect(xOff-7, yOff-7, width+14, height+14, clr);
498 	/* -- Draw the dividers */
499 	botDiv = yOff + 5 + title->h + 5;
500 	rightDiv = xOff + 5 + title->w + 5;
501 	screen->DrawLine(rightDiv, yOff, rightDiv, yOff+height, ltClr);
502 	screen->DrawLine(xOff, botDiv, rightDiv, botDiv, ltClr);
503 	screen->DrawLine(rightDiv, 263+yOff, xOff+width, 263+yOff, ltClr);
504 	/* -- Draw the title image */
505 	screen->Unlock();
506 	screen->QueueBlit(xOff+5, yOff+5, title, NOCLIP);
507 	screen->Update();
508 	screen->FreeImage(title);
509 
510 
511 	/* -- Draw the high scores */
512 
513 	/* -- First the headings  -- fontserv() isn't elegant, but hey.. */
514 	if ( (bigfont = fontserv->NewFont("New York", 18)) == NULL ) {
515 		error("Can't use New York (18) font! -- Exiting.\n");
516 		exit(255);
517 	}
518 	DrawText(xOff+5, botDiv+22, "Name", bigfont, STYLE_ULINE,
519 						0xFF, 0xFF, 0x00);
520 	sRt = xOff+185;
521 	DrawText(sRt, botDiv+22, "Score", bigfont, STYLE_ULINE,
522 						0xFF, 0xFF, 0x00);
523 	sRt += fontserv->TextWidth("Score", bigfont, STYLE_ULINE);
524 	wRt = xOff+245;
525 	DrawText(wRt, botDiv+22, "Wave", bigfont, STYLE_ULINE,
526 						0xFF, 0xFF, 0x00);
527 	wRt += fontserv->TextWidth("Wave", bigfont, STYLE_ULINE)-10;
528 
529 	/* -- Now the scores */
530 	LoadScores();
531 	if ( (font = fontserv->NewFont("New York", 14)) == NULL ) {
532 		error("Can't use New York (14) font! -- Exiting.\n");
533 		exit(255);
534 	}
535 
536 	for (index = 0; index < 10; index++) {
537 		Uint8 R, G, B;
538 
539 		if ( gLastHigh == index ) {
540 			R = 0xFF;
541 			G = 0xFF;
542 			B = 0xFF;
543 		} else {
544 			R = 30000>>8;
545 			G = 30000>>8;
546 			B = 30000>>8;
547 		}
548 		DrawText(xOff+5, botDiv+42+(index*18), hScores[index].name,
549 						font, STYLE_BOLD, R, G, B);
550 		snprintf(buffer, sizeof(buffer), "%u", hScores[index].score);
551 		sw = fontserv->TextWidth(buffer, font, STYLE_BOLD);
552 		DrawText(sRt-sw, botDiv+42+(index*18), buffer,
553 						font, STYLE_BOLD, R, G, B);
554 		snprintf(buffer, sizeof(buffer), "%u", hScores[index].wave);
555 		sw = fontserv->TextWidth(buffer, font, STYLE_BOLD);
556 		DrawText(wRt-sw, botDiv+42+(index*18), buffer,
557 						font, STYLE_BOLD, R, G, B);
558 	}
559 	delete font;
560 
561 	DrawText(xOff+5, botDiv+46+(10*18)+3, "Last Score: ",
562 					bigfont, STYLE_NORM, 0xFF, 0xFF, 0xFF);
563 	snprintf(buffer, sizeof(buffer), "%d", GetScore());
564 	sw = fontserv->TextWidth("Last Score: ", bigfont, STYLE_NORM);
565 	DrawText(xOff+5+sw, botDiv+46+(index*18)+3, buffer,
566 					bigfont, STYLE_NORM, 0xFF, 0xFF, 0xFF);
567 	delete bigfont;
568 
569 	/* -- Draw the Instructions */
570 	offset = 34;
571 
572 	pt.h = rightDiv + 10;
573 	pt.v = yOff + 10;
574 	DrawKey(&pt, "P", " Start playing Maelstrom", RunPlayGame);
575 
576 	pt.h = rightDiv + 10;
577 	pt.v += offset;
578 	DrawKey(&pt, "C", " Configure the game controls", RunConfigureControls);
579 
580 	pt.h = rightDiv + 10;
581 	pt.v += offset;
582 	DrawKey(&pt, "Z", " Zap the high scores", RunZapScores);
583 
584 	pt.h = rightDiv + 10;
585 	pt.v += offset;
586 	DrawKey(&pt, "A", " About Maelstrom...", RunDoAbout);
587 
588 	pt.v += offset;
589 
590 	pt.h = rightDiv + 10;
591 	pt.v += offset;
592 	DrawKey(&pt, "Q", " Quit Maelstrom", RunQuitGame);
593 
594 	pt.h = rightDiv + 10;
595 	pt.v += offset;
596 	DrawKey(&pt, "0", " ", DecrementSound);
597 
598 	if ( (font = fontserv->NewFont("Geneva", 9)) == NULL ) {
599 		error("Can't use Geneva font! -- Exiting.\n");
600 		exit(255);
601 	}
602 	DrawText(pt.h+gKeyIcon->w+3, pt.v+19, "-",
603 				font, STYLE_NORM, 0xFF, 0xFF, 0x00);
604 
605 	pt.h = rightDiv + 50;
606 	DrawKey(&pt, "8", " Set Sound Volume", IncrementSound);
607 
608 /* -- Draw the credits */
609 
610 	DrawText(xOff+5+68, yOff+5+127, "Port to Linux by Sam Lantinga",
611 				font, STYLE_BOLD, 0xFF, 0xFF, 0x00);
612 	DrawText(rightDiv+10, yOff+259, "�1992-4 Ambrosia Software, Inc.",
613 				font, STYLE_BOLD, 0xFF, 0xFF, 0xFF);
614 
615 /* -- Draw the version number */
616 
617 	DrawText(xOff+20, yOff+151, VERSION_STRING,
618 				font, STYLE_NORM, 0xFF, 0xFF, 0xFF);
619 	delete font;
620 
621 	DrawSoundLevel();
622 
623 	/* Always drawing while faded out -- fade in */
624 	screen->Update();
625 	screen->Fade();
626 }	/* -- DrawMainScreen */
627 
628 
629 
630 /* ----------------------------------------------------------------- */
631 /* -- Draw the key and its function */
632 
DrawKey(MPoint * pt,char * key,char * text,void (* callback)(void))633 static void DrawKey(MPoint *pt, char *key, char *text, void (*callback)(void))
634 {
635 	MFont *geneva;
636 
637 	if ( (geneva = fontserv->NewFont("Geneva", 9)) == NULL ) {
638 		error("Can't use Geneva font! -- Exiting.\n");
639 		exit(255);
640 	}
641 	screen->QueueBlit(pt->h, pt->v, gKeyIcon);
642 	screen->Update();
643 
644 	DrawText(pt->h+14, pt->v+20, key, geneva, STYLE_BOLD, 0xFF, 0xFF, 0xFF);
645 	DrawText(pt->h+13, pt->v+19, key, geneva, STYLE_BOLD, 0x00, 0x00, 0x00);
646 	DrawText(pt->h+gKeyIcon->w+3, pt->v+19, text,
647 					geneva, STYLE_BOLD, 0xFF, 0xFF, 0x00);
648 	delete geneva;
649 
650 	buttons.Add_Button(pt->h, pt->v, gKeyIcon->w, gKeyIcon->h, callback);
651 }	/* -- DrawKey */
652 
653 
Message(char * message)654 void Message(char *message)
655 {
656 	static MFont *font;
657 	static int xOff;
658 	static char *last_message;
659 
660 	if ( ! last_message ) { 	/* Initialize everything */
661 		/* This was taken from the DrawMainScreen function */
662 		xOff = (SCREEN_WIDTH - 512) / 2;
663 
664 		if ( (font = fontserv->NewFont("New York", 14)) == NULL ) {
665 			error("Can't use New York(14) font! -- Exiting.\n");
666 			exit(255);
667 		}
668 	} else {
669 		DrawText(xOff, 25, last_message, font, STYLE_BOLD, 0, 0, 0);
670 		delete[] last_message;
671 	}
672 	if ( message ) {
673 		DrawText(xOff, 25, message, font, STYLE_BOLD, 0xCC,0xCC,0xCC);
674 		last_message = new char[strlen(message)+1];
675 		strcpy(last_message, message);
676 	} else {
677 		last_message = new char[1];
678 		last_message[0] = '\0';
679 	}
680 	screen->Update();
681 }
682 
683