diff options
author | Antoine Cellerier <dionoea@videolan.org> | 2007-09-24 22:19:59 +0000 |
---|---|---|
committer | Antoine Cellerier <dionoea@videolan.org> | 2007-09-24 22:19:59 +0000 |
commit | 62c1a87df40b0f21ddc9094d279ecf3869c578c1 (patch) | |
tree | 8f023fee5da40f232c2170e3515c757a4744ca21 /apps/plugins | |
parent | 04321574556bb1f665f3f84815cb43c5d992ec03 (diff) | |
download | rockbox-62c1a87df40b0f21ddc9094d279ecf3869c578c1.tar.gz rockbox-62c1a87df40b0f21ddc9094d279ecf3869c578c1.zip |
Automatically save and load solitaire game. Close FS#7796. (Do we need a "quit without saving" menu entry?)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@14846 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/solitaire.c | 165 |
1 files changed, 140 insertions, 25 deletions
diff --git a/apps/plugins/solitaire.c b/apps/plugins/solitaire.c index ae1294cbc5..933a7226ca 100644 --- a/apps/plugins/solitaire.c +++ b/apps/plugins/solitaire.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2004-2006 Antoine Cellerier <dionoea @t videolan d.t org> | 10 | * Copyright (C) 2004-2007 Antoine Cellerier <dionoea @t videolan d.t org> |
11 | * | 11 | * |
12 | * All files in this archive are subject to the GNU General Public License. | 12 | * All files in this archive are subject to the GNU General Public License. |
13 | * See the file COPYING in the source tree root for full license agreement. | 13 | * See the file COPYING in the source tree root for full license agreement. |
@@ -17,20 +17,6 @@ | |||
17 | * | 17 | * |
18 | ****************************************************************************/ | 18 | ****************************************************************************/ |
19 | 19 | ||
20 | /***************************************************************************** | ||
21 | Solitaire by dionoea | ||
22 | Graphics & Fix Bugs by Ben Basha | ||
23 | |||
24 | use arrows to move the cursor | ||
25 | use ON to select cards, move cards, reveal hidden cards, ... | ||
26 | use PLAY to move a card from the remains' stack to the top of the cursor | ||
27 | use F1 to put card under cursor on one of the 4 final stacks | ||
28 | use F2 to un-select card if a card was selected, else draw 3 new cards | ||
29 | out of the remains' stack | ||
30 | use F3 to put card on top of the remains' stack on one of the 4 final stacks | ||
31 | |||
32 | *****************************************************************************/ | ||
33 | |||
34 | #include "plugin.h" | 20 | #include "plugin.h" |
35 | #include "playback_control.h" | 21 | #include "playback_control.h" |
36 | #include "configfile.h" | 22 | #include "configfile.h" |
@@ -1046,7 +1032,7 @@ enum move move_card( int dest_col, int src_card ) | |||
1046 | return MOVE_OK; | 1032 | return MOVE_OK; |
1047 | } | 1033 | } |
1048 | 1034 | ||
1049 | enum { SOLITAIRE_WIN, SOLITAIRE_QUIT, SOLITAIRE_USB }; | 1035 | enum { SOLITAIRE_WIN, SOLITAIRE_QUIT_NEW, SOLITAIRE_QUIT, SOLITAIRE_USB }; |
1050 | 1036 | ||
1051 | /** | 1037 | /** |
1052 | * Bouncing cards at the end of the game | 1038 | * Bouncing cards at the end of the game |
@@ -1115,10 +1101,125 @@ int bouncing_cards( void ) | |||
1115 | } | 1101 | } |
1116 | 1102 | ||
1117 | /** | 1103 | /** |
1104 | * Game save/load routines | ||
1105 | */ | ||
1106 | void get_save_filename( char *buf ) | ||
1107 | { | ||
1108 | char *s; | ||
1109 | rb->strcpy( buf, rb->plugin_get_current_filename() ); | ||
1110 | s = rb->strrchr( buf, '/' ) + 1; | ||
1111 | *s = '\0'; | ||
1112 | rb->strcat( s, "sol.save" ); | ||
1113 | } | ||
1114 | |||
1115 | int open_save_file( int flags ) | ||
1116 | { | ||
1117 | char buf[MAX_PATH]; | ||
1118 | get_save_filename( buf ); | ||
1119 | return rb->open( buf, flags ); | ||
1120 | } | ||
1121 | |||
1122 | void delete_save_file( void ) | ||
1123 | { | ||
1124 | char buf[MAX_PATH]; | ||
1125 | rb->remove( buf ); | ||
1126 | } | ||
1127 | |||
1128 | #ifdef write | ||
1129 | # undef write | ||
1130 | #endif | ||
1131 | int save_write( int fd, const void *buf, size_t count, int *checksum ) | ||
1132 | { | ||
1133 | size_t i; | ||
1134 | if( rb->PREFIX(write)( fd, buf, count ) < (ssize_t)count ) | ||
1135 | return 1; | ||
1136 | for( i = 0; i < count; i++ ) | ||
1137 | *checksum += (int)(((const char *)buf)[i]); | ||
1138 | return 0; | ||
1139 | } | ||
1140 | |||
1141 | #ifdef read | ||
1142 | # undef read | ||
1143 | #endif | ||
1144 | int save_read( int fd, void *buf, size_t count, int *checksum ) | ||
1145 | { | ||
1146 | size_t i; | ||
1147 | if( rb->PREFIX(read)( fd, buf, count ) < (ssize_t)count ) | ||
1148 | return 1; | ||
1149 | for( i = 0; i < count; i++ ) | ||
1150 | *checksum -= (int)(((const char *)buf)[i]); | ||
1151 | return 0; | ||
1152 | } | ||
1153 | |||
1154 | int save_game( void ) | ||
1155 | { | ||
1156 | int fd = open_save_file( O_CREAT|O_WRONLY|O_TRUNC ); | ||
1157 | int checksum = 42; | ||
1158 | if( fd < 0 ) | ||
1159 | return -1; | ||
1160 | if( save_write( fd, &cur_card, sizeof( int ), &checksum ) | ||
1161 | || save_write( fd, &cur_col, sizeof( int ), &checksum ) | ||
1162 | || save_write( fd, &sel_card, sizeof( int ), &checksum ) | ||
1163 | || save_write( fd, deck, NUM_CARDS * sizeof( card_t ), &checksum ) | ||
1164 | || save_write( fd, &rem, sizeof( int ), &checksum ) | ||
1165 | || save_write( fd, &cur_rem, sizeof( int ), &checksum ) | ||
1166 | || save_write( fd, &count_rem, sizeof( int ), &checksum ) | ||
1167 | || save_write( fd, &cards_per_draw, sizeof( int ), &checksum ) | ||
1168 | || save_write( fd, cols, COL_NUM * sizeof( int ), &checksum ) | ||
1169 | || save_write( fd, stacks, SUITS * sizeof( int ), &checksum ) | ||
1170 | || ( rb->PREFIX(write)( fd, &checksum, sizeof( int ) ) < (ssize_t)(sizeof( int ) ) ) ) | ||
1171 | { | ||
1172 | rb->close( fd ); | ||
1173 | rb->splash( 2*HZ, "Error while saving game. Aborting." ); | ||
1174 | return -2; | ||
1175 | } | ||
1176 | rb->close( fd ); | ||
1177 | return 0; | ||
1178 | } | ||
1179 | |||
1180 | int load_game( void ) | ||
1181 | { | ||
1182 | int fd = open_save_file( O_RDONLY ); | ||
1183 | int checksum; | ||
1184 | if( fd < 0 ) | ||
1185 | return -1; | ||
1186 | if( ( rb->PREFIX(lseek)( fd, -sizeof( int ), SEEK_END ) == -((ssize_t)sizeof( int ))-1 ) | ||
1187 | || ( rb->PREFIX(read)( fd, &checksum, sizeof( int ) ) < ((ssize_t)sizeof( int )) ) | ||
1188 | || ( rb->PREFIX(lseek)( fd, 0, SEEK_SET ) == -1 ) | ||
1189 | || save_read( fd, &cur_card, sizeof( int ), &checksum ) | ||
1190 | || save_read( fd, &cur_col, sizeof( int ), &checksum ) | ||
1191 | || save_read( fd, &sel_card, sizeof( int ), &checksum ) | ||
1192 | || save_read( fd, deck, NUM_CARDS * sizeof( card_t ), &checksum ) | ||
1193 | || save_read( fd, &rem, sizeof( int ), &checksum ) | ||
1194 | || save_read( fd, &cur_rem, sizeof( int ), &checksum ) | ||
1195 | || save_read( fd, &count_rem, sizeof( int ), &checksum ) | ||
1196 | || save_read( fd, &cards_per_draw, sizeof( int ), &checksum ) | ||
1197 | || save_read( fd, cols, COL_NUM * sizeof( int ), &checksum ) | ||
1198 | || save_read( fd, stacks, SUITS * sizeof( int ), &checksum ) ) | ||
1199 | { | ||
1200 | rb->close( fd ); | ||
1201 | rb->splash( 2*HZ, "Error while loading saved game. Aborting." ); | ||
1202 | delete_save_file(); | ||
1203 | return -2; | ||
1204 | } | ||
1205 | rb->close( fd ); | ||
1206 | if( checksum != 42 ) | ||
1207 | { | ||
1208 | rb->splash( 2*HZ, "Save file was corrupted. Aborting." ); | ||
1209 | delete_save_file(); | ||
1210 | return -3; | ||
1211 | } | ||
1212 | return 0; | ||
1213 | } | ||
1214 | |||
1215 | /** | ||
1118 | * The main game loop | 1216 | * The main game loop |
1217 | * | ||
1218 | * If skipmenu is defined to SOLITAIRE_QUIT, the menu will be skipped and | ||
1219 | * game will resume. | ||
1119 | */ | 1220 | */ |
1120 | 1221 | ||
1121 | int solitaire( void ) | 1222 | int solitaire( int skipmenu ) |
1122 | { | 1223 | { |
1123 | 1224 | ||
1124 | int i,j; | 1225 | int i,j; |
@@ -1127,15 +1228,18 @@ int solitaire( void ) | |||
1127 | int biggest_col_length; | 1228 | int biggest_col_length; |
1128 | 1229 | ||
1129 | rb->srand( *rb->current_tick ); | 1230 | rb->srand( *rb->current_tick ); |
1130 | switch( solitaire_menu(false) ) | 1231 | if( skipmenu != SOLITAIRE_QUIT ) |
1131 | { | 1232 | { |
1132 | case MENU_QUIT: | 1233 | switch( solitaire_menu(false) ) |
1133 | return SOLITAIRE_QUIT; | 1234 | { |
1235 | case MENU_QUIT: | ||
1236 | return SOLITAIRE_QUIT_NEW; | ||
1134 | 1237 | ||
1135 | case MENU_USB: | 1238 | case MENU_USB: |
1136 | return SOLITAIRE_USB; | 1239 | return SOLITAIRE_USB; |
1240 | } | ||
1241 | solitaire_init(); | ||
1137 | } | 1242 | } |
1138 | solitaire_init(); | ||
1139 | 1243 | ||
1140 | while( true ) | 1244 | while( true ) |
1141 | { | 1245 | { |
@@ -1600,7 +1704,7 @@ int solitaire( void ) | |||
1600 | 1704 | ||
1601 | case SYS_POWEROFF: | 1705 | case SYS_POWEROFF: |
1602 | return SOLITAIRE_QUIT; | 1706 | return SOLITAIRE_QUIT; |
1603 | 1707 | ||
1604 | default: | 1708 | default: |
1605 | if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) | 1709 | if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) |
1606 | return SOLITAIRE_USB; | 1710 | return SOLITAIRE_USB; |
@@ -1640,12 +1744,23 @@ enum plugin_status plugin_start( struct plugin_api* api, void* parameter ) | |||
1640 | sizeof(config) / sizeof(config[0]), CFGFILE_VERSION); | 1744 | sizeof(config) / sizeof(config[0]), CFGFILE_VERSION); |
1641 | rb->memcpy(&sol, &sol_disk, sizeof(sol)); /* copy to running config */ | 1745 | rb->memcpy(&sol, &sol_disk, sizeof(sol)); /* copy to running config */ |
1642 | 1746 | ||
1747 | if( load_game() == 0 ) | ||
1748 | result = SOLITAIRE_QUIT; | ||
1749 | else | ||
1750 | result = SOLITAIRE_WIN; | ||
1751 | |||
1643 | init_help(); | 1752 | init_help(); |
1644 | 1753 | ||
1645 | /* play the game :) | 1754 | /* play the game :) |
1646 | * Keep playing if a game was won (that means display the menu after | 1755 | * Keep playing if a game was won (that means display the menu after |
1647 | * winning instead of quiting) */ | 1756 | * winning instead of quiting) */ |
1648 | while( ( result = solitaire() ) == SOLITAIRE_WIN ); | 1757 | while( ( result = solitaire( result ) ) == SOLITAIRE_WIN ); |
1758 | |||
1759 | if( result != SOLITAIRE_QUIT_NEW ) | ||
1760 | save_game(); | ||
1761 | else | ||
1762 | /* XXX: Not sure if this is the best spot to delete the save file */ | ||
1763 | delete_save_file(); | ||
1649 | 1764 | ||
1650 | if (rb->memcmp(&sol, &sol_disk, sizeof(sol))) /* save settings if changed */ | 1765 | if (rb->memcmp(&sol, &sol_disk, sizeof(sol))) /* save settings if changed */ |
1651 | { | 1766 | { |