diff options
Diffstat (limited to 'apps/plugins/sudoku/sudoku.c')
-rw-r--r-- | apps/plugins/sudoku/sudoku.c | 156 |
1 files changed, 117 insertions, 39 deletions
diff --git a/apps/plugins/sudoku/sudoku.c b/apps/plugins/sudoku/sudoku.c index fcf1566d65..9485f2de23 100644 --- a/apps/plugins/sudoku/sudoku.c +++ b/apps/plugins/sudoku/sudoku.c | |||
@@ -57,6 +57,7 @@ Example ".ss" file, and one with a saved state: | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | #include "plugin.h" | 59 | #include "plugin.h" |
60 | #include "lib/configfile.h" | ||
60 | #include "lib/oldmenuapi.h" | 61 | #include "lib/oldmenuapi.h" |
61 | 62 | ||
62 | #ifdef HAVE_LCD_BITMAP | 63 | #ifdef HAVE_LCD_BITMAP |
@@ -171,6 +172,28 @@ static const char default_game[9][9] = | |||
171 | 172 | ||
172 | #endif /* Layout */ | 173 | #endif /* Layout */ |
173 | 174 | ||
175 | #define CFGFILE_VERSION 0 /* Current config file version */ | ||
176 | #define CFGFILE_MINVERSION 0 /* Minimum config file version to accept */ | ||
177 | |||
178 | #ifdef HAVE_LCD_COLOR | ||
179 | /* settings */ | ||
180 | struct sudoku_config { | ||
181 | int number_display; | ||
182 | }; | ||
183 | struct sudoku_config sudcfg_disk = { 0 }; | ||
184 | struct sudoku_config sudcfg; | ||
185 | |||
186 | static const char cfg_filename[] = "sudoku.cfg"; | ||
187 | static char *number_str[2] = { "black", "coloured" }; | ||
188 | |||
189 | struct configdata disk_config[] = { | ||
190 | { TYPE_ENUM, 0, 2, &sudcfg_disk.number_display, "numbers", number_str, NULL }, | ||
191 | }; | ||
192 | #define NUMBER_TYPE (sudcfg.number_display*CELL_WIDTH) | ||
193 | #else | ||
194 | #define NUMBER_TYPE 0 | ||
195 | #endif | ||
196 | |||
174 | /* Size dependent build-time calculations */ | 197 | /* Size dependent build-time calculations */ |
175 | #ifdef SMALL_BOARD | 198 | #ifdef SMALL_BOARD |
176 | #define BOARD_WIDTH (CELL_WIDTH*9+10) | 199 | #define BOARD_WIDTH (CELL_WIDTH*9+10) |
@@ -767,20 +790,20 @@ void update_cell(struct sudoku_state_t* state, int r, int c) | |||
767 | */ | 790 | */ |
768 | 791 | ||
769 | if ((r==state->y) && (c==state->x)) { | 792 | if ((r==state->y) && (c==state->x)) { |
770 | rb->lcd_bitmap_part(sudoku_inverse,0, | 793 | rb->lcd_bitmap_part(sudoku_inverse,NUMBER_TYPE, |
771 | BITMAP_HEIGHT*(state->currentboard[r][c]-'0'), | 794 | BITMAP_HEIGHT*(state->currentboard[r][c]-'0'), |
772 | BITMAP_STRIDE, | 795 | BITMAP_STRIDE, |
773 | XOFS+cellxpos[c],YOFS+cellypos[r],CELL_WIDTH, | 796 | XOFS+cellxpos[c],YOFS+cellypos[r],CELL_WIDTH, |
774 | CELL_HEIGHT); | 797 | CELL_HEIGHT); |
775 | } else { | 798 | } else { |
776 | if (state->startboard[r][c]!='0') { | 799 | if (state->startboard[r][c]!='0') { |
777 | rb->lcd_bitmap_part(sudoku_start,0, | 800 | rb->lcd_bitmap_part(sudoku_start,NUMBER_TYPE, |
778 | BITMAP_HEIGHT*(state->startboard[r][c]-'0'), | 801 | BITMAP_HEIGHT*(state->startboard[r][c]-'0'), |
779 | BITMAP_STRIDE, | 802 | BITMAP_STRIDE, |
780 | XOFS+cellxpos[c],YOFS+cellypos[r], | 803 | XOFS+cellxpos[c],YOFS+cellypos[r], |
781 | CELL_WIDTH,CELL_HEIGHT); | 804 | CELL_WIDTH,CELL_HEIGHT); |
782 | } else { | 805 | } else { |
783 | rb->lcd_bitmap_part(sudoku_normal,0, | 806 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE, |
784 | BITMAP_HEIGHT*(state->currentboard[r][c]-'0'), | 807 | BITMAP_HEIGHT*(state->currentboard[r][c]-'0'), |
785 | BITMAP_STRIDE, | 808 | BITMAP_STRIDE, |
786 | XOFS+cellxpos[c],YOFS+cellypos[r], | 809 | XOFS+cellxpos[c],YOFS+cellypos[r], |
@@ -862,9 +885,9 @@ void display_board(struct sudoku_state_t* state) | |||
862 | YOFSSCRATCHPAD+CELL_HEIGHT+1); | 885 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
863 | #endif | 886 | #endif |
864 | if ((r>0) && state->possiblevals[state->y][state->x]&(1<<(r))) | 887 | if ((r>0) && state->possiblevals[state->y][state->x]&(1<<(r))) |
865 | rb->lcd_bitmap_part(sudoku_normal,0,BITMAP_HEIGHT*r,BITMAP_STRIDE, | 888 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
866 | XOFS+cellxpos[r-1],YOFSSCRATCHPAD+1, | 889 | BITMAP_STRIDE,XOFS+cellxpos[r-1], |
867 | CELL_WIDTH,CELL_HEIGHT); | 890 | YOFSSCRATCHPAD+1,CELL_WIDTH,CELL_HEIGHT); |
868 | } | 891 | } |
869 | rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH,YOFSSCRATCHPAD, | 892 | rb->lcd_vline(XOFS+cellxpos[8]+CELL_WIDTH,YOFSSCRATCHPAD, |
870 | YOFSSCRATCHPAD+CELL_HEIGHT+1); | 893 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
@@ -873,8 +896,8 @@ void display_board(struct sudoku_state_t* state) | |||
873 | YOFSSCRATCHPAD+CELL_HEIGHT+1); | 896 | YOFSSCRATCHPAD+CELL_HEIGHT+1); |
874 | #endif | 897 | #endif |
875 | if (state->possiblevals[state->y][state->x]&(1<<(r))) | 898 | if (state->possiblevals[state->y][state->x]&(1<<(r))) |
876 | rb->lcd_bitmap_part(sudoku_normal,0,BITMAP_HEIGHT*r,BITMAP_STRIDE, | 899 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
877 | XOFS+cellxpos[8],YOFSSCRATCHPAD+1, | 900 | BITMAP_STRIDE,XOFS+cellxpos[8],YOFSSCRATCHPAD+1, |
878 | CELL_WIDTH,CELL_HEIGHT); | 901 | CELL_WIDTH,CELL_HEIGHT); |
879 | #else /* Horizontal layout */ | 902 | #else /* Horizontal layout */ |
880 | rb->lcd_vline(XOFSSCRATCHPAD,YOFS,YOFS+BOARD_HEIGHT-1); | 903 | rb->lcd_vline(XOFSSCRATCHPAD,YOFS,YOFS+BOARD_HEIGHT-1); |
@@ -901,9 +924,9 @@ void display_board(struct sudoku_state_t* state) | |||
901 | YOFS+cellypos[r]-2); | 924 | YOFS+cellypos[r]-2); |
902 | #endif | 925 | #endif |
903 | if ((r>0) && state->possiblevals[state->y][state->x]&(1<<(r))) | 926 | if ((r>0) && state->possiblevals[state->y][state->x]&(1<<(r))) |
904 | rb->lcd_bitmap_part(sudoku_normal,0,BITMAP_HEIGHT*r,BITMAP_STRIDE, | 927 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
905 | XOFSSCRATCHPAD+1,YOFS+cellypos[r-1], | 928 | BITMAP_STRIDE,XOFSSCRATCHPAD+1, |
906 | CELL_WIDTH,CELL_HEIGHT); | 929 | YOFS+cellypos[r-1],CELL_WIDTH,CELL_HEIGHT); |
907 | } | 930 | } |
908 | rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1, | 931 | rb->lcd_hline(XOFSSCRATCHPAD,XOFSSCRATCHPAD+CELL_WIDTH+1, |
909 | YOFS+cellypos[8]+CELL_HEIGHT); | 932 | YOFS+cellypos[8]+CELL_HEIGHT); |
@@ -912,8 +935,8 @@ void display_board(struct sudoku_state_t* state) | |||
912 | YOFS+cellypos[8]+CELL_HEIGHT+1); | 935 | YOFS+cellypos[8]+CELL_HEIGHT+1); |
913 | #endif | 936 | #endif |
914 | if (state->possiblevals[state->y][state->x]&(1<<(r))) | 937 | if (state->possiblevals[state->y][state->x]&(1<<(r))) |
915 | rb->lcd_bitmap_part(sudoku_normal,0,BITMAP_HEIGHT*r,BITMAP_STRIDE, | 938 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE,BITMAP_HEIGHT*r, |
916 | XOFSSCRATCHPAD+1,YOFS+cellypos[8], | 939 | BITMAP_STRIDE,XOFSSCRATCHPAD+1,YOFS+cellypos[8], |
917 | CELL_WIDTH,CELL_HEIGHT); | 940 | CELL_WIDTH,CELL_HEIGHT); |
918 | #endif /* Layout */ | 941 | #endif /* Layout */ |
919 | #endif /* SUDOKU_BUTTON_POSSIBLE */ | 942 | #endif /* SUDOKU_BUTTON_POSSIBLE */ |
@@ -928,7 +951,7 @@ void display_board(struct sudoku_state_t* state) | |||
928 | */ | 951 | */ |
929 | 952 | ||
930 | if ((r==state->y) && (c==state->x)) { | 953 | if ((r==state->y) && (c==state->x)) { |
931 | rb->lcd_bitmap_part(sudoku_inverse,0, | 954 | rb->lcd_bitmap_part(sudoku_inverse,NUMBER_TYPE, |
932 | BITMAP_HEIGHT*(state->currentboard[r][c]- | 955 | BITMAP_HEIGHT*(state->currentboard[r][c]- |
933 | '0'), | 956 | '0'), |
934 | BITMAP_STRIDE, | 957 | BITMAP_STRIDE, |
@@ -936,14 +959,14 @@ void display_board(struct sudoku_state_t* state) | |||
936 | CELL_WIDTH,CELL_HEIGHT); | 959 | CELL_WIDTH,CELL_HEIGHT); |
937 | } else { | 960 | } else { |
938 | if (state->startboard[r][c]!='0') { | 961 | if (state->startboard[r][c]!='0') { |
939 | rb->lcd_bitmap_part(sudoku_start,0, | 962 | rb->lcd_bitmap_part(sudoku_start,NUMBER_TYPE, |
940 | BITMAP_HEIGHT*(state->startboard[r][c]- | 963 | BITMAP_HEIGHT*(state->startboard[r][c]- |
941 | '0'), | 964 | '0'), |
942 | BITMAP_STRIDE, | 965 | BITMAP_STRIDE, |
943 | XOFS+cellxpos[c],YOFS+cellypos[r], | 966 | XOFS+cellxpos[c],YOFS+cellypos[r], |
944 | CELL_WIDTH,CELL_HEIGHT); | 967 | CELL_WIDTH,CELL_HEIGHT); |
945 | } else { | 968 | } else { |
946 | rb->lcd_bitmap_part(sudoku_normal,0, | 969 | rb->lcd_bitmap_part(sudoku_normal,NUMBER_TYPE, |
947 | BITMAP_HEIGHT* | 970 | BITMAP_HEIGHT* |
948 | (state->currentboard[r][c]-'0'), | 971 | (state->currentboard[r][c]-'0'), |
949 | BITMAP_STRIDE, | 972 | BITMAP_STRIDE, |
@@ -992,20 +1015,50 @@ bool sudoku_generate(struct sudoku_state_t* state) | |||
992 | return res; | 1015 | return res; |
993 | } | 1016 | } |
994 | 1017 | ||
1018 | #ifdef HAVE_LCD_COLOR | ||
1019 | static bool numdisplay_setting(void) | ||
1020 | { | ||
1021 | static const struct opt_items names[] = { | ||
1022 | {"Black", -1}, | ||
1023 | {"Coloured", -1}, | ||
1024 | }; | ||
1025 | |||
1026 | return rb->set_option("Number Display", &sudcfg.number_display, INT, names, | ||
1027 | sizeof(names) / sizeof(names[0]), NULL); | ||
1028 | } | ||
1029 | #endif | ||
1030 | |||
1031 | enum { | ||
1032 | SM_AUDIO_PLAYBACK = 0, | ||
1033 | #ifdef HAVE_LCD_COLOR | ||
1034 | SM_NUMBER_DISPLAY, | ||
1035 | #endif | ||
1036 | SM_SAVE, | ||
1037 | SM_RELOAD, | ||
1038 | SM_CLEAR, | ||
1039 | SM_SOLVE, | ||
1040 | SM_GENERATE, | ||
1041 | SM_NEW, | ||
1042 | SM_QUIT, | ||
1043 | }; | ||
1044 | |||
995 | bool sudoku_menu(struct sudoku_state_t* state) | 1045 | bool sudoku_menu(struct sudoku_state_t* state) |
996 | { | 1046 | { |
997 | int m; | 1047 | int m; |
998 | int result; | 1048 | int result; |
999 | 1049 | ||
1000 | static const struct menu_item items[] = { | 1050 | static const struct menu_item items[] = { |
1001 | { "Audio Playback", NULL }, | 1051 | [SM_AUDIO_PLAYBACK] = { "Audio Playback", NULL }, |
1002 | { "Save", NULL }, | 1052 | #ifdef HAVE_LCD_COLOR |
1003 | { "Reload", NULL }, | 1053 | [SM_NUMBER_DISPLAY] = { "Number Display", NULL }, |
1004 | { "Clear", NULL }, | 1054 | #endif |
1005 | { "Solve", NULL }, | 1055 | [SM_SAVE] = { "Save", NULL }, |
1006 | { "Generate", NULL }, | 1056 | [SM_RELOAD] = { "Reload", NULL }, |
1007 | { "New", NULL }, | 1057 | [SM_CLEAR] = { "Clear", NULL }, |
1008 | { "Quit", NULL }, | 1058 | [SM_SOLVE] = { "Solve", NULL }, |
1059 | [SM_GENERATE] = { "Generate", NULL }, | ||
1060 | [SM_NEW] = { "New", NULL }, | ||
1061 | [SM_QUIT] = { "Quit", NULL }, | ||
1009 | }; | 1062 | }; |
1010 | 1063 | ||
1011 | m = menu_init(rb,items, sizeof(items) / sizeof(*items), | 1064 | m = menu_init(rb,items, sizeof(items) / sizeof(*items), |
@@ -1014,36 +1067,41 @@ bool sudoku_menu(struct sudoku_state_t* state) | |||
1014 | result=menu_show(m); | 1067 | result=menu_show(m); |
1015 | 1068 | ||
1016 | switch (result) { | 1069 | switch (result) { |
1017 | case 0: /* Audio playback */ | 1070 | case SM_AUDIO_PLAYBACK: |
1018 | playback_control(rb); | 1071 | playback_control(rb); |
1019 | break; | 1072 | break; |
1020 | 1073 | ||
1021 | case 1: /* Save state */ | 1074 | #ifdef HAVE_LCD_COLOR |
1075 | case SM_NUMBER_DISPLAY: | ||
1076 | numdisplay_setting(); | ||
1077 | break; | ||
1078 | #endif | ||
1079 | case SM_SAVE: | ||
1022 | save_sudoku(state); | 1080 | save_sudoku(state); |
1023 | break; | 1081 | break; |
1024 | 1082 | ||
1025 | case 2: /* Restore state */ | 1083 | case SM_RELOAD: |
1026 | restore_state(state); | 1084 | restore_state(state); |
1027 | break; | 1085 | break; |
1028 | 1086 | ||
1029 | case 3: /* Clear all */ | 1087 | case SM_CLEAR: |
1030 | clear_board(state); | 1088 | clear_board(state); |
1031 | break; | 1089 | break; |
1032 | 1090 | ||
1033 | case 4: /* Solve */ | 1091 | case SM_SOLVE: |
1034 | sudoku_solve(state); | 1092 | sudoku_solve(state); |
1035 | break; | 1093 | break; |
1036 | 1094 | ||
1037 | case 5: /* Generate Game */ | 1095 | case SM_GENERATE: |
1038 | sudoku_generate(state); | 1096 | sudoku_generate(state); |
1039 | break; | 1097 | break; |
1040 | 1098 | ||
1041 | case 6: /* Create a new game manually */ | 1099 | case SM_NEW: |
1042 | clear_state(state); | 1100 | clear_state(state); |
1043 | state->editmode=1; | 1101 | state->editmode=1; |
1044 | break; | 1102 | break; |
1045 | 1103 | ||
1046 | case 7: /* Quit */ | 1104 | case SM_QUIT: |
1047 | save_sudoku(state); | 1105 | save_sudoku(state); |
1048 | menu_exit(m); | 1106 | menu_exit(m); |
1049 | return true; | 1107 | return true; |
@@ -1126,12 +1184,21 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1126 | int button; | 1184 | int button; |
1127 | int lastbutton = BUTTON_NONE; | 1185 | int lastbutton = BUTTON_NONE; |
1128 | int res; | 1186 | int res; |
1187 | int rc = PLUGIN_OK; | ||
1129 | long ticks; | 1188 | long ticks; |
1130 | struct sudoku_state_t state; | 1189 | struct sudoku_state_t state; |
1131 | 1190 | ||
1132 | /* plugin init */ | 1191 | /* plugin init */ |
1133 | rb = api; | 1192 | rb = api; |
1134 | /* end of plugin init */ | 1193 | /* end of plugin init */ |
1194 | |||
1195 | #ifdef HAVE_LCD_COLOR | ||
1196 | configfile_init(rb); | ||
1197 | configfile_load(cfg_filename, disk_config, | ||
1198 | sizeof(disk_config) / sizeof(disk_config[0]), | ||
1199 | CFGFILE_MINVERSION); | ||
1200 | rb->memcpy(&sudcfg, &sudcfg_disk, sizeof(sudcfg)); /* copy to running config */ | ||
1201 | #endif | ||
1135 | 1202 | ||
1136 | #if LCD_DEPTH > 1 | 1203 | #if LCD_DEPTH > 1 |
1137 | rb->lcd_set_backdrop(NULL); | 1204 | rb->lcd_set_backdrop(NULL); |
@@ -1173,7 +1240,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1173 | rb->button_clear_queue(); | 1240 | rb->button_clear_queue(); |
1174 | } else { | 1241 | } else { |
1175 | save_sudoku(&state); | 1242 | save_sudoku(&state); |
1176 | exit=1; | 1243 | exit=true; |
1177 | } | 1244 | } |
1178 | break; | 1245 | break; |
1179 | #endif | 1246 | #endif |
@@ -1324,13 +1391,15 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1324 | if (state.editmode) { | 1391 | if (state.editmode) { |
1325 | res = sudoku_edit_menu(&state); | 1392 | res = sudoku_edit_menu(&state); |
1326 | if (res == MENU_ATTACHED_USB) { | 1393 | if (res == MENU_ATTACHED_USB) { |
1327 | return PLUGIN_USB_CONNECTED; | 1394 | rc = PLUGIN_USB_CONNECTED; |
1395 | exit = true; | ||
1328 | } else if (res == 1) { /* Quit */ | 1396 | } else if (res == 1) { /* Quit */ |
1329 | return PLUGIN_OK; | 1397 | exit = true; |
1330 | } | 1398 | } |
1331 | } else { | 1399 | } else { |
1332 | if (sudoku_menu(&state)) { | 1400 | if (sudoku_menu(&state)) { |
1333 | return PLUGIN_USB_CONNECTED; | 1401 | rc = PLUGIN_USB_CONNECTED; |
1402 | exit = true; | ||
1334 | } | 1403 | } |
1335 | } | 1404 | } |
1336 | } | 1405 | } |
@@ -1347,7 +1416,8 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1347 | default: | 1416 | default: |
1348 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { | 1417 | if (rb->default_event_handler(button) == SYS_USB_CONNECTED) { |
1349 | /* Quit if USB has been connected */ | 1418 | /* Quit if USB has been connected */ |
1350 | return PLUGIN_USB_CONNECTED; | 1419 | rc = PLUGIN_USB_CONNECTED; |
1420 | exit = true; | ||
1351 | } | 1421 | } |
1352 | break; | 1422 | break; |
1353 | } | 1423 | } |
@@ -1356,8 +1426,16 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
1356 | 1426 | ||
1357 | display_board(&state); | 1427 | display_board(&state); |
1358 | } | 1428 | } |
1359 | 1429 | #ifdef HAVE_LCD_COLOR | |
1360 | return PLUGIN_OK; | 1430 | if (rb->memcmp(&sudcfg, &sudcfg_disk, sizeof(sudcfg))) /* save settings if changed */ |
1431 | { | ||
1432 | rb->memcpy(&sudcfg_disk, &sudcfg, sizeof(sudcfg)); | ||
1433 | configfile_save(cfg_filename, disk_config, | ||
1434 | sizeof(disk_config) / sizeof(disk_config[0]), | ||
1435 | CFGFILE_VERSION); | ||
1436 | } | ||
1437 | #endif | ||
1438 | return rc; | ||
1361 | } | 1439 | } |
1362 | 1440 | ||
1363 | #endif | 1441 | #endif |