rev |
line source |
paulo@0
|
1 /* options code for LOCKJAW, an implementation of the Soviet Mind Game
|
paulo@0
|
2
|
paulo@0
|
3 Copyright (C) 2007-2008 Damian Yerrick <tepples+lj@spamcop.net>
|
paulo@0
|
4
|
paulo@0
|
5 This work is free software; you can redistribute it and/or modify
|
paulo@0
|
6 it under the terms of the GNU General Public License as published by
|
paulo@0
|
7 the Free Software Foundation; either version 2 of the License, or
|
paulo@0
|
8 (at your option) any later version.
|
paulo@0
|
9
|
paulo@0
|
10 This program is distributed in the hope that it will be useful,
|
paulo@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
paulo@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
paulo@0
|
13 GNU General Public License for more details.
|
paulo@0
|
14
|
paulo@0
|
15 You should have received a copy of the GNU General Public License
|
paulo@0
|
16 along with this program; if not, write to the Free Software
|
paulo@0
|
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
paulo@0
|
18
|
paulo@0
|
19 Original game concept and design by Alexey Pajitnov.
|
paulo@0
|
20 The Software is not sponsored or endorsed by Alexey Pajitnov, Elorg,
|
paulo@0
|
21 or The Tetris Company LLC.
|
paulo@0
|
22
|
paulo@0
|
23 */
|
paulo@0
|
24
|
paulo@0
|
25
|
paulo@0
|
26 #include <string.h>
|
paulo@0
|
27 #include <stdio.h>
|
paulo@0
|
28 #include "options.h"
|
paulo@0
|
29 #include "ljplay.h"
|
paulo@0
|
30 #include "ljlocale.h"
|
paulo@0
|
31
|
paulo@0
|
32 #ifdef HAS_FPU
|
paulo@0
|
33 #define siprintf sprintf
|
paulo@0
|
34 #define MIN_SHADOW 0
|
paulo@0
|
35 #define N_SHADOWS LJSHADOW_N_STYLES
|
paulo@0
|
36 #define FACTORY_SHADOW 0
|
paulo@0
|
37 #include "ljpc.h"
|
paulo@0
|
38 #else
|
paulo@0
|
39 #define MIN_SHADOW LJSHADOW_COLORED
|
paulo@0
|
40 #define N_SHADOWS (LJSHADOW_N_STYLES - 2)
|
paulo@0
|
41 #define FACTORY_SHADOW MIN_SHADOW
|
paulo@0
|
42 #endif
|
paulo@0
|
43
|
paulo@0
|
44 const FourCC optionsBoolNames[2] = {
|
paulo@0
|
45 {"Off"}, {"On"}
|
paulo@0
|
46 };
|
paulo@0
|
47
|
paulo@0
|
48 const FourCC gimmickNames[LJGM_N_GIMMICKS] = {
|
paulo@0
|
49 {"Mara"}, {"Line"}, {"Time"}, {"DrlA"}, {"Item"}, {"Keys"}
|
paulo@0
|
50 };
|
paulo@0
|
51
|
paulo@0
|
52 const FourCC optionsGarbageNames[LJGARBAGE_N_STYLES] = {
|
paulo@0
|
53 {"Off"}, {"Lv.1"}, {"Lv.2"}, {"Lv.3"}, {"Lv.4"},
|
paulo@0
|
54 {"HRD"}, {"DrlG"}, {"Zigz"}
|
paulo@0
|
55 };
|
paulo@0
|
56
|
paulo@0
|
57 const FourCC optionsScoringNames[LJSCORE_N_STYLES] = {
|
paulo@0
|
58 {"LJ"}, {"Fibo"}, {"HotL"}, {"TDSl"}, {"NESl"}, {"LJns"}
|
paulo@0
|
59 };
|
paulo@0
|
60
|
paulo@0
|
61 const FourCC optionsKickLimitNames[N_KICK_LIMITS] = {
|
paulo@0
|
62 {"Off"}, {"1"}, {"2"}, {"3"}, {"4"}, {"5"}, {"Inf"}
|
paulo@0
|
63 };
|
paulo@0
|
64
|
paulo@0
|
65 const FourCC optionsSpeedCurveNames[] = {
|
paulo@0
|
66 {"Zero"}, {"Rhy0"}, {"Exp"}, {"Rh20"},
|
paulo@0
|
67 {"TGM2"}, {"TAPD"}, {"TAD3"},
|
paulo@0
|
68 {"NESc"}, {"GBc"}, {"GBHL"}
|
paulo@0
|
69 };
|
paulo@0
|
70
|
paulo@0
|
71 static const FourCC optionsWindowedNames[2] = {
|
paulo@0
|
72 {"FulS"}, {"Wind"}
|
paulo@0
|
73 };
|
paulo@0
|
74
|
paulo@0
|
75 const FourCC optionsShadowNames[LJSHADOW_N_STYLES] = {
|
paulo@0
|
76 {"tl25"}, {"tl50"}, {"tlsC"}, {"tlsM"}, {"Off"}, {"invF"}
|
paulo@0
|
77 };
|
paulo@0
|
78
|
paulo@0
|
79 const FourCC optionsLockDelayNames[2] = {
|
paulo@0
|
80 {"SBSC"}, {"Inf"}
|
paulo@0
|
81 };
|
paulo@0
|
82
|
paulo@0
|
83 const FourCC optionsSBSCNames[2] = {
|
paulo@0
|
84 {"SBSC"}, {.i=0}
|
paulo@0
|
85 };
|
paulo@0
|
86
|
paulo@0
|
87 const FourCC optionsTspinNames[] = {
|
paulo@0
|
88 {"Off"}, {"Imob"}, {"CrnT"}, {"WKT"}
|
paulo@0
|
89 };
|
paulo@0
|
90
|
paulo@0
|
91 const FourCC optionsLockdownNames[] = {
|
paulo@0
|
92 {"OLD"}, {"EntR"}, {"StpR"}, {"MovR"}
|
paulo@0
|
93 };
|
paulo@0
|
94
|
paulo@0
|
95 const FourCC optionsHoldStyleNames[] = {
|
paulo@0
|
96 {"Off"}, {"HldE"}, {"HldR"}, {"HldN"}
|
paulo@0
|
97 };
|
paulo@0
|
98
|
paulo@0
|
99 const FourCC optionsDropScoringNames[LJDROP_N_STYLES] = {
|
paulo@0
|
100 {"None"}, {"ConD"}, {"S1H1"}, {"S1H2"}
|
paulo@0
|
101 };
|
paulo@0
|
102
|
paulo@0
|
103 const FourCC optionsGravNames[] = {
|
paulo@0
|
104 {"Naiv"}, {"Stky"}, {"byCo"}, {"Casc"}
|
paulo@0
|
105 };
|
paulo@0
|
106
|
paulo@0
|
107 const FourCC optionsPieceSetNames[LJRAND_N_PIECE_SETS] = {
|
paulo@0
|
108 {"IJLO"},
|
paulo@0
|
109 {"JLOT"},
|
paulo@0
|
110 {"SZSZ"},
|
paulo@0
|
111 {"IIII"},
|
paulo@0
|
112 {"AllP"},
|
paulo@0
|
113 {"TTTT"}
|
paulo@0
|
114 };
|
paulo@0
|
115
|
paulo@0
|
116 const FourCC optionsRandNames[LJRAND_N_RANDS] = {
|
paulo@0
|
117 {"Unif"},
|
paulo@0
|
118 {"Bag"},
|
paulo@0
|
119 {"Bag+"},
|
paulo@0
|
120 {"Bag2"},
|
paulo@0
|
121 {"Hist"},
|
paulo@0
|
122 {"His6"}
|
paulo@0
|
123 };
|
paulo@0
|
124
|
paulo@0
|
125 const FourCC optionsLineDelayNames[] = {
|
paulo@0
|
126 {"SBSC"}, {.i=0}
|
paulo@0
|
127 };
|
paulo@0
|
128
|
paulo@0
|
129 const FourCC optionsZangiNames[] = {
|
paulo@0
|
130 {"Slid"}, {"Lock"}, {"LocU"}
|
paulo@0
|
131 };
|
paulo@0
|
132
|
paulo@0
|
133 const FourCC optionsGluingNames[] = {
|
paulo@0
|
134 {"Off"}, {"Squ"}, {"Stky"}, {"byCo"}
|
paulo@0
|
135 };
|
paulo@0
|
136
|
paulo@0
|
137 const FourCC optionsRotNames[N_ROTATION_SYSTEMS] = {
|
paulo@0
|
138 {"SRS"}, {"Sega"}, {"ARS"}, {"Tngn"},
|
paulo@0
|
139 {"NRSR"}, {"NRSL"}, {"TOD4"}, {"TDX"}
|
paulo@0
|
140 };
|
paulo@0
|
141
|
paulo@0
|
142
|
paulo@0
|
143 const OptionsLine commonOptionsMenu[] = {
|
paulo@0
|
144 {{"gimm"}, gimmickNames,
|
paulo@0
|
145 0, LJGM_N_GIMMICKS, 0 },
|
paulo@0
|
146 {{"pfw"}, NULL,
|
paulo@0
|
147 4, LJ_PF_WID - 4 + 1, 10 },
|
paulo@0
|
148 {{"pfh"}, NULL,
|
paulo@0
|
149 8, LJ_PF_VIS_HT - 8 + 1, LJ_PF_VIS_HT },
|
paulo@0
|
150 {{"vzsp"}, optionsBoolNames,
|
paulo@0
|
151 0, 2, 1 },
|
paulo@0
|
152 {{"spdc"}, optionsSpeedCurveNames,
|
paulo@0
|
153 0, LJSPD_N_CURVES, LJSPD_EXP },
|
paulo@0
|
154 {{"are"}, NULL,
|
paulo@0
|
155 0, 121, 0, OPTSTYLE_FRAMES },
|
paulo@0
|
156 {{"piec"}, optionsPieceSetNames,
|
paulo@0
|
157 0, LJRAND_N_PIECE_SETS, LJRAND_4BLK },
|
paulo@0
|
158 {{"rand"}, optionsRandNames,
|
paulo@0
|
159 0, LJRAND_N_RANDS, LJRAND_BAG },
|
paulo@0
|
160
|
paulo@0
|
161 {{"hold"}, optionsHoldStyleNames,
|
paulo@0
|
162 0, LJHOLD_N_STYLES, LJHOLD_EMPTY },
|
paulo@0
|
163 {{"rots"}, optionsRotNames,
|
paulo@0
|
164 0, N_ROTATION_SYSTEMS, 0 },
|
paulo@0
|
165 {{"upkl"}, optionsKickLimitNames,
|
paulo@0
|
166 0, N_KICK_LIMITS, N_KICK_LIMITS - 1 },
|
paulo@0
|
167 {{"lock"}, optionsLockdownNames,
|
paulo@0
|
168 0, LJLOCK_N_STYLES, LJLOCK_MOVE },
|
paulo@0
|
169 {{"sldt"}, optionsLockDelayNames,
|
paulo@0
|
170 0, 129, 0, OPTSTYLE_FRAMES },
|
paulo@0
|
171 {{"deep"}, optionsBoolNames,
|
paulo@0
|
172 0, 2, 0 },
|
paulo@0
|
173
|
paulo@0
|
174 {{"clrd"}, optionsSBSCNames,
|
paulo@0
|
175 0, 121, 0, OPTSTYLE_FRAMES },
|
paulo@0
|
176 {{"grav"}, optionsGravNames,
|
paulo@0
|
177 0, LJGRAV_N_ALGOS, LJGRAV_NAIVE },
|
paulo@0
|
178 {{"glue"}, optionsGluingNames,
|
paulo@0
|
179 0, LJGLUING_N_STYLES, LJGLUING_NONE },
|
paulo@0
|
180 {{"lsco"}, optionsScoringNames,
|
paulo@0
|
181 0, LJSCORE_N_STYLES },
|
paulo@0
|
182 {{"dsco"}, optionsDropScoringNames,
|
paulo@0
|
183 0, LJDROP_N_STYLES, 0 },
|
paulo@0
|
184 {{"tspn"}, optionsTspinNames,
|
paulo@0
|
185 0, LJTS_N_ALGOS, LJTS_TDS },
|
paulo@0
|
186 {{"garb"}, optionsGarbageNames,
|
paulo@0
|
187 0, LJGARBAGE_N_STYLES, 0 },
|
paulo@0
|
188
|
paulo@0
|
189 {{"dasd"}, NULL,
|
paulo@0
|
190 1, 120, 10, OPTSTYLE_FRAMES },
|
paulo@0
|
191 {{"dass"}, NULL,
|
paulo@0
|
192 0, 10, 1, OPTSTYLE_FRAC_G },
|
paulo@0
|
193 {{"idas"}, optionsBoolNames,
|
paulo@0
|
194 0, 2, 1 },
|
paulo@0
|
195 {{"irs"}, optionsBoolNames,
|
paulo@0
|
196 0, 2, 1 },
|
paulo@0
|
197 {{"8way"}, optionsBoolNames,
|
paulo@0
|
198 0, 2, 0 },
|
paulo@0
|
199
|
paulo@0
|
200 {{"sfds"}, NULL,
|
paulo@0
|
201 1, 3, 1, OPTSTYLE_FRAC_G },
|
paulo@0
|
202 {{"sfdl"}, optionsZangiNames,
|
paulo@0
|
203 0, LJZANGI_N_STYLES, LJZANGI_SLIDE },
|
paulo@0
|
204 {{"hrdl"}, optionsZangiNames,
|
paulo@0
|
205 0, LJZANGI_N_STYLES, LJZANGI_LOCK },
|
paulo@0
|
206
|
paulo@0
|
207 {{"tls"}, optionsShadowNames + MIN_SHADOW,
|
paulo@0
|
208 MIN_SHADOW, N_SHADOWS, FACTORY_SHADOW },
|
paulo@0
|
209 {{"invs"}, optionsBoolNames,
|
paulo@0
|
210 0, 2, 0 },
|
paulo@0
|
211 {{"next"}, NULL,
|
paulo@0
|
212 0, LJ_NEXT_PIECES + 1, 6 },
|
paulo@0
|
213 {{"srph"}, optionsBoolNames,
|
paulo@0
|
214 0, 2, 1 },
|
paulo@0
|
215
|
paulo@0
|
216 #ifdef HAS_FPU
|
paulo@0
|
217 {{"inpv"}, NULL,
|
paulo@0
|
218 0, LJ_NEXT_PIECES + 1, 0 },
|
paulo@0
|
219 {{"mblr"}, optionsBoolNames,
|
paulo@0
|
220 0, 2, 1 },
|
paulo@0
|
221 {{"lidp"}, optionsBoolNames,
|
paulo@0
|
222 0, 2, 1 },
|
paulo@0
|
223 {{"rec"}, optionsBoolNames,
|
paulo@0
|
224 0, 2, 0 },
|
paulo@0
|
225 {{"wndw"}, optionsWindowedNames,
|
paulo@0
|
226 0, 2, 1 }
|
paulo@0
|
227 #endif
|
paulo@0
|
228 };
|
paulo@0
|
229
|
paulo@0
|
230 const OptionsPage optionsPages[] = {
|
paulo@0
|
231 {OPTIONS_GIMMICK, "Game"},
|
paulo@0
|
232 {OPTIONS_WIDTH, "Rules: Well"},
|
paulo@0
|
233 {OPTIONS_HOLD_PIECE, "Rules: Movement"},
|
paulo@0
|
234 {OPTIONS_LINE_DELAY, "Rules: Line clear"},
|
paulo@0
|
235 {OPTIONS_SIDEWAYS_DELAY, "Control: Movement"},
|
paulo@0
|
236 {OPTIONS_SOFT_DROP_SPEED, "Control: Drop"},
|
paulo@0
|
237 {OPTIONS_SHADOW, "Display"},
|
paulo@0
|
238 #ifdef HAS_FPU
|
paulo@0
|
239 {OPTIONS_MENU_LEN, "PC"},
|
paulo@0
|
240 {PC_OPTIONS_MENU_LEN, NULL}
|
paulo@0
|
241 #else
|
paulo@0
|
242 {OPTIONS_MENU_LEN, NULL}
|
paulo@0
|
243 #endif
|
paulo@0
|
244 };
|
paulo@0
|
245
|
paulo@0
|
246 void setOptionsValueToFourCC(char *dst, FourCC f) {
|
paulo@0
|
247 const char *valueName = ljGetFourCCName(f);
|
paulo@0
|
248 if (valueName) {
|
paulo@0
|
249 strncpy(dst,
|
paulo@0
|
250 valueName,
|
paulo@0
|
251 OPTIONS_VALUE_LEN - 1);
|
paulo@0
|
252 dst[OPTIONS_VALUE_LEN - 1] = 0;
|
paulo@0
|
253 } else {
|
paulo@0
|
254 strncpy(dst, f.c, 4);
|
paulo@0
|
255 dst[4] = 0;
|
paulo@0
|
256 }
|
paulo@0
|
257 }
|
paulo@0
|
258
|
paulo@0
|
259 struct DisabledOption {
|
paulo@0
|
260 unsigned char name;
|
paulo@0
|
261 unsigned char value;
|
paulo@0
|
262 unsigned char name2;
|
paulo@0
|
263 char reason[45];
|
paulo@0
|
264 };
|
paulo@0
|
265
|
paulo@0
|
266 /*
|
paulo@0
|
267 Semantics:
|
paulo@0
|
268 If option name is set to value,
|
paulo@0
|
269 then gray out option name2 and draw its value as reason.
|
paulo@0
|
270 */
|
paulo@0
|
271 #define N_DISABLED_OPTIONS 12
|
paulo@0
|
272 const struct DisabledOption disabledOptions[N_DISABLED_OPTIONS] = {
|
paulo@0
|
273 { OPTIONS_LOCKDOWN, LJLOCK_NOW,
|
paulo@0
|
274 OPTIONS_SOFT_DROP, "Lockdown is immediate" },
|
paulo@0
|
275 { OPTIONS_LOCKDOWN, LJLOCK_NOW,
|
paulo@0
|
276 OPTIONS_HARD_DROP, "Lockdown is immediate" },
|
paulo@0
|
277 { OPTIONS_LOCKDOWN, LJLOCK_NOW,
|
paulo@0
|
278 OPTIONS_LOCK_DELAY, "Lockdown is immediate" },
|
paulo@0
|
279 { OPTIONS_LOCK_DELAY, 128,
|
paulo@0
|
280 OPTIONS_LOCKDOWN, "Lockdown is manual" },
|
paulo@0
|
281 { OPTIONS_SPEED_CURVE, LJSPD_DEATH,
|
paulo@0
|
282 OPTIONS_SOFT_DROP_SPEED,"Death: pieces land instantly" },
|
paulo@0
|
283 { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM,
|
paulo@0
|
284 OPTIONS_SOFT_DROP_SPEED,"Rhythm: pieces land instantly" },
|
paulo@0
|
285 { OPTIONS_SPEED_CURVE, LJSPD_DEATH,
|
paulo@0
|
286 OPTIONS_SMOOTH_GRAVITY, "Death: pieces land instantly" },
|
paulo@0
|
287 { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM,
|
paulo@0
|
288 OPTIONS_SMOOTH_GRAVITY, "Rhythm: pieces land instantly" },
|
paulo@0
|
289 { OPTIONS_SPEED_CURVE, LJSPD_DEATH,
|
paulo@0
|
290 OPTIONS_SOFT_DROP, "Death: pieces land instantly" },
|
paulo@0
|
291 { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM,
|
paulo@0
|
292 OPTIONS_SOFT_DROP, "Rhythm: pieces land instantly" },
|
paulo@0
|
293 { OPTIONS_SPEED_CURVE, LJSPD_DEATH,
|
paulo@0
|
294 OPTIONS_HARD_DROP, "Death: pieces land instantly" },
|
paulo@0
|
295 { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM,
|
paulo@0
|
296 OPTIONS_HARD_DROP, "Rhythm: pieces land instantly" },
|
paulo@0
|
297 };
|
paulo@0
|
298
|
paulo@0
|
299 const char *isDisabledOption(const unsigned char *prefs, int y) {
|
paulo@0
|
300 for (int i = 0; i < N_DISABLED_OPTIONS; ++i) {
|
paulo@0
|
301 if (y == disabledOptions[i].name2) {
|
paulo@0
|
302 int name = disabledOptions[i].name;
|
paulo@0
|
303 int value = disabledOptions[i].value;
|
paulo@0
|
304
|
paulo@0
|
305 if (prefs[name] == value) {
|
paulo@0
|
306 return disabledOptions[i].reason;
|
paulo@0
|
307 }
|
paulo@0
|
308 }
|
paulo@0
|
309 }
|
paulo@0
|
310 return NULL;
|
paulo@0
|
311 }
|
paulo@0
|
312
|
paulo@0
|
313
|
paulo@0
|
314 const char *getOptionsValueStr(char *dst, int line, int value) {
|
paulo@0
|
315 const OptionsLine *l = &(commonOptionsMenu[line]);
|
paulo@0
|
316 FourCC f = {.i = 0};
|
paulo@0
|
317 const char *desc = NULL;
|
paulo@0
|
318
|
paulo@0
|
319 switch (l->style) {
|
paulo@0
|
320 case OPTSTYLE_DEFAULT:
|
paulo@0
|
321 if (l->valueNames) {
|
paulo@0
|
322 f = l->valueNames[value - l->minValue];
|
paulo@0
|
323 } else {
|
paulo@0
|
324 siprintf(dst, "%d", value);
|
paulo@0
|
325 }
|
paulo@0
|
326 break;
|
paulo@0
|
327
|
paulo@0
|
328 case OPTSTYLE_FRAMES:
|
paulo@0
|
329 if (l->valueNames
|
paulo@0
|
330 && value == l->minValue
|
paulo@0
|
331 && l->valueNames[0].i) {
|
paulo@0
|
332
|
paulo@0
|
333 // override first with name 0
|
paulo@0
|
334 f = l->valueNames[0];
|
paulo@0
|
335 } else if (l->valueNames
|
paulo@0
|
336 && value == l->minValue
|
paulo@0
|
337 + l->nValues - 1
|
paulo@0
|
338 && l->valueNames[1].i) {
|
paulo@0
|
339
|
paulo@0
|
340 // override second with name 1
|
paulo@0
|
341 f = l->valueNames[1];
|
paulo@0
|
342 } else {
|
paulo@0
|
343 if (value >= 60) {
|
paulo@0
|
344 int ds = value / 6;
|
paulo@0
|
345 int s = ds / 10;
|
paulo@0
|
346 ds -= s * 10;
|
paulo@0
|
347 siprintf(dst, "%d/60 s (%d.%d s)", value, s, ds);
|
paulo@0
|
348 } else {
|
paulo@0
|
349 int ms = value * 50 / 3;
|
paulo@0
|
350 siprintf(dst, "%d/60 s (%d ms)", value, ms);
|
paulo@0
|
351 }
|
paulo@0
|
352 } break;
|
paulo@0
|
353
|
paulo@0
|
354 case OPTSTYLE_FRAC_G:
|
paulo@0
|
355 if (value > 6) {
|
paulo@0
|
356 int dHz = 600 / value;
|
paulo@0
|
357 int Hz = dHz / 10;
|
paulo@0
|
358 dHz -= Hz * 10;
|
paulo@0
|
359 siprintf(dst, "1/%dG (%d.%d Hz)", value, Hz, dHz);
|
paulo@0
|
360 } else if (value > 0) {
|
paulo@0
|
361 if (value > 1) {
|
paulo@0
|
362 dst[0] = '1';
|
paulo@0
|
363 dst[1] = '/';
|
paulo@0
|
364 dst += 2;
|
paulo@0
|
365 }
|
paulo@0
|
366 siprintf(dst, "%dG (%d Hz)", value, 60 / value);
|
paulo@0
|
367 } else {
|
paulo@0
|
368 strcpy(dst, "Instant");
|
paulo@0
|
369 }
|
paulo@0
|
370 break;
|
paulo@0
|
371
|
paulo@0
|
372 default:
|
paulo@0
|
373 strncpy(dst, "Unknown option style.", OPTIONS_VALUE_LEN - 1);
|
paulo@0
|
374 dst[OPTIONS_VALUE_LEN - 1] = 0;
|
paulo@0
|
375 break;
|
paulo@0
|
376 }
|
paulo@0
|
377
|
paulo@0
|
378 /* If we have a fourCC, use it. */
|
paulo@0
|
379 if (f.i != 0) {
|
paulo@0
|
380 setOptionsValueToFourCC(dst, f);
|
paulo@0
|
381 desc = ljGetFourCCDesc(f);
|
paulo@0
|
382 }
|
paulo@0
|
383 return desc;
|
paulo@0
|
384 }
|
paulo@0
|
385
|
paulo@0
|
386 void unpackCommonOptions(LJView *v, const unsigned char *prefs) {
|
paulo@0
|
387 if (prefs[OPTIONS_GIMMICK] < 255)
|
paulo@0
|
388 v->field->gimmick = prefs[OPTIONS_GIMMICK];
|
paulo@0
|
389 if (prefs[OPTIONS_WIDTH] < 255) {
|
paulo@0
|
390 int width = prefs[OPTIONS_WIDTH];
|
paulo@0
|
391 v->field->leftWall = (LJ_PF_WID - width) / 2;
|
paulo@0
|
392 v->field->rightWall = v->field->leftWall + width;
|
paulo@0
|
393 }
|
paulo@0
|
394 if (prefs[OPTIONS_HEIGHT] < 255)
|
paulo@0
|
395 v->field->ceiling = prefs[OPTIONS_HEIGHT];
|
paulo@0
|
396 if (prefs[OPTIONS_ENTER_ABOVE] < 255)
|
paulo@0
|
397 v->field->enterAbove = prefs[OPTIONS_ENTER_ABOVE];
|
paulo@0
|
398 if (prefs[OPTIONS_SPEED_CURVE] < 255)
|
paulo@0
|
399 v->field->speedState.curve = prefs[OPTIONS_SPEED_CURVE];
|
paulo@0
|
400 if (prefs[OPTIONS_ENTRY_DELAY] < 255)
|
paulo@0
|
401 v->field->areStyle = prefs[OPTIONS_ENTRY_DELAY];
|
paulo@0
|
402 if (prefs[OPTIONS_PIECE_SET] < 255)
|
paulo@0
|
403 v->field->pieceSet = prefs[OPTIONS_PIECE_SET];
|
paulo@0
|
404 if (prefs[OPTIONS_RANDOMIZER] < 255)
|
paulo@0
|
405 v->field->randomizer = prefs[OPTIONS_RANDOMIZER];
|
paulo@0
|
406
|
paulo@0
|
407 if (prefs[OPTIONS_ROTATION_SYSTEM] < 255)
|
paulo@0
|
408 v->field->rotationSystem = prefs[OPTIONS_ROTATION_SYSTEM];
|
paulo@0
|
409 if (prefs[OPTIONS_FLOOR_KICKS] < 255)
|
paulo@0
|
410 v->field->maxUpwardKicks = prefs[OPTIONS_FLOOR_KICKS] == N_KICK_LIMITS - 1
|
paulo@0
|
411 ? 128
|
paulo@0
|
412 : prefs[OPTIONS_FLOOR_KICKS];
|
paulo@0
|
413 if (prefs[OPTIONS_HOLD_PIECE] < 255)
|
paulo@0
|
414 v->field->holdStyle = prefs[OPTIONS_HOLD_PIECE];
|
paulo@0
|
415 if (prefs[OPTIONS_LOCKDOWN] < 255)
|
paulo@0
|
416 v->field->lockReset = prefs[OPTIONS_LOCKDOWN];
|
paulo@0
|
417 if (prefs[OPTIONS_LOCK_DELAY] < 255)
|
paulo@0
|
418 v->field->setLockDelay = prefs[OPTIONS_LOCK_DELAY];
|
paulo@0
|
419 if (prefs[OPTIONS_BOTTOM_BLOCKS] < 255)
|
paulo@0
|
420 v->field->bottomBlocks = prefs[OPTIONS_BOTTOM_BLOCKS];
|
paulo@0
|
421
|
paulo@0
|
422 if (prefs[OPTIONS_LINE_DELAY] < 255)
|
paulo@0
|
423 v->field->setLineDelay = prefs[OPTIONS_LINE_DELAY];
|
paulo@0
|
424 if (prefs[OPTIONS_T_SPIN] < 255)
|
paulo@0
|
425 v->field->tSpinAlgo = prefs[OPTIONS_T_SPIN];
|
paulo@0
|
426 if (prefs[OPTIONS_CLEAR_GRAVITY] < 255)
|
paulo@0
|
427 v->field->clearGravity = prefs[OPTIONS_CLEAR_GRAVITY];
|
paulo@0
|
428 if (prefs[OPTIONS_GLUING] < 255)
|
paulo@0
|
429 v->field->gluing = prefs[OPTIONS_GLUING];
|
paulo@0
|
430 if (prefs[OPTIONS_SCORING] < 255)
|
paulo@0
|
431 v->field->scoreStyle = prefs[OPTIONS_SCORING];
|
paulo@0
|
432 if (prefs[OPTIONS_DROP_SCORING] < 255)
|
paulo@0
|
433 v->field->dropScoreStyle = prefs[OPTIONS_DROP_SCORING];
|
paulo@0
|
434 if (prefs[OPTIONS_GARBAGE] < 255)
|
paulo@0
|
435 v->field->garbageStyle = prefs[OPTIONS_GARBAGE];
|
paulo@0
|
436
|
paulo@0
|
437 if (prefs[OPTIONS_SIDEWAYS_DELAY] < 255)
|
paulo@0
|
438 v->control->dasDelay = prefs[OPTIONS_SIDEWAYS_DELAY];
|
paulo@0
|
439 if (prefs[OPTIONS_SIDEWAYS_SPEED] < 255)
|
paulo@0
|
440 v->control->dasSpeed = prefs[OPTIONS_SIDEWAYS_SPEED];
|
paulo@0
|
441 if (v->control->dasDelay < v->control->dasSpeed) {
|
paulo@0
|
442 v->control->dasDelay = v->control->dasSpeed;
|
paulo@0
|
443 }
|
paulo@0
|
444 if (prefs[OPTIONS_INITIAL_SIDEWAYS] < 255)
|
paulo@0
|
445 v->control->initialDAS = prefs[OPTIONS_INITIAL_SIDEWAYS];
|
paulo@0
|
446 if (prefs[OPTIONS_IRS] < 255)
|
paulo@0
|
447 v->control->initialRotate = prefs[OPTIONS_IRS];
|
paulo@0
|
448 if (prefs[OPTIONS_DIAGONAL_MOTION] < 255)
|
paulo@0
|
449 v->control->allowDiagonals = prefs[OPTIONS_DIAGONAL_MOTION];
|
paulo@0
|
450 if (prefs[OPTIONS_SOFT_DROP_SPEED] < 255)
|
paulo@0
|
451 v->control->softDropSpeed = prefs[OPTIONS_SOFT_DROP_SPEED] - 1;
|
paulo@0
|
452 if (prefs[OPTIONS_SOFT_DROP] < 255)
|
paulo@0
|
453 v->control->softDropLock = prefs[OPTIONS_SOFT_DROP];
|
paulo@0
|
454 if (prefs[OPTIONS_HARD_DROP] < 255)
|
paulo@0
|
455 v->control->hardDropLock = prefs[OPTIONS_HARD_DROP];
|
paulo@0
|
456
|
paulo@0
|
457 if (prefs[OPTIONS_SHADOW] < 255)
|
paulo@0
|
458 v->hideShadow = prefs[OPTIONS_SHADOW];
|
paulo@0
|
459 if (prefs[OPTIONS_HIDE_PF] < 255)
|
paulo@0
|
460 v->hidePF = prefs[OPTIONS_HIDE_PF];
|
paulo@0
|
461 if (prefs[OPTIONS_NEXT_PIECES] < 255)
|
paulo@0
|
462 v->nextPieces = prefs[OPTIONS_NEXT_PIECES];
|
paulo@0
|
463 if (prefs[OPTIONS_SMOOTH_GRAVITY] < 255)
|
paulo@0
|
464 v->smoothGravity = prefs[OPTIONS_SMOOTH_GRAVITY];
|
paulo@0
|
465 }
|
paulo@0
|
466
|
paulo@0
|
467 void initOptions(unsigned char *prefs) {
|
paulo@0
|
468 for (int i = 0; i < OPTIONS_MENU_LEN; ++i) {
|
paulo@0
|
469 prefs[i] = commonOptionsMenu[i].startValue;
|
paulo@0
|
470 }
|
paulo@0
|
471 }
|
paulo@0
|
472
|
paulo@0
|
473 LJBits menuReadPad(void);
|
paulo@0
|
474 void vsync(void);
|
paulo@0
|
475
|
paulo@0
|
476 void options(LJView *v, unsigned char *prefs) {
|
paulo@0
|
477 int page = 0, y = 0;
|
paulo@0
|
478 int redraw = 2;
|
paulo@0
|
479 int done = 0;
|
paulo@0
|
480 LJBits lastKeys = ~0;
|
paulo@0
|
481 int dasDir = 0;
|
paulo@0
|
482 int dasCounter = 0;
|
paulo@0
|
483 const OptionsLine const *optionsMenu = commonOptionsMenu;
|
paulo@0
|
484 int lastClock = getTime();
|
paulo@0
|
485 int erase = -1;
|
paulo@0
|
486
|
paulo@0
|
487 optionsWinInit();
|
paulo@0
|
488
|
paulo@0
|
489 while (!done) {
|
paulo@0
|
490 if (redraw) {
|
paulo@0
|
491 if (redraw == 2) {
|
paulo@0
|
492 redraw = 1;
|
paulo@0
|
493 optionsDrawPage(page, prefs);
|
paulo@0
|
494 }
|
paulo@0
|
495 if (redraw == 1) {
|
paulo@0
|
496 if (erase >= 0) {
|
paulo@0
|
497 vsync();
|
paulo@0
|
498 optionsDrawRow(prefs,
|
paulo@0
|
499 erase - optionsPages[page].start,
|
paulo@0
|
500 erase, prefs[erase], 0);
|
paulo@0
|
501 erase = -1;
|
paulo@0
|
502 }
|
paulo@0
|
503 optionsDrawRow(prefs,
|
paulo@0
|
504 y - optionsPages[page].start,
|
paulo@0
|
505 y, prefs[y], 1);
|
paulo@0
|
506 redraw = 0;
|
paulo@0
|
507 }
|
paulo@0
|
508 } else {
|
paulo@0
|
509 optionsIdle();
|
paulo@0
|
510 }
|
paulo@0
|
511
|
paulo@0
|
512 LJBits keys = menuReadPad();
|
paulo@0
|
513 LJBits sounds = 0;
|
paulo@0
|
514 int lastY = y;
|
paulo@0
|
515 LJBits newKeys = keys & ~lastKeys;
|
paulo@0
|
516 LJBits dasKeys = 0;
|
paulo@0
|
517
|
paulo@0
|
518 if (getTime() != lastClock) {
|
paulo@0
|
519 // Handle DAS within options (fixed at 250 ms 30 Hz)
|
paulo@0
|
520 lastClock = getTime();
|
paulo@0
|
521 if (keys & dasDir) {
|
paulo@0
|
522 ++dasCounter;
|
paulo@0
|
523 if (dasCounter >= 15) {
|
paulo@0
|
524 dasCounter -= 2;
|
paulo@0
|
525 dasKeys = dasDir;
|
paulo@0
|
526 }
|
paulo@0
|
527 } else {
|
paulo@0
|
528 dasCounter = 0;
|
paulo@0
|
529 }
|
paulo@0
|
530 }
|
paulo@0
|
531
|
paulo@0
|
532 if (newKeys & VKEY_UP
|
paulo@0
|
533 || ((dasKeys & VKEY_UP)
|
paulo@0
|
534 && y > optionsPages[page].start)) {
|
paulo@0
|
535 dasDir = VKEY_UP;
|
paulo@0
|
536 if (y <= 0) {
|
paulo@0
|
537 while (optionsPages[page].name) {
|
paulo@0
|
538 ++page;
|
paulo@0
|
539 }
|
paulo@0
|
540 y = optionsPages[page].start - 1;
|
paulo@0
|
541 } else {
|
paulo@0
|
542 --y;
|
paulo@0
|
543 }
|
paulo@0
|
544 }
|
paulo@0
|
545 if (newKeys & VKEY_DOWN
|
paulo@0
|
546 || ((dasKeys & VKEY_DOWN)
|
paulo@0
|
547 && y < optionsPages[page + 1].start - 1)) {
|
paulo@0
|
548 dasDir = VKEY_DOWN;
|
paulo@0
|
549 ++y;
|
paulo@0
|
550 if (y >= optionsPages[page + 1].start
|
paulo@0
|
551 && !optionsPages[page + 1].name) {
|
paulo@0
|
552 y = 0;
|
paulo@0
|
553 }
|
paulo@0
|
554 }
|
paulo@0
|
555
|
paulo@0
|
556 if (!isDisabledOption(prefs, y)) {
|
paulo@0
|
557 if ((newKeys | dasKeys) & VKEY_RIGHT) {
|
paulo@0
|
558 int num = prefs[y] + 1;
|
paulo@0
|
559
|
paulo@0
|
560 if (num >= optionsMenu[y].minValue + optionsMenu[y].nValues) {
|
paulo@0
|
561 prefs[y] = optionsMenu[y].minValue;
|
paulo@0
|
562 } else {
|
paulo@0
|
563 prefs[y] = num;
|
paulo@0
|
564 }
|
paulo@0
|
565
|
paulo@0
|
566 sounds |= LJSND_ROTATE;
|
paulo@0
|
567 // XXX: need to redraw the whole box (redraw = 2)
|
paulo@0
|
568 // if options have become enabled or disabled
|
paulo@0
|
569 redraw = 1;
|
paulo@0
|
570 dasDir = VKEY_RIGHT;
|
paulo@0
|
571 }
|
paulo@0
|
572
|
paulo@0
|
573 if ((newKeys | dasKeys) & VKEY_LEFT) {
|
paulo@0
|
574 int num = prefs[y] - 1;
|
paulo@0
|
575
|
paulo@0
|
576 if (num < optionsMenu[y].minValue) {
|
paulo@0
|
577 prefs[y] = optionsMenu[y].minValue + optionsMenu[y].nValues - 1;
|
paulo@0
|
578 } else {
|
paulo@0
|
579 prefs[y] = num;
|
paulo@0
|
580 }
|
paulo@0
|
581
|
paulo@0
|
582 sounds |= LJSND_ROTATE;
|
paulo@0
|
583 redraw = 1;
|
paulo@0
|
584 dasDir = VKEY_LEFT;
|
paulo@0
|
585 }
|
paulo@0
|
586 }
|
paulo@0
|
587
|
paulo@0
|
588 // Rotate left: Go to the top of the previous page if it exists.
|
paulo@0
|
589 if (newKeys & VKEY_ROTL) {
|
paulo@0
|
590 if (page > 0) {
|
paulo@0
|
591 y = optionsPages[page - 1].start;
|
paulo@0
|
592 } else {
|
paulo@0
|
593 y = 0;
|
paulo@0
|
594 }
|
paulo@0
|
595 }
|
paulo@0
|
596
|
paulo@0
|
597 // Rotate right: If on last page, finish;
|
paulo@0
|
598 // otherwise, go to the top of the next page.
|
paulo@0
|
599 if (newKeys & VKEY_ROTR) {
|
paulo@0
|
600 if (!optionsPages[page + 1].name) {
|
paulo@0
|
601 done = 1;
|
paulo@0
|
602 } else {
|
paulo@0
|
603 y = optionsPages[page + 1].start;
|
paulo@0
|
604 }
|
paulo@0
|
605 }
|
paulo@0
|
606
|
paulo@0
|
607 // Start: finish
|
paulo@0
|
608 if (newKeys & VKEY_START) {
|
paulo@0
|
609 done = 1;
|
paulo@0
|
610 }
|
paulo@0
|
611
|
paulo@0
|
612 if (lastY != y) {
|
paulo@0
|
613 sounds |= LJSND_SHIFT;
|
paulo@0
|
614
|
paulo@0
|
615 // calculate which page the cursor has moved to
|
paulo@0
|
616 int lastPage = page;
|
paulo@0
|
617 while (y < optionsPages[page].start) {
|
paulo@0
|
618 --page;
|
paulo@0
|
619 }
|
paulo@0
|
620 while (y >= optionsPages[page + 1].start) {
|
paulo@0
|
621 ++page;
|
paulo@0
|
622 }
|
paulo@0
|
623
|
paulo@0
|
624 if (lastPage == page) {
|
paulo@0
|
625 erase = lastY;
|
paulo@0
|
626 if (redraw < 1) {
|
paulo@0
|
627 redraw = 1;
|
paulo@0
|
628 }
|
paulo@0
|
629 } else {
|
paulo@0
|
630 // turning the page
|
paulo@0
|
631 sounds |= LJSND_HOLD;
|
paulo@0
|
632 redraw = 2; // redraw the whole screen
|
paulo@0
|
633 }
|
paulo@0
|
634 }
|
paulo@0
|
635 lastKeys = keys;
|
paulo@0
|
636
|
paulo@0
|
637 if (done) {
|
paulo@0
|
638 sounds |= LJSND_LINE;
|
paulo@0
|
639 }
|
paulo@0
|
640 playSoundEffects(v, sounds, 100);
|
paulo@0
|
641 }
|
paulo@0
|
642 }
|