Mercurial > hg > index.fcgi > lj > lj046
diff src/options.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/options.c Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,642 @@ 1.4 +/* options code for LOCKJAW, an implementation of the Soviet Mind Game 1.5 + 1.6 +Copyright (C) 2007-2008 Damian Yerrick <tepples+lj@spamcop.net> 1.7 + 1.8 +This work is free software; you can redistribute it and/or modify 1.9 +it under the terms of the GNU General Public License as published by 1.10 +the Free Software Foundation; either version 2 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU General Public License 1.19 +along with this program; if not, write to the Free Software 1.20 +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.21 + 1.22 +Original game concept and design by Alexey Pajitnov. 1.23 +The Software is not sponsored or endorsed by Alexey Pajitnov, Elorg, 1.24 +or The Tetris Company LLC. 1.25 + 1.26 +*/ 1.27 + 1.28 + 1.29 +#include <string.h> 1.30 +#include <stdio.h> 1.31 +#include "options.h" 1.32 +#include "ljplay.h" 1.33 +#include "ljlocale.h" 1.34 + 1.35 +#ifdef HAS_FPU 1.36 +#define siprintf sprintf 1.37 +#define MIN_SHADOW 0 1.38 +#define N_SHADOWS LJSHADOW_N_STYLES 1.39 +#define FACTORY_SHADOW 0 1.40 +#include "ljpc.h" 1.41 +#else 1.42 +#define MIN_SHADOW LJSHADOW_COLORED 1.43 +#define N_SHADOWS (LJSHADOW_N_STYLES - 2) 1.44 +#define FACTORY_SHADOW MIN_SHADOW 1.45 +#endif 1.46 + 1.47 +const FourCC optionsBoolNames[2] = { 1.48 + {"Off"}, {"On"} 1.49 +}; 1.50 + 1.51 +const FourCC gimmickNames[LJGM_N_GIMMICKS] = { 1.52 + {"Mara"}, {"Line"}, {"Time"}, {"DrlA"}, {"Item"}, {"Keys"} 1.53 +}; 1.54 + 1.55 +const FourCC optionsGarbageNames[LJGARBAGE_N_STYLES] = { 1.56 + {"Off"}, {"Lv.1"}, {"Lv.2"}, {"Lv.3"}, {"Lv.4"}, 1.57 + {"HRD"}, {"DrlG"}, {"Zigz"} 1.58 +}; 1.59 + 1.60 +const FourCC optionsScoringNames[LJSCORE_N_STYLES] = { 1.61 + {"LJ"}, {"Fibo"}, {"HotL"}, {"TDSl"}, {"NESl"}, {"LJns"} 1.62 +}; 1.63 + 1.64 +const FourCC optionsKickLimitNames[N_KICK_LIMITS] = { 1.65 + {"Off"}, {"1"}, {"2"}, {"3"}, {"4"}, {"5"}, {"Inf"} 1.66 +}; 1.67 + 1.68 +const FourCC optionsSpeedCurveNames[] = { 1.69 + {"Zero"}, {"Rhy0"}, {"Exp"}, {"Rh20"}, 1.70 + {"TGM2"}, {"TAPD"}, {"TAD3"}, 1.71 + {"NESc"}, {"GBc"}, {"GBHL"} 1.72 +}; 1.73 + 1.74 +static const FourCC optionsWindowedNames[2] = { 1.75 + {"FulS"}, {"Wind"} 1.76 +}; 1.77 + 1.78 +const FourCC optionsShadowNames[LJSHADOW_N_STYLES] = { 1.79 + {"tl25"}, {"tl50"}, {"tlsC"}, {"tlsM"}, {"Off"}, {"invF"} 1.80 +}; 1.81 + 1.82 +const FourCC optionsLockDelayNames[2] = { 1.83 + {"SBSC"}, {"Inf"} 1.84 +}; 1.85 + 1.86 +const FourCC optionsSBSCNames[2] = { 1.87 + {"SBSC"}, {.i=0} 1.88 +}; 1.89 + 1.90 +const FourCC optionsTspinNames[] = { 1.91 + {"Off"}, {"Imob"}, {"CrnT"}, {"WKT"} 1.92 +}; 1.93 + 1.94 +const FourCC optionsLockdownNames[] = { 1.95 + {"OLD"}, {"EntR"}, {"StpR"}, {"MovR"} 1.96 +}; 1.97 + 1.98 +const FourCC optionsHoldStyleNames[] = { 1.99 + {"Off"}, {"HldE"}, {"HldR"}, {"HldN"} 1.100 +}; 1.101 + 1.102 +const FourCC optionsDropScoringNames[LJDROP_N_STYLES] = { 1.103 + {"None"}, {"ConD"}, {"S1H1"}, {"S1H2"} 1.104 +}; 1.105 + 1.106 +const FourCC optionsGravNames[] = { 1.107 + {"Naiv"}, {"Stky"}, {"byCo"}, {"Casc"} 1.108 +}; 1.109 + 1.110 +const FourCC optionsPieceSetNames[LJRAND_N_PIECE_SETS] = { 1.111 + {"IJLO"}, 1.112 + {"JLOT"}, 1.113 + {"SZSZ"}, 1.114 + {"IIII"}, 1.115 + {"AllP"}, 1.116 + {"TTTT"} 1.117 +}; 1.118 + 1.119 +const FourCC optionsRandNames[LJRAND_N_RANDS] = { 1.120 + {"Unif"}, 1.121 + {"Bag"}, 1.122 + {"Bag+"}, 1.123 + {"Bag2"}, 1.124 + {"Hist"}, 1.125 + {"His6"} 1.126 +}; 1.127 + 1.128 +const FourCC optionsLineDelayNames[] = { 1.129 + {"SBSC"}, {.i=0} 1.130 +}; 1.131 + 1.132 +const FourCC optionsZangiNames[] = { 1.133 + {"Slid"}, {"Lock"}, {"LocU"} 1.134 +}; 1.135 + 1.136 +const FourCC optionsGluingNames[] = { 1.137 + {"Off"}, {"Squ"}, {"Stky"}, {"byCo"} 1.138 +}; 1.139 + 1.140 +const FourCC optionsRotNames[N_ROTATION_SYSTEMS] = { 1.141 + {"SRS"}, {"Sega"}, {"ARS"}, {"Tngn"}, 1.142 + {"NRSR"}, {"NRSL"}, {"TOD4"}, {"TDX"} 1.143 +}; 1.144 + 1.145 + 1.146 +const OptionsLine commonOptionsMenu[] = { 1.147 + {{"gimm"}, gimmickNames, 1.148 + 0, LJGM_N_GIMMICKS, 0 }, 1.149 + {{"pfw"}, NULL, 1.150 + 4, LJ_PF_WID - 4 + 1, 10 }, 1.151 + {{"pfh"}, NULL, 1.152 + 8, LJ_PF_VIS_HT - 8 + 1, LJ_PF_VIS_HT }, 1.153 + {{"vzsp"}, optionsBoolNames, 1.154 + 0, 2, 1 }, 1.155 + {{"spdc"}, optionsSpeedCurveNames, 1.156 + 0, LJSPD_N_CURVES, LJSPD_EXP }, 1.157 + {{"are"}, NULL, 1.158 + 0, 121, 0, OPTSTYLE_FRAMES }, 1.159 + {{"piec"}, optionsPieceSetNames, 1.160 + 0, LJRAND_N_PIECE_SETS, LJRAND_4BLK }, 1.161 + {{"rand"}, optionsRandNames, 1.162 + 0, LJRAND_N_RANDS, LJRAND_BAG }, 1.163 + 1.164 + {{"hold"}, optionsHoldStyleNames, 1.165 + 0, LJHOLD_N_STYLES, LJHOLD_EMPTY }, 1.166 + {{"rots"}, optionsRotNames, 1.167 + 0, N_ROTATION_SYSTEMS, 0 }, 1.168 + {{"upkl"}, optionsKickLimitNames, 1.169 + 0, N_KICK_LIMITS, N_KICK_LIMITS - 1 }, 1.170 + {{"lock"}, optionsLockdownNames, 1.171 + 0, LJLOCK_N_STYLES, LJLOCK_MOVE }, 1.172 + {{"sldt"}, optionsLockDelayNames, 1.173 + 0, 129, 0, OPTSTYLE_FRAMES }, 1.174 + {{"deep"}, optionsBoolNames, 1.175 + 0, 2, 0 }, 1.176 + 1.177 + {{"clrd"}, optionsSBSCNames, 1.178 + 0, 121, 0, OPTSTYLE_FRAMES }, 1.179 + {{"grav"}, optionsGravNames, 1.180 + 0, LJGRAV_N_ALGOS, LJGRAV_NAIVE }, 1.181 + {{"glue"}, optionsGluingNames, 1.182 + 0, LJGLUING_N_STYLES, LJGLUING_NONE }, 1.183 + {{"lsco"}, optionsScoringNames, 1.184 + 0, LJSCORE_N_STYLES }, 1.185 + {{"dsco"}, optionsDropScoringNames, 1.186 + 0, LJDROP_N_STYLES, 0 }, 1.187 + {{"tspn"}, optionsTspinNames, 1.188 + 0, LJTS_N_ALGOS, LJTS_TDS }, 1.189 + {{"garb"}, optionsGarbageNames, 1.190 + 0, LJGARBAGE_N_STYLES, 0 }, 1.191 + 1.192 + {{"dasd"}, NULL, 1.193 + 1, 120, 10, OPTSTYLE_FRAMES }, 1.194 + {{"dass"}, NULL, 1.195 + 0, 10, 1, OPTSTYLE_FRAC_G }, 1.196 + {{"idas"}, optionsBoolNames, 1.197 + 0, 2, 1 }, 1.198 + {{"irs"}, optionsBoolNames, 1.199 + 0, 2, 1 }, 1.200 + {{"8way"}, optionsBoolNames, 1.201 + 0, 2, 0 }, 1.202 + 1.203 + {{"sfds"}, NULL, 1.204 + 1, 3, 1, OPTSTYLE_FRAC_G }, 1.205 + {{"sfdl"}, optionsZangiNames, 1.206 + 0, LJZANGI_N_STYLES, LJZANGI_SLIDE }, 1.207 + {{"hrdl"}, optionsZangiNames, 1.208 + 0, LJZANGI_N_STYLES, LJZANGI_LOCK }, 1.209 + 1.210 + {{"tls"}, optionsShadowNames + MIN_SHADOW, 1.211 + MIN_SHADOW, N_SHADOWS, FACTORY_SHADOW }, 1.212 + {{"invs"}, optionsBoolNames, 1.213 + 0, 2, 0 }, 1.214 + {{"next"}, NULL, 1.215 + 0, LJ_NEXT_PIECES + 1, 6 }, 1.216 + {{"srph"}, optionsBoolNames, 1.217 + 0, 2, 1 }, 1.218 + 1.219 +#ifdef HAS_FPU 1.220 + {{"inpv"}, NULL, 1.221 + 0, LJ_NEXT_PIECES + 1, 0 }, 1.222 + {{"mblr"}, optionsBoolNames, 1.223 + 0, 2, 1 }, 1.224 + {{"lidp"}, optionsBoolNames, 1.225 + 0, 2, 1 }, 1.226 + {{"rec"}, optionsBoolNames, 1.227 + 0, 2, 0 }, 1.228 + {{"wndw"}, optionsWindowedNames, 1.229 + 0, 2, 1 } 1.230 +#endif 1.231 +}; 1.232 + 1.233 +const OptionsPage optionsPages[] = { 1.234 + {OPTIONS_GIMMICK, "Game"}, 1.235 + {OPTIONS_WIDTH, "Rules: Well"}, 1.236 + {OPTIONS_HOLD_PIECE, "Rules: Movement"}, 1.237 + {OPTIONS_LINE_DELAY, "Rules: Line clear"}, 1.238 + {OPTIONS_SIDEWAYS_DELAY, "Control: Movement"}, 1.239 + {OPTIONS_SOFT_DROP_SPEED, "Control: Drop"}, 1.240 + {OPTIONS_SHADOW, "Display"}, 1.241 +#ifdef HAS_FPU 1.242 + {OPTIONS_MENU_LEN, "PC"}, 1.243 + {PC_OPTIONS_MENU_LEN, NULL} 1.244 +#else 1.245 + {OPTIONS_MENU_LEN, NULL} 1.246 +#endif 1.247 +}; 1.248 + 1.249 +void setOptionsValueToFourCC(char *dst, FourCC f) { 1.250 + const char *valueName = ljGetFourCCName(f); 1.251 + if (valueName) { 1.252 + strncpy(dst, 1.253 + valueName, 1.254 + OPTIONS_VALUE_LEN - 1); 1.255 + dst[OPTIONS_VALUE_LEN - 1] = 0; 1.256 + } else { 1.257 + strncpy(dst, f.c, 4); 1.258 + dst[4] = 0; 1.259 + } 1.260 +} 1.261 + 1.262 +struct DisabledOption { 1.263 + unsigned char name; 1.264 + unsigned char value; 1.265 + unsigned char name2; 1.266 + char reason[45]; 1.267 +}; 1.268 + 1.269 +/* 1.270 + Semantics: 1.271 + If option name is set to value, 1.272 + then gray out option name2 and draw its value as reason. 1.273 +*/ 1.274 +#define N_DISABLED_OPTIONS 12 1.275 +const struct DisabledOption disabledOptions[N_DISABLED_OPTIONS] = { 1.276 + { OPTIONS_LOCKDOWN, LJLOCK_NOW, 1.277 + OPTIONS_SOFT_DROP, "Lockdown is immediate" }, 1.278 + { OPTIONS_LOCKDOWN, LJLOCK_NOW, 1.279 + OPTIONS_HARD_DROP, "Lockdown is immediate" }, 1.280 + { OPTIONS_LOCKDOWN, LJLOCK_NOW, 1.281 + OPTIONS_LOCK_DELAY, "Lockdown is immediate" }, 1.282 + { OPTIONS_LOCK_DELAY, 128, 1.283 + OPTIONS_LOCKDOWN, "Lockdown is manual" }, 1.284 + { OPTIONS_SPEED_CURVE, LJSPD_DEATH, 1.285 + OPTIONS_SOFT_DROP_SPEED,"Death: pieces land instantly" }, 1.286 + { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM, 1.287 + OPTIONS_SOFT_DROP_SPEED,"Rhythm: pieces land instantly" }, 1.288 + { OPTIONS_SPEED_CURVE, LJSPD_DEATH, 1.289 + OPTIONS_SMOOTH_GRAVITY, "Death: pieces land instantly" }, 1.290 + { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM, 1.291 + OPTIONS_SMOOTH_GRAVITY, "Rhythm: pieces land instantly" }, 1.292 + { OPTIONS_SPEED_CURVE, LJSPD_DEATH, 1.293 + OPTIONS_SOFT_DROP, "Death: pieces land instantly" }, 1.294 + { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM, 1.295 + OPTIONS_SOFT_DROP, "Rhythm: pieces land instantly" }, 1.296 + { OPTIONS_SPEED_CURVE, LJSPD_DEATH, 1.297 + OPTIONS_HARD_DROP, "Death: pieces land instantly" }, 1.298 + { OPTIONS_SPEED_CURVE, LJSPD_RHYTHM, 1.299 + OPTIONS_HARD_DROP, "Rhythm: pieces land instantly" }, 1.300 +}; 1.301 + 1.302 +const char *isDisabledOption(const unsigned char *prefs, int y) { 1.303 + for (int i = 0; i < N_DISABLED_OPTIONS; ++i) { 1.304 + if (y == disabledOptions[i].name2) { 1.305 + int name = disabledOptions[i].name; 1.306 + int value = disabledOptions[i].value; 1.307 + 1.308 + if (prefs[name] == value) { 1.309 + return disabledOptions[i].reason; 1.310 + } 1.311 + } 1.312 + } 1.313 + return NULL; 1.314 +} 1.315 + 1.316 + 1.317 +const char *getOptionsValueStr(char *dst, int line, int value) { 1.318 + const OptionsLine *l = &(commonOptionsMenu[line]); 1.319 + FourCC f = {.i = 0}; 1.320 + const char *desc = NULL; 1.321 + 1.322 + switch (l->style) { 1.323 + case OPTSTYLE_DEFAULT: 1.324 + if (l->valueNames) { 1.325 + f = l->valueNames[value - l->minValue]; 1.326 + } else { 1.327 + siprintf(dst, "%d", value); 1.328 + } 1.329 + break; 1.330 + 1.331 + case OPTSTYLE_FRAMES: 1.332 + if (l->valueNames 1.333 + && value == l->minValue 1.334 + && l->valueNames[0].i) { 1.335 + 1.336 + // override first with name 0 1.337 + f = l->valueNames[0]; 1.338 + } else if (l->valueNames 1.339 + && value == l->minValue 1.340 + + l->nValues - 1 1.341 + && l->valueNames[1].i) { 1.342 + 1.343 + // override second with name 1 1.344 + f = l->valueNames[1]; 1.345 + } else { 1.346 + if (value >= 60) { 1.347 + int ds = value / 6; 1.348 + int s = ds / 10; 1.349 + ds -= s * 10; 1.350 + siprintf(dst, "%d/60 s (%d.%d s)", value, s, ds); 1.351 + } else { 1.352 + int ms = value * 50 / 3; 1.353 + siprintf(dst, "%d/60 s (%d ms)", value, ms); 1.354 + } 1.355 + } break; 1.356 + 1.357 + case OPTSTYLE_FRAC_G: 1.358 + if (value > 6) { 1.359 + int dHz = 600 / value; 1.360 + int Hz = dHz / 10; 1.361 + dHz -= Hz * 10; 1.362 + siprintf(dst, "1/%dG (%d.%d Hz)", value, Hz, dHz); 1.363 + } else if (value > 0) { 1.364 + if (value > 1) { 1.365 + dst[0] = '1'; 1.366 + dst[1] = '/'; 1.367 + dst += 2; 1.368 + } 1.369 + siprintf(dst, "%dG (%d Hz)", value, 60 / value); 1.370 + } else { 1.371 + strcpy(dst, "Instant"); 1.372 + } 1.373 + break; 1.374 + 1.375 + default: 1.376 + strncpy(dst, "Unknown option style.", OPTIONS_VALUE_LEN - 1); 1.377 + dst[OPTIONS_VALUE_LEN - 1] = 0; 1.378 + break; 1.379 + } 1.380 + 1.381 + /* If we have a fourCC, use it. */ 1.382 + if (f.i != 0) { 1.383 + setOptionsValueToFourCC(dst, f); 1.384 + desc = ljGetFourCCDesc(f); 1.385 + } 1.386 + return desc; 1.387 +} 1.388 + 1.389 +void unpackCommonOptions(LJView *v, const unsigned char *prefs) { 1.390 + if (prefs[OPTIONS_GIMMICK] < 255) 1.391 + v->field->gimmick = prefs[OPTIONS_GIMMICK]; 1.392 + if (prefs[OPTIONS_WIDTH] < 255) { 1.393 + int width = prefs[OPTIONS_WIDTH]; 1.394 + v->field->leftWall = (LJ_PF_WID - width) / 2; 1.395 + v->field->rightWall = v->field->leftWall + width; 1.396 + } 1.397 + if (prefs[OPTIONS_HEIGHT] < 255) 1.398 + v->field->ceiling = prefs[OPTIONS_HEIGHT]; 1.399 + if (prefs[OPTIONS_ENTER_ABOVE] < 255) 1.400 + v->field->enterAbove = prefs[OPTIONS_ENTER_ABOVE]; 1.401 + if (prefs[OPTIONS_SPEED_CURVE] < 255) 1.402 + v->field->speedState.curve = prefs[OPTIONS_SPEED_CURVE]; 1.403 + if (prefs[OPTIONS_ENTRY_DELAY] < 255) 1.404 + v->field->areStyle = prefs[OPTIONS_ENTRY_DELAY]; 1.405 + if (prefs[OPTIONS_PIECE_SET] < 255) 1.406 + v->field->pieceSet = prefs[OPTIONS_PIECE_SET]; 1.407 + if (prefs[OPTIONS_RANDOMIZER] < 255) 1.408 + v->field->randomizer = prefs[OPTIONS_RANDOMIZER]; 1.409 + 1.410 + if (prefs[OPTIONS_ROTATION_SYSTEM] < 255) 1.411 + v->field->rotationSystem = prefs[OPTIONS_ROTATION_SYSTEM]; 1.412 + if (prefs[OPTIONS_FLOOR_KICKS] < 255) 1.413 + v->field->maxUpwardKicks = prefs[OPTIONS_FLOOR_KICKS] == N_KICK_LIMITS - 1 1.414 + ? 128 1.415 + : prefs[OPTIONS_FLOOR_KICKS]; 1.416 + if (prefs[OPTIONS_HOLD_PIECE] < 255) 1.417 + v->field->holdStyle = prefs[OPTIONS_HOLD_PIECE]; 1.418 + if (prefs[OPTIONS_LOCKDOWN] < 255) 1.419 + v->field->lockReset = prefs[OPTIONS_LOCKDOWN]; 1.420 + if (prefs[OPTIONS_LOCK_DELAY] < 255) 1.421 + v->field->setLockDelay = prefs[OPTIONS_LOCK_DELAY]; 1.422 + if (prefs[OPTIONS_BOTTOM_BLOCKS] < 255) 1.423 + v->field->bottomBlocks = prefs[OPTIONS_BOTTOM_BLOCKS]; 1.424 + 1.425 + if (prefs[OPTIONS_LINE_DELAY] < 255) 1.426 + v->field->setLineDelay = prefs[OPTIONS_LINE_DELAY]; 1.427 + if (prefs[OPTIONS_T_SPIN] < 255) 1.428 + v->field->tSpinAlgo = prefs[OPTIONS_T_SPIN]; 1.429 + if (prefs[OPTIONS_CLEAR_GRAVITY] < 255) 1.430 + v->field->clearGravity = prefs[OPTIONS_CLEAR_GRAVITY]; 1.431 + if (prefs[OPTIONS_GLUING] < 255) 1.432 + v->field->gluing = prefs[OPTIONS_GLUING]; 1.433 + if (prefs[OPTIONS_SCORING] < 255) 1.434 + v->field->scoreStyle = prefs[OPTIONS_SCORING]; 1.435 + if (prefs[OPTIONS_DROP_SCORING] < 255) 1.436 + v->field->dropScoreStyle = prefs[OPTIONS_DROP_SCORING]; 1.437 + if (prefs[OPTIONS_GARBAGE] < 255) 1.438 + v->field->garbageStyle = prefs[OPTIONS_GARBAGE]; 1.439 + 1.440 + if (prefs[OPTIONS_SIDEWAYS_DELAY] < 255) 1.441 + v->control->dasDelay = prefs[OPTIONS_SIDEWAYS_DELAY]; 1.442 + if (prefs[OPTIONS_SIDEWAYS_SPEED] < 255) 1.443 + v->control->dasSpeed = prefs[OPTIONS_SIDEWAYS_SPEED]; 1.444 + if (v->control->dasDelay < v->control->dasSpeed) { 1.445 + v->control->dasDelay = v->control->dasSpeed; 1.446 + } 1.447 + if (prefs[OPTIONS_INITIAL_SIDEWAYS] < 255) 1.448 + v->control->initialDAS = prefs[OPTIONS_INITIAL_SIDEWAYS]; 1.449 + if (prefs[OPTIONS_IRS] < 255) 1.450 + v->control->initialRotate = prefs[OPTIONS_IRS]; 1.451 + if (prefs[OPTIONS_DIAGONAL_MOTION] < 255) 1.452 + v->control->allowDiagonals = prefs[OPTIONS_DIAGONAL_MOTION]; 1.453 + if (prefs[OPTIONS_SOFT_DROP_SPEED] < 255) 1.454 + v->control->softDropSpeed = prefs[OPTIONS_SOFT_DROP_SPEED] - 1; 1.455 + if (prefs[OPTIONS_SOFT_DROP] < 255) 1.456 + v->control->softDropLock = prefs[OPTIONS_SOFT_DROP]; 1.457 + if (prefs[OPTIONS_HARD_DROP] < 255) 1.458 + v->control->hardDropLock = prefs[OPTIONS_HARD_DROP]; 1.459 + 1.460 + if (prefs[OPTIONS_SHADOW] < 255) 1.461 + v->hideShadow = prefs[OPTIONS_SHADOW]; 1.462 + if (prefs[OPTIONS_HIDE_PF] < 255) 1.463 + v->hidePF = prefs[OPTIONS_HIDE_PF]; 1.464 + if (prefs[OPTIONS_NEXT_PIECES] < 255) 1.465 + v->nextPieces = prefs[OPTIONS_NEXT_PIECES]; 1.466 + if (prefs[OPTIONS_SMOOTH_GRAVITY] < 255) 1.467 + v->smoothGravity = prefs[OPTIONS_SMOOTH_GRAVITY]; 1.468 +} 1.469 + 1.470 +void initOptions(unsigned char *prefs) { 1.471 + for (int i = 0; i < OPTIONS_MENU_LEN; ++i) { 1.472 + prefs[i] = commonOptionsMenu[i].startValue; 1.473 + } 1.474 +} 1.475 + 1.476 +LJBits menuReadPad(void); 1.477 +void vsync(void); 1.478 + 1.479 +void options(LJView *v, unsigned char *prefs) { 1.480 + int page = 0, y = 0; 1.481 + int redraw = 2; 1.482 + int done = 0; 1.483 + LJBits lastKeys = ~0; 1.484 + int dasDir = 0; 1.485 + int dasCounter = 0; 1.486 + const OptionsLine const *optionsMenu = commonOptionsMenu; 1.487 + int lastClock = getTime(); 1.488 + int erase = -1; 1.489 + 1.490 + optionsWinInit(); 1.491 + 1.492 + while (!done) { 1.493 + if (redraw) { 1.494 + if (redraw == 2) { 1.495 + redraw = 1; 1.496 + optionsDrawPage(page, prefs); 1.497 + } 1.498 + if (redraw == 1) { 1.499 + if (erase >= 0) { 1.500 + vsync(); 1.501 + optionsDrawRow(prefs, 1.502 + erase - optionsPages[page].start, 1.503 + erase, prefs[erase], 0); 1.504 + erase = -1; 1.505 + } 1.506 + optionsDrawRow(prefs, 1.507 + y - optionsPages[page].start, 1.508 + y, prefs[y], 1); 1.509 + redraw = 0; 1.510 + } 1.511 + } else { 1.512 + optionsIdle(); 1.513 + } 1.514 + 1.515 + LJBits keys = menuReadPad(); 1.516 + LJBits sounds = 0; 1.517 + int lastY = y; 1.518 + LJBits newKeys = keys & ~lastKeys; 1.519 + LJBits dasKeys = 0; 1.520 + 1.521 + if (getTime() != lastClock) { 1.522 + // Handle DAS within options (fixed at 250 ms 30 Hz) 1.523 + lastClock = getTime(); 1.524 + if (keys & dasDir) { 1.525 + ++dasCounter; 1.526 + if (dasCounter >= 15) { 1.527 + dasCounter -= 2; 1.528 + dasKeys = dasDir; 1.529 + } 1.530 + } else { 1.531 + dasCounter = 0; 1.532 + } 1.533 + } 1.534 + 1.535 + if (newKeys & VKEY_UP 1.536 + || ((dasKeys & VKEY_UP) 1.537 + && y > optionsPages[page].start)) { 1.538 + dasDir = VKEY_UP; 1.539 + if (y <= 0) { 1.540 + while (optionsPages[page].name) { 1.541 + ++page; 1.542 + } 1.543 + y = optionsPages[page].start - 1; 1.544 + } else { 1.545 + --y; 1.546 + } 1.547 + } 1.548 + if (newKeys & VKEY_DOWN 1.549 + || ((dasKeys & VKEY_DOWN) 1.550 + && y < optionsPages[page + 1].start - 1)) { 1.551 + dasDir = VKEY_DOWN; 1.552 + ++y; 1.553 + if (y >= optionsPages[page + 1].start 1.554 + && !optionsPages[page + 1].name) { 1.555 + y = 0; 1.556 + } 1.557 + } 1.558 + 1.559 + if (!isDisabledOption(prefs, y)) { 1.560 + if ((newKeys | dasKeys) & VKEY_RIGHT) { 1.561 + int num = prefs[y] + 1; 1.562 + 1.563 + if (num >= optionsMenu[y].minValue + optionsMenu[y].nValues) { 1.564 + prefs[y] = optionsMenu[y].minValue; 1.565 + } else { 1.566 + prefs[y] = num; 1.567 + } 1.568 + 1.569 + sounds |= LJSND_ROTATE; 1.570 + // XXX: need to redraw the whole box (redraw = 2) 1.571 + // if options have become enabled or disabled 1.572 + redraw = 1; 1.573 + dasDir = VKEY_RIGHT; 1.574 + } 1.575 + 1.576 + if ((newKeys | dasKeys) & VKEY_LEFT) { 1.577 + int num = prefs[y] - 1; 1.578 + 1.579 + if (num < optionsMenu[y].minValue) { 1.580 + prefs[y] = optionsMenu[y].minValue + optionsMenu[y].nValues - 1; 1.581 + } else { 1.582 + prefs[y] = num; 1.583 + } 1.584 + 1.585 + sounds |= LJSND_ROTATE; 1.586 + redraw = 1; 1.587 + dasDir = VKEY_LEFT; 1.588 + } 1.589 + } 1.590 + 1.591 + // Rotate left: Go to the top of the previous page if it exists. 1.592 + if (newKeys & VKEY_ROTL) { 1.593 + if (page > 0) { 1.594 + y = optionsPages[page - 1].start; 1.595 + } else { 1.596 + y = 0; 1.597 + } 1.598 + } 1.599 + 1.600 + // Rotate right: If on last page, finish; 1.601 + // otherwise, go to the top of the next page. 1.602 + if (newKeys & VKEY_ROTR) { 1.603 + if (!optionsPages[page + 1].name) { 1.604 + done = 1; 1.605 + } else { 1.606 + y = optionsPages[page + 1].start; 1.607 + } 1.608 + } 1.609 + 1.610 + // Start: finish 1.611 + if (newKeys & VKEY_START) { 1.612 + done = 1; 1.613 + } 1.614 + 1.615 + if (lastY != y) { 1.616 + sounds |= LJSND_SHIFT; 1.617 + 1.618 + // calculate which page the cursor has moved to 1.619 + int lastPage = page; 1.620 + while (y < optionsPages[page].start) { 1.621 + --page; 1.622 + } 1.623 + while (y >= optionsPages[page + 1].start) { 1.624 + ++page; 1.625 + } 1.626 + 1.627 + if (lastPage == page) { 1.628 + erase = lastY; 1.629 + if (redraw < 1) { 1.630 + redraw = 1; 1.631 + } 1.632 + } else { 1.633 + // turning the page 1.634 + sounds |= LJSND_HOLD; 1.635 + redraw = 2; // redraw the whole screen 1.636 + } 1.637 + } 1.638 + lastKeys = keys; 1.639 + 1.640 + if (done) { 1.641 + sounds |= LJSND_LINE; 1.642 + } 1.643 + playSoundEffects(v, sounds, 100); 1.644 + } 1.645 +}