diff options
-rw-r--r-- | apps/recorder/sokoban.c | 119 |
1 files changed, 40 insertions, 79 deletions
diff --git a/apps/recorder/sokoban.c b/apps/recorder/sokoban.c index 5e4148c2e1..d28e32f430 100644 --- a/apps/recorder/sokoban.c +++ b/apps/recorder/sokoban.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include "screens.h" | 34 | #include "screens.h" |
35 | #include "font.h" | 35 | #include "font.h" |
36 | #include "file.h" | 36 | #include "file.h" |
37 | #include "misc.h" | ||
38 | #include "debug.h" | ||
37 | 39 | ||
38 | #ifdef SIMULATOR | 40 | #ifdef SIMULATOR |
39 | #include <stdio.h> | 41 | #include <stdio.h> |
@@ -255,40 +257,29 @@ static void init_boards(void) | |||
255 | 257 | ||
256 | static int get_level_count(void) | 258 | static int get_level_count(void) |
257 | { | 259 | { |
258 | int i = 0; | ||
259 | int fd = 0; | 260 | int fd = 0; |
260 | int nread = 0; | 261 | int len, lastlen = 0; |
261 | char buffer[ROWS * COLS * 2]; | 262 | char buffer[COLS + 3]; /* COLS plus CR/LF and \0 */ |
262 | 263 | ||
263 | if ((fd = open(LEVELS_FILE, O_RDONLY)) < 0) { | 264 | if ((fd = open(LEVELS_FILE, O_RDONLY)) < 0) { |
264 | splash(0, 0, true, "Unable to open %s", LEVELS_FILE); | 265 | splash(0, 0, true, "Unable to open %s", LEVELS_FILE); |
265 | return -1; | 266 | return -1; |
266 | } | 267 | } |
267 | 268 | ||
268 | do { | 269 | while(1) { |
269 | if ((nread = read(fd, buffer, sizeof(buffer))) < 0) { | 270 | len = read_line(fd, buffer, sizeof(buffer)); |
270 | splash(0, 0, true, "Reading %s failed.", LEVELS_FILE); | 271 | if(len <= 0) |
271 | close(fd); | 272 | break; |
272 | return -1; | ||
273 | } | ||
274 | |||
275 | for (i = 0; i < (nread - 1); i++) { | ||
276 | if (buffer[i] == '\n' && buffer[i+1] == '\n') { | ||
277 | 273 | ||
278 | while (isspace(buffer[i])) | 274 | /* Two short lines in a row means new level */ |
279 | i++; | 275 | if(len < 3 && lastlen < 3) |
276 | current_info.max_level++; | ||
280 | 277 | ||
281 | current_info.max_level++; | 278 | lastlen = len; |
282 | } | 279 | } |
283 | } | ||
284 | 280 | ||
285 | if (buffer[i] == '\n' && buffer[i-1] != '\n') | 281 | DEBUGF("%d levels loaded\n", current_info.max_level); |
286 | lseek(fd, -1, SEEK_CUR); | ||
287 | |||
288 | } while (nread == sizeof(buffer)); | ||
289 | |||
290 | close(fd); | 282 | close(fd); |
291 | |||
292 | return 0; | 283 | return 0; |
293 | } | 284 | } |
294 | 285 | ||
@@ -297,73 +288,42 @@ static int get_level(char *level, int level_size) | |||
297 | int fd = 0, i = 0; | 288 | int fd = 0, i = 0; |
298 | int nread = 0; | 289 | int nread = 0; |
299 | int count = 0; | 290 | int count = 0; |
300 | int offset = 0; | 291 | int len, lastlen = 0; |
301 | int level_ct = 0; | 292 | int level_ct = 1; |
302 | unsigned char buffer[SOKOBAN_LEVEL_SIZE * 2]; | 293 | unsigned char buffer[SOKOBAN_LEVEL_SIZE * 2]; |
303 | bool level_found = false; | 294 | bool level_found = false; |
304 | int prevnewl=2; /* previous newlines in a row */ | ||
305 | |||
306 | /* Lets not reparse the full file if we can avoid it */ | ||
307 | if (current_info.loaded_level > current_info.level.level) | ||
308 | offset = 0; | ||
309 | 295 | ||
310 | /* open file */ | 296 | /* open file */ |
311 | if ((fd = open(LEVELS_FILE, O_RDONLY)) < 0) | 297 | if ((fd = open(LEVELS_FILE, O_RDONLY)) < 0) |
312 | return -1; | 298 | return -1; |
313 | 299 | ||
314 | /* go where we left off */ | 300 | /* Lets not reparse the full file if we can avoid it */ |
315 | offset = current_info.level_offset; | 301 | if (current_info.loaded_level < current_info.level.level) { |
316 | if(offset) | 302 | lseek(fd, current_info.level_offset, SEEK_SET); |
317 | if (lseek(fd, offset, SEEK_SET) < 0) { | 303 | level_ct = current_info.loaded_level; |
318 | close(fd); | 304 | } |
319 | return -1; | ||
320 | } | ||
321 | |||
322 | while (!level_found) { | ||
323 | nread = read(fd, buffer, sizeof(buffer)); | ||
324 | if (nread < SOKOBAN_LEVEL_SIZE) { | ||
325 | close(fd); | ||
326 | return -1; | ||
327 | } | ||
328 | 305 | ||
329 | /* we search for the first character that isn't a newline */ | 306 | if(current_info.level.level > 1) { |
330 | for (i = 0; i < nread; i++) { | 307 | while(!level_found) { |
331 | /* skip and count all newlines */ | 308 | len = read_line(fd, buffer, SOKOBAN_LEVEL_SIZE); |
332 | while((buffer[i] == '\n' || buffer[i] == '\r') && (i < nread)) { | 309 | if(len <= 0) { |
333 | prevnewl++; | 310 | close(fd); |
334 | i++; | 311 | return -1; |
335 | } | 312 | } |
336 | 313 | ||
337 | /* end of buffer? */ | 314 | /* Two short lines in a row means new level */ |
338 | if(i == nread) | 315 | if(len < 3 && lastlen < 3) { |
339 | break; | ||
340 | |||
341 | /* start of new level? */ | ||
342 | if((prevnewl>1) && (buffer[i] != '\n' && buffer[i] != '\r')) { | ||
343 | prevnewl=0; /* none now */ | ||
344 | level_ct++; | 316 | level_ct++; |
345 | 317 | if(level_ct == current_info.level.level) | |
346 | if (level_ct == current_info.level.level) { | 318 | level_found = true; |
347 | level_found = true; | ||
348 | offset += i; | ||
349 | break; | ||
350 | } | ||
351 | } | 319 | } |
352 | 320 | lastlen = len; | |
353 | /* skip all non-newlines */ | ||
354 | while((buffer[i] != '\n' && buffer[i] != '\r') && (i < nread)) | ||
355 | i++; | ||
356 | } | 321 | } |
357 | if(!level_found) | 322 | } |
358 | offset += nread; | ||
359 | } | ||
360 | |||
361 | if (!level_found) | ||
362 | return -1; | ||
363 | |||
364 | /* now seek back to the exact start position */ | ||
365 | lseek(fd, offset, SEEK_SET); | ||
366 | 323 | ||
324 | /* Remember the current offset */ | ||
325 | current_info.level_offset = lseek(fd, 0, SEEK_CUR); | ||
326 | |||
367 | /* read a full buffer chunk from here */ | 327 | /* read a full buffer chunk from here */ |
368 | nread = read(fd, buffer, sizeof(buffer)-1); | 328 | nread = read(fd, buffer, sizeof(buffer)-1); |
369 | if (nread < 0) | 329 | if (nread < 0) |
@@ -851,14 +811,15 @@ static bool sokoban_loop(void) | |||
851 | 811 | ||
852 | lcd_clear_display(); | 812 | lcd_clear_display(); |
853 | 813 | ||
854 | if (current_info.level.level == current_info.max_level) { | 814 | if (current_info.level.level > current_info.max_level) { |
855 | lcd_putsxy(10, 20, str(LANG_SOKOBAN_WIN)); | 815 | lcd_putsxy(10, 20, str(LANG_SOKOBAN_WIN)); |
856 | 816 | ||
857 | for (i = 0; i < 30000 ; i++) { | 817 | for (i = 0; i < 30000 ; i++) { |
858 | lcd_invertrect(0, 0, 111, 63); | 818 | lcd_invertrect(0, 0, 111, 63); |
859 | lcd_update(); | 819 | lcd_update(); |
860 | 820 | ||
861 | if (button_get(false)) | 821 | button = button_get(false); |
822 | if (button && ((button & BUTTON_REL) != BUTTON_REL)) | ||
862 | break; | 823 | break; |
863 | } | 824 | } |
864 | 825 | ||