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