summaryrefslogtreecommitdiff
path: root/apps/plugins
diff options
context:
space:
mode:
authorAntoine Cellerier <dionoea@videolan.org>2007-09-24 22:19:59 +0000
committerAntoine Cellerier <dionoea@videolan.org>2007-09-24 22:19:59 +0000
commit62c1a87df40b0f21ddc9094d279ecf3869c578c1 (patch)
tree8f023fee5da40f232c2170e3515c757a4744ca21 /apps/plugins
parent04321574556bb1f665f3f84815cb43c5d992ec03 (diff)
downloadrockbox-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.c165
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/*****************************************************************************
21Solitaire by dionoea
22Graphics & Fix Bugs by Ben Basha
23
24use arrows to move the cursor
25use ON to select cards, move cards, reveal hidden cards, ...
26use PLAY to move a card from the remains' stack to the top of the cursor
27use F1 to put card under cursor on one of the 4 final stacks
28use F2 to un-select card if a card was selected, else draw 3 new cards
29 out of the remains' stack
30use 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
1049enum { SOLITAIRE_WIN, SOLITAIRE_QUIT, SOLITAIRE_USB }; 1035enum { 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 */
1106void 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
1115int open_save_file( int flags )
1116{
1117 char buf[MAX_PATH];
1118 get_save_filename( buf );
1119 return rb->open( buf, flags );
1120}
1121
1122void delete_save_file( void )
1123{
1124 char buf[MAX_PATH];
1125 rb->remove( buf );
1126}
1127
1128#ifdef write
1129# undef write
1130#endif
1131int 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
1144int 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
1154int 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
1180int 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
1121int solitaire( void ) 1222int 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 {