1 /*
2  * XGalaga-SDL - a SDL port of XGalaga, clone of the game Galaga
3  * Copyright (c) 1995-1998 Joe Rumsey (mrogre@mediaone.net)
4  * Copyright (c) 2010 Frank Zago
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  * 02110-1301, USA.
20  */
21 
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #ifdef HAVE_UNISTD_H
26 # include <unistd.h>
27 #endif
28 #include <sys/stat.h>
29 #ifdef HAVE_FCNTL_H
30 # include <fcntl.h>
31 #endif
32 #include <ctype.h>
33 #include <pwd.h>
34 #include <string.h>
35 
36 #include "xgalaga.h"
37 
38 #include <SDL/SDL_endian.h>
39 
40 #define NUM_MY_SCORES 10
41 
42 static char new_name[20];
43 static int nnpos=0;
44 static int my_thisplace = -1;
45 
46 static struct high_score {
47     char name[20];
48     Uint32 score;
49     Uint32 level;
50 } my_scores[NUM_MY_SCORES];
51 
do_name(void)52 void do_name(void)
53 {
54     char buf[21];
55     static int init = 0;
56 
57     if(!init) {
58 		strcpy(new_name, getUsersFullName());
59 		nnpos = strlen(new_name);
60 		init = 1;
61     }
62     SFont_WriteCenter(fnt_reg_red, 250, "Great score! Enter your name:");
63     sprintf(buf, "%s_", new_name);
64     SFont_WriteCenter(fnt_reg_cyan, 250 + SFont_TextHeight(fnt_reg_cyan), buf);
65 }
66 
67 #ifdef __WII__
getUsersFullName(void)68 char *getUsersFullName(void)
69 {
70 	return "Player";
71 }
72 #else
getUsersFullName()73 char *getUsersFullName()
74 {
75     struct passwd *pass;
76     char *comma;
77     char *cp1, *cp2;
78     static char fullname[80];
79 
80     /* Get user information from password file */
81     if (!(pass = getpwuid(getuid())))
82         return("Anonymous?");       /* Unknown user oops. */
83 
84     /* find a comma indicating further info after name */
85     comma = strchr(pass->pw_gecos, ',');
86 
87     /* NULL out the comma */
88     if (comma) *comma = '\0';
89 
90     /* Use the nickname if not null otherwise password file name */
91     cp1 = pass->pw_gecos;
92     cp2 = fullname;
93 
94     /* Search through the gecos field looking for an '&' which on very
95      * old UNIX systems is supposed to be the users user name with the
96      * first letter uppercased.
97      */
98     while(*cp1)
99     {
100         /* Look for the '&' symbol */
101         if(*cp1 != '&')
102             *cp2++ = *cp1++;
103         else
104         {
105             /* A ha. Now copy the users name to be in place of '&' */
106             strcpy(cp2, pass->pw_name);
107 
108             /* Convert the first letter to uppercase. */
109             if(islower(*cp2))
110                 *cp2 = toupper(*cp2);
111 
112             /* Continue with the remaining string */
113             while(*cp2) cp2++;
114                 cp1++;
115         }
116     }
117 
118     /* shorten to 20 chars */
119     fullname[19] = 0;
120 
121     /* Return their name without any trailing stuff */
122     return(fullname);
123 }
124 #endif
125 
save_scores(void)126 static void save_scores(void)
127 {
128     int i;
129     int hsf;
130     long x;
131     char my_file_name [256], *home;
132 
133 #ifdef __WII__
134 	home = DATADIR;
135 #else
136 	home = getenv("HOME");
137 #endif
138 
139     if (home) {
140 		snprintf(my_file_name, sizeof(my_file_name)-1, "%s/%s", home, SCORE_FILE_NAME);
141 		hsf = open(my_file_name, O_WRONLY | O_TRUNC | O_CREAT, 0644);
142 
143 		if(hsf < 0) {
144 			fprintf(stderr, "Couldn't write scores file %s\n", my_file_name);
145 			return;
146 		}
147 		for(i=0;i<NUM_MY_SCORES;i++) {
148 			if(write(hsf, my_scores[i].name, 20) < 20)
149 				goto error2;
150 			x=SDL_SwapBE32(my_scores[i].score);
151 			if(write(hsf, &x, sizeof(Uint32)) < (ssize_t)sizeof(Uint32))
152 				goto error2;
153 			x=SDL_SwapBE32(my_scores[i].level);
154 			if(write(hsf, &x, sizeof(Uint32)) < (ssize_t)sizeof(Uint32))
155 				goto error2;
156 		}
157         close(hsf);
158     }
159 
160     return;
161 error2:
162     fprintf(stderr, "Error saving high scores file %s\n", my_file_name);
163     return;
164 }
165 
add_score(char * name,unsigned int score)166 void add_score(char *name, unsigned int score)
167 {
168     int i,j ; /* ,k; */
169 
170     load_scores();
171 
172     for(i=0;i<NUM_MY_SCORES;i++) {
173 		if(score > my_scores[i].score) {
174 			for(j=NUM_MY_SCORES-1;j>i;j--) {
175 				strcpy(my_scores[j].name, my_scores[j-1].name);
176 				my_scores[j].score = my_scores[j-1].score;
177 				my_scores[j].level = my_scores[j-1].level;
178 			}
179 			strcpy(my_scores[i].name, name);
180 			my_scores[i].score = score;
181 			my_scores[i].level = level;
182 			my_thisplace = i;
183 			break;
184 		}
185     }
186     save_scores();
187 }
188 
189 /* Read a new name for highscore. */
score_key(SDLKey key)190 int score_key(SDLKey key)
191 {
192 	switch(key) {
193 	case SDLK_RETURN:
194 	case SDLK_KP_ENTER:
195 	case SDLK_ESCAPE:
196 		gstate = INTRO;
197 		add_score(new_name, score);
198 		title_page = 1;
199 		pagetimer = 300;
200 		break;
201 
202 	case SDLK_BACKSPACE:
203 	case SDLK_DELETE:
204 	case SDLK_KP4:
205 	case SDLK_LEFT:
206 		if (nnpos > 0) {
207 			nnpos--;
208 			new_name[nnpos] = 0;
209 		}
210 		break;
211 
212 	case SDLK_HOME:
213 		nnpos = 0;
214 		new_name[nnpos] = 0;
215 		break;
216 
217 	default:
218 		if (nnpos < 19 &&
219 			key >= SDLK_SPACE &&
220 			key <= SDLK_z) {
221 			new_name[nnpos++] = key;
222 			new_name[nnpos] = 0;
223 		}
224 		break;
225 	}
226 
227 	return 1;
228 }
229 
230 
check_score(unsigned int score)231 int check_score(unsigned int score)
232 {
233     int i;
234 
235     load_scores(); /* in case someone else has gotten a high score */
236 
237     for(i=0;i<NUM_MY_SCORES;i++) {
238 		if(score > my_scores[i].score)
239 			return 1;
240     }
241 
242     my_thisplace = -1;
243     return 0;
244 }
245 
246 
show_scores(int top)247 void show_scores(int top)
248 {
249     int i;
250     char buf[60];
251 	int dy = SFont_TextHeight(fnt_reg_yellow);
252 	const char *labels = "Rank  Name                      Score   Level";
253 	int length;
254 
255     SFont_WriteCenter(fnt_reg_yellow, top, "High scores");
256 	top += dy;
257     SFont_WriteCenter(fnt_reg_yellow, top, labels);
258 
259 	/* Draw a line. */
260 	length = SFont_TextWidth(fnt_reg_yellow, labels);
261 	S_DrawRect((winwidth-length)/2, top + 1 + SFont_TextHeight(fnt_reg_yellow),
262 			   length, 1,
263 			   SDL_MapRGB(screen->format, 0xff, 0, 0));
264 
265     for(i=0;i<NUM_MY_SCORES;i++) {
266 		SFont_Font *font = i==my_thisplace ? fnt_reg_red : fnt_reg_grey;
267 
268 		sprintf(buf, "  %2d. %-20s     %7lu %5lu",
269 				i+1, my_scores[i].name,
270 				(unsigned long)my_scores[i].score,
271 				(unsigned long)my_scores[i].level);
272 		SFont_WriteCenter(font, top+(3+i)*dy, buf);
273     }
274 }
275 
load_scores(void)276 void load_scores(void)
277 {
278     int i;
279     int hsf;
280     char my_file_name[256], *home;
281 
282 #ifdef __WII__
283 	home = DATADIR;
284 #else
285 	home = getenv("HOME");
286 #endif
287 
288 	if (home) {
289 		snprintf(my_file_name, sizeof(my_file_name)-1, "%s/%s", home, SCORE_FILE_NAME);
290 		hsf = open(my_file_name, O_RDONLY);
291 		if(hsf <0 ) {
292 			fprintf(stderr, "Trouble opening high scores file '%s'\n", my_file_name);
293 			for(i=0;i<NUM_MY_SCORES;i++) {
294 				my_scores[i].name[0]=0;
295 				my_scores[i].score = 0;
296 				my_scores[i].level = 0;
297 			}
298 		} else {
299 			for(i=0;i<NUM_MY_SCORES;i++) {
300 				if(read(hsf, my_scores[i].name, 20) < 20)
301 					goto error2;
302 				if(read(hsf, &my_scores[i].score, sizeof(Uint32)) < (ssize_t)sizeof(Uint32))
303 					goto error2;
304 				if(read(hsf, &my_scores[i].level, sizeof(Uint32)) < (ssize_t)sizeof(Uint32))
305 					goto error2;
306 				my_scores[i].score = SDL_SwapBE32(my_scores[i].score);
307 				my_scores[i].level = SDL_SwapBE32(my_scores[i].level);
308 			}
309 		}
310 		close(hsf);
311     } else {
312 		fprintf(stderr, "No HOME variable, so no personal score file.\n");
313 		for(i=0;i<NUM_MY_SCORES;i++) {
314 			my_scores[i].name[0]=0;
315 			my_scores[i].score = 0;
316 			my_scores[i].level = 0;
317 		}
318     }
319     return;
320 
321 error2:
322     if(i>0)
323 		fprintf(stderr, "Error reading high scores file '%s'\n", my_file_name);
324     for(i=0;i<NUM_MY_SCORES;i++) {
325 		my_scores[i].name[0]=0;
326 		my_scores[i].score = 0;
327 		my_scores[i].level = 0;
328     }
329     close(hsf);
330 }
331 
332 #ifndef __WII_
print_scores(void)333 void print_scores(void)
334 {
335     int i;
336 
337     load_scores();
338 
339     printf("-----------------------------------------------\n");
340     printf("\nYour High Scores:\n");
341     printf("--------------------------------------\n");
342     printf("%-20s %8s %8s\n", "name", "score", "level");
343     printf("--------------------------------------\n");
344     for(i=0;i<NUM_MY_SCORES;i++) {
345 	if(my_scores[i].score == 0)
346 	    break;
347 	printf("%-20s %8lu %8lu\n", my_scores[i].name,
348 	       (unsigned long)my_scores[i].score, (unsigned long)my_scores[i].level);
349     }
350     printf("--------------------------------------\n");
351 }
352 #endif
353