annotate src/lj.h @ 3:17286938e22a

change DS alt. rotate key to rotate twice
author paulo@localhost
date Wed, 08 Apr 2009 21:50:13 -0700
parents
children
rev   line source
paulo@0 1 /* Header file for the engine of LOCKJAW, an implementation of the Soviet Mind Game
paulo@0 2
paulo@0 3 Copyright (C) 2006 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 #ifndef LJ_H
paulo@0 26 #define LJ_H
paulo@0 27
paulo@0 28 #include <stdlib.h>
paulo@0 29 #include "ljtypes.h"
paulo@0 30
paulo@0 31 enum {
paulo@0 32 CONNECT_U = 0x01,
paulo@0 33 CONNECT_R = 0x02,
paulo@0 34 CONNECT_D = 0x04,
paulo@0 35 CONNECT_L = 0x08,
paulo@0 36 CONNECT_UD = CONNECT_U | CONNECT_D,
paulo@0 37 CONNECT_UL = CONNECT_U | CONNECT_L,
paulo@0 38 CONNECT_DL = CONNECT_D | CONNECT_L,
paulo@0 39 CONNECT_UR = CONNECT_U | CONNECT_R,
paulo@0 40 CONNECT_DR = CONNECT_D | CONNECT_R,
paulo@0 41 CONNECT_LR = CONNECT_L | CONNECT_R,
paulo@0 42 CONNECT_UDL = CONNECT_UD | CONNECT_L,
paulo@0 43 CONNECT_UDR = CONNECT_UD | CONNECT_R,
paulo@0 44 CONNECT_ULR = CONNECT_UL | CONNECT_R,
paulo@0 45 CONNECT_DLR = CONNECT_DL | CONNECT_R,
paulo@0 46 CONNECT_UDLR = CONNECT_UD | CONNECT_LR,
paulo@0 47 CONNECT_MASK = CONNECT_UDLR,
paulo@0 48 COLOR_MASK = 0xF0
paulo@0 49 };
paulo@0 50
paulo@0 51 typedef unsigned char LJBlock;
paulo@0 52
paulo@0 53 typedef enum LJState {
paulo@0 54 LJS_INACTIVE,
paulo@0 55 LJS_NEW_PIECE, /* delay is ARE */
paulo@0 56 LJS_FALLING, /* delay is fall delay; NOT IMPLEMENTED */
paulo@0 57 LJS_LANDED, /* delay is lock delay */
paulo@0 58 LJS_LINES, /* delay is line delay */
paulo@0 59 LJS_LINES_FALLING, /* delay is fall delay per line; NOT IMPLEMENTED */
paulo@0 60 LJS_GAMEOVER, /* game over animation */
paulo@0 61 LJS_EXPLODE /* used for bombliss extension */
paulo@0 62 } LJState;
paulo@0 63
paulo@0 64 // for other
paulo@0 65 enum {
paulo@0 66 LJI_HOLD = 0x01,
paulo@0 67 LJI_LOCK = 0x02
paulo@0 68 };
paulo@0 69
paulo@0 70 // for dirty bits
paulo@0 71 enum {
paulo@0 72 LJ_DIRTY_NEXT = 0x01000000,
paulo@0 73 LJ_DIRTY_SCORE = 0x02000000
paulo@0 74 };
paulo@0 75
paulo@0 76 // for gimmick (game mode)
paulo@0 77 enum {
paulo@0 78 LJGM_ATYPE, // marathon
paulo@0 79 LJGM_BTYPE, // 40 lines
paulo@0 80 LJGM_ULTRA, // 180 seconds
paulo@0 81 LJGM_DRILL, // clear bottom line
paulo@0 82 LJGM_ITEMS, // no rotation + no next + fast drop + garbage + banana
paulo@0 83 LJGM_BABY, // 300 keypresses
paulo@0 84 LJGM_N_GIMMICKS
paulo@0 85 };
paulo@0 86
paulo@0 87 enum {
paulo@0 88 LJP_I = 0,
paulo@0 89 LJP_J,
paulo@0 90 LJP_L,
paulo@0 91 LJP_O,
paulo@0 92 LJP_S,
paulo@0 93 LJP_T,
paulo@0 94 LJP_Z,
paulo@0 95 LJP_I2,
paulo@0 96 LJP_I3,
paulo@0 97 LJP_L3,
paulo@0 98 LJP_GARBAGE = 7,
paulo@0 99 LJP_MASK = 0x0F
paulo@0 100 };
paulo@0 101
paulo@0 102 enum {
paulo@0 103 LJSND_ROTATE = 0x0001,
paulo@0 104 LJSND_SHIFT = 0x0002,
paulo@0 105 LJSND_DROP = 0x0004,
paulo@0 106 LJSND_LAND = 0x0008,
paulo@0 107 LJSND_LOCK = 0x0010,
paulo@0 108 LJSND_LINE = 0x0020, // a line was scored
paulo@0 109 LJSND_SETB2B = 0x0040, // this line is b2b worthy (tetris or t-spin)
paulo@0 110 LJSND_B2B = 0x0080, // this line AND last line were b2b worthy
paulo@0 111 LJSND_SPAWN = 0x0100, // next piece was moved up
paulo@0 112 LJSND_HOLD = 0x0200, // hold piece was activated
paulo@0 113 LJSND_IRS = 0x0400, // initial rotation: spawn last frame and rotation this frame
paulo@0 114 LJSND_SQUARE = 0x0800, // formed 4x4 square
paulo@0 115 LJSND_COUNTDOWN = 0x4000, // countdown value changed
paulo@0 116 LJSND_SECTIONUP = 0x8000, // section increased
paulo@0 117 };
paulo@0 118
paulo@0 119 enum {
paulo@0 120 LJRAND_PURE,
paulo@0 121 LJRAND_BAG,
paulo@0 122 LJRAND_BAGPLUS1,
paulo@0 123 LJRAND_2BAG,
paulo@0 124 LJRAND_HIST_INF,
paulo@0 125 LJRAND_HIST_6,
paulo@0 126 LJRAND_N_RANDS
paulo@0 127 };
paulo@0 128
paulo@0 129 enum {
paulo@0 130 LJRAND_4BLK,
paulo@0 131 LJRAND_JLOSTZ,
paulo@0 132 LJRAND_SZ,
paulo@0 133 LJRAND_I,
paulo@0 134 LJRAND_234BLK,
paulo@0 135 LJRAND_T,
paulo@0 136 LJRAND_N_PIECE_SETS
paulo@0 137 };
paulo@0 138
paulo@0 139 enum {
paulo@0 140 LJTS_OFF = 0,
paulo@0 141 LJTS_TNT,
paulo@0 142 LJTS_TDS,
paulo@0 143 LJTS_TDS_NO_KICK,
paulo@0 144 LJTS_N_ALGOS
paulo@0 145 };
paulo@0 146
paulo@0 147 enum {
paulo@0 148 LJSPD_ZERO = 0,
paulo@0 149 LJSPD_RHYTHMZERO,
paulo@0 150 LJSPD_EXP,
paulo@0 151 LJSPD_RHYTHM,
paulo@0 152 LJSPD_TGM,
paulo@0 153 LJSPD_DEATH,
paulo@0 154 LJSPD_DEATH300,
paulo@0 155 LJSPD_NES,
paulo@0 156 LJSPD_GB,
paulo@0 157 LJSPD_GBHEART,
paulo@0 158 LJSPD_N_CURVES
paulo@0 159 };
paulo@0 160
paulo@0 161 enum {
paulo@0 162 LJLOCK_NOW = 0,
paulo@0 163 LJLOCK_SPAWN,
paulo@0 164 LJLOCK_STEP,
paulo@0 165 LJLOCK_MOVE,
paulo@0 166 LJLOCK_N_STYLES
paulo@0 167 };
paulo@0 168
paulo@0 169 enum {
paulo@0 170 LJGRAV_NAIVE = 0,
paulo@0 171 LJGRAV_STICKY,
paulo@0 172 LJGRAV_STICKY_BY_COLOR,
paulo@0 173 LJGRAV_CASCADE,
paulo@0 174 LJGRAV_N_ALGOS
paulo@0 175 };
paulo@0 176
paulo@0 177 enum {
paulo@0 178 LJSCORE_LJ,
paulo@0 179 LJSCORE_TNT64,
paulo@0 180 LJSCORE_HOTLINE,
paulo@0 181 LJSCORE_TDS,
paulo@0 182 LJSCORE_NES,
paulo@0 183 LJSCORE_LJ_NERF,
paulo@0 184 LJSCORE_N_STYLES,
paulo@0 185 LJSCORE_WORLDS,
paulo@0 186 LJSCORE_TGM1,
paulo@0 187 LJSCORE_IPOD
paulo@0 188 };
paulo@0 189
paulo@0 190 enum {
paulo@0 191 LJDROP_NOSCORE,
paulo@0 192 LJDROP_NES,
paulo@0 193 LJDROP_1CELL,
paulo@0 194 LJDROP_1S_2H,
paulo@0 195 LJDROP_N_STYLES
paulo@0 196 };
paulo@0 197
paulo@0 198 enum {
paulo@0 199 LJGARBAGE_NONE,
paulo@0 200 LJGARBAGE_1,
paulo@0 201 LJGARBAGE_2,
paulo@0 202 LJGARBAGE_3,
paulo@0 203 LJGARBAGE_4,
paulo@0 204 LJGARBAGE_HRDERBY,
paulo@0 205 LJGARBAGE_DRILL,
paulo@0 206 LJGARBAGE_ZIGZAG,
paulo@0 207
paulo@0 208 LJGARBAGE_N_STYLES
paulo@0 209 };
paulo@0 210
paulo@0 211 enum {
paulo@0 212 LJHOLD_NONE,
paulo@0 213 LJHOLD_EMPTY,
paulo@0 214 LJHOLD_TNT,
paulo@0 215 LJHOLD_TO_NEXT,
paulo@0 216 LJHOLD_N_STYLES
paulo@0 217 };
paulo@0 218
paulo@0 219 enum {
paulo@0 220 LJGLUING_NONE,
paulo@0 221 LJGLUING_SQUARE,
paulo@0 222 LJGLUING_STICKY,
paulo@0 223 LJGLUING_STICKY_BY_COLOR,
paulo@0 224 LJGLUING_N_STYLES
paulo@0 225 };
paulo@0 226
paulo@0 227 // Guideline says 10 wide, but we want to support tetrinet mode
paulo@0 228 #define LJ_PF_WID ((size_t)12)
paulo@0 229 #define LJ_SPAWN_X ((LJ_PF_WID - 3) / 2)
paulo@0 230 #define LJ_PF_HT ((size_t)24)
paulo@0 231 #define LJ_PF_VIS_HT ((size_t)20)
paulo@0 232 #define LJ_NEXT_PIECES 8
paulo@0 233 #define LJ_MAX_LINES_PER_PIECE 8
paulo@0 234
paulo@0 235 typedef struct LJBlkSpec
paulo@0 236 {
paulo@0 237 signed char x, y, conn, reserved;
paulo@0 238 } LJBlkSpec;
paulo@0 239
paulo@0 240 typedef struct LJInput {
paulo@0 241 signed char rotation, movement;
paulo@0 242 unsigned char gravity; /* 5.3 format */
paulo@0 243 unsigned char other;
paulo@0 244 } LJInput;
paulo@0 245
paulo@0 246 typedef struct LJSpeedSetting {
paulo@0 247 LJFixed gravity;
paulo@0 248 unsigned char entryDelay, dasDelay, lockDelay, lineDelay;
paulo@0 249 } LJSpeedSetting;
paulo@0 250
paulo@0 251 typedef struct SpeedStateBase {
paulo@0 252 unsigned char curve, section;
paulo@0 253 unsigned char pad[2];
paulo@0 254 signed int level;
paulo@0 255 } SpeedStateBase;
paulo@0 256
paulo@0 257 #define MAX_BAG_LEN 10
paulo@0 258 #define MAX_OMINO 4
paulo@0 259
paulo@0 260 typedef struct LJField
paulo@0 261 {
paulo@0 262 /* Game state */
paulo@0 263 LJBlock b[LJ_PF_HT][LJ_PF_WID];
paulo@0 264 LJBlock c[LJ_PF_HT][LJ_PF_WID];
paulo@0 265 LJBits clearedLines;
paulo@0 266 LJBits sounds;
paulo@0 267 LJBits tempRows;
paulo@0 268 unsigned char curPiece[1 + LJ_NEXT_PIECES];
paulo@0 269 signed char permuPiece[2 * MAX_BAG_LEN], permuPhase;
paulo@0 270 unsigned short nLineClears[LJ_MAX_LINES_PER_PIECE]; // [n-1] = # of n-line clears
paulo@0 271 LJFixed y;
paulo@0 272 LJState state;
paulo@0 273 signed char stateTime;
paulo@0 274 unsigned char theta;
paulo@0 275 signed char x;
paulo@0 276 signed char hardDropY;
paulo@0 277 char alreadyHeld;
paulo@0 278 char isSpin;
paulo@0 279 char nLinesThisPiece;
paulo@0 280 char canRotate;
paulo@0 281 unsigned char upwardKicks;
paulo@0 282
paulo@0 283 /* Persist from piece to piece */
paulo@0 284 int score, lines;
paulo@0 285 unsigned int gameTime; // number of frames
paulo@0 286 unsigned int activeTime; // number of frames
paulo@0 287 signed short holdPiece;
paulo@0 288 char chain;
paulo@0 289 signed char garbage;
paulo@0 290 unsigned char dropDist;
paulo@0 291 unsigned char garbageX;
paulo@0 292 unsigned short nPieces, outGarbage;
paulo@0 293 unsigned short monosquares, multisquares;
paulo@0 294
paulo@0 295 /* Determined by gimmick */
paulo@0 296 signed char gimmick;
paulo@0 297 signed int bpmCounter;
paulo@0 298 unsigned int speedupCounter;
paulo@0 299 unsigned int goalCount;
paulo@0 300 unsigned int seed;
paulo@0 301 unsigned char goalType;
paulo@0 302
paulo@0 303 LJSpeedSetting speed;
paulo@0 304 SpeedStateBase speedState;
paulo@0 305
paulo@0 306 unsigned char lockReset; // lockdown reset rule type
paulo@0 307 unsigned char areStyle;
paulo@0 308 unsigned char setLockDelay; // Overridden lock delay (255 = never)
paulo@0 309 unsigned char setLineDelay; // Overridden line delay
paulo@0 310 unsigned char garbageStyle;
paulo@0 311 unsigned char ceiling;
paulo@0 312 unsigned char enterAbove;
paulo@0 313 unsigned char leftWall, rightWall;
paulo@0 314 unsigned char pieceSet;
paulo@0 315 unsigned char randomizer;
paulo@0 316 unsigned char rotationSystem;
paulo@0 317 unsigned char garbageRandomness; // 64: change garbageX in 1/4 of rows; 255: change all
paulo@0 318 unsigned char tSpinAlgo; // 0: off, 1: TNT, 2: TDS
paulo@0 319 unsigned char clearGravity;
paulo@0 320 unsigned char gluing; // 0: off; 1: square
paulo@0 321 unsigned char scoreStyle;
paulo@0 322 unsigned char dropScoreStyle;
paulo@0 323 unsigned char maxUpwardKicks;
paulo@0 324 unsigned char holdStyle;
paulo@0 325 unsigned char bottomBlocks;
paulo@0 326 unsigned char reloaded; // 0: played through; 1: reloaded from saved state
paulo@0 327 } LJField;
paulo@0 328
paulo@0 329 /**
paulo@0 330 * Names of the supported rotation systems (wktables.c).
paulo@0 331 */
paulo@0 332 enum {
paulo@0 333 LJROT_SRS,
paulo@0 334 LJROT_SEGA,
paulo@0 335 LJROT_ARIKA,
paulo@0 336 LJROT_ATARI,
paulo@0 337 LJROT_NES,
paulo@0 338 LJROT_GB,
paulo@0 339 LJROT_TOD,
paulo@0 340 LJROT_TDX,
paulo@0 341 N_ROTATION_SYSTEMS
paulo@0 342 };
paulo@0 343
paulo@0 344 #define N_PIECE_SHAPES 10
paulo@0 345 #define KICK_TABLE_LEN 5
paulo@0 346 extern const char pieceColors[N_PIECE_SHAPES];
paulo@0 347 typedef unsigned char WallKickTable[4][KICK_TABLE_LEN];
paulo@0 348 typedef struct LJRotSystem {
paulo@0 349 /**
paulo@0 350 * Color scheme for this rotation system (0: SRS; 1: Sega)
paulo@0 351 * Use colorset 0 (SRS) if all free-space kicks are WK(0, 0).
paulo@0 352 * Otherwise, your rotation system has what Eddie Rogers has called
paulo@0 353 * a topknot, and you should use Sega colors.
paulo@0 354 */
paulo@0 355 unsigned char colorScheme;
paulo@0 356 unsigned char reserved1[3];
paulo@0 357 unsigned char entryOffset[N_PIECE_SHAPES];
paulo@0 358 unsigned char entryTheta[N_PIECE_SHAPES];
paulo@0 359 /* These control which kick table is used for each piece.
paulo@0 360 * If negative, no kick table is present.
paulo@0 361 */
paulo@0 362 signed char kicksL[N_PIECE_SHAPES];
paulo@0 363 signed char kicksR[N_PIECE_SHAPES];
paulo@0 364 WallKickTable kickTables[];
paulo@0 365 } LJRotSystem;
paulo@0 366
paulo@0 367 extern const LJRotSystem *const rotSystems[N_ROTATION_SYSTEMS];
paulo@0 368
paulo@0 369 #ifdef LJ_INTERNAL
paulo@0 370 // Used for defining wall kick tables:
paulo@0 371 // WK(x, y) builds a 1-byte record with 2 coordinates, at 4 bits
paulo@0 372 // per coordinate.
paulo@0 373 // WKX() and WKY() retrieve the X or Y coordinate from this record.
paulo@0 374 // The ((stuff ^ 8) - 8) is sign extension magick
paulo@0 375 #define WK(x, y) (((x) & 0x0F) | ((y) & 0x0F) << 4)
paulo@0 376 #define WKX(wk) ((((wk) & 0x0F) ^ 8) - 8)
paulo@0 377 #define WKY(wk) WKX((wk) >> 4)
paulo@0 378 // If ARIKA_IF_NOT_CENTER is specified, check the free space
paulo@0 379 // rotation for blocks in columns other than 1, and stop if
paulo@0 380 // none of them are filled. This obsoletes the old SKIP_IF.
paulo@0 381 #define SKIP_IF 0x80
paulo@0 382 #define SKIP_IF3 0x82
paulo@0 383
paulo@0 384 #define ARIKA_IF_NOT_CENTER 0x83
paulo@0 385 #define WK_END 0x8F
paulo@0 386 #if 0
paulo@0 387 extern const WallKickTable *const wkTablesL[N_ROTATION_SYSTEMS][N_PIECE_SHAPES];
paulo@0 388 extern const WallKickTable *const wkTablesR[N_ROTATION_SYSTEMS][N_PIECE_SHAPES];
paulo@0 389 #endif
paulo@0 390 #endif
paulo@0 391
paulo@0 392 /**
paulo@0 393 * Expands a tetromino to the blocks that make it up.
paulo@0 394 * @param out an array of length 4
paulo@0 395 * @param p the field into which the tetromino will be spawned
paulo@0 396 * (used for default spawn orientation)
paulo@0 397 * @param piece a piece number
paulo@0 398 * @param xBase x coordinate of base position of the tetromino
paulo@0 399 * @param yBase y coordinate of base position of the tetromino
paulo@0 400 * @param theta the orientation of the tetromino
paulo@0 401 * (0-3: use this; 4: use default spawn rotation)
paulo@0 402 */
paulo@0 403 void expandPieceToBlocks(LJBlkSpec out[],
paulo@0 404 const LJField *p,
paulo@0 405 int piece, int xBase, int yBase, int theta);
paulo@0 406
paulo@0 407 /**
paulo@0 408 * Tests whether a particular block is occupied.
paulo@0 409 * @param p the playfield
paulo@0 410 * @param x the column
paulo@0 411 * @param y the row (0 = bottom)
paulo@0 412 * @return zero iff the space is open
paulo@0 413 */
paulo@0 414 int isOccupied(const LJField *p, int x, int y);
paulo@0 415
paulo@0 416 /**
paulo@0 417 * Tests whether a particular tetromino would overlap one or more
paulo@0 418 * blocks, a side wall, or the floor
paulo@0 419 * @param p the playfield
paulo@0 420 * @param x the column of the left side of the piece's bounding 4x4
paulo@0 421 * @param y the row of the bottom of the piece's bounding 4x4 (0 = bottom)
paulo@0 422 * @return zero iff the space is open
paulo@0 423 */
paulo@0 424 int isCollision(const LJField *p, int x, int y, int theta);
paulo@0 425
paulo@0 426 /**
paulo@0 427 * Blanks a playfield and prepares it for a new game.
paulo@0 428 * @param p the playfield
paulo@0 429 */
paulo@0 430 void newGame(LJField *p);
paulo@0 431
paulo@0 432 /**
paulo@0 433 * Runs one frame of S.M.G.
paulo@0 434 * @param p the playfield
paulo@0 435 * @param in the player's input
paulo@0 436 * @return the rows that were modified
paulo@0 437 */
paulo@0 438 LJBits frame(LJField *p, const LJInput *in);
paulo@0 439
paulo@0 440 /**
paulo@0 441 * Applies gimmicks to a new game.
paulo@0 442 * @param p the playfield
paulo@0 443 * @param in the player's input
paulo@0 444 */
paulo@0 445 void initGimmicks(LJField *p);
paulo@0 446
paulo@0 447 /**
paulo@0 448 * Runs gimmicks for one frame of S.M.G.
paulo@0 449 * @param p the playfield
paulo@0 450 * @param c the control settings
paulo@0 451 * @return the rows that were modified
paulo@0 452 */
paulo@0 453 struct LJControl;
paulo@0 454 LJBits gimmicks(LJField *p, struct LJControl *c);
paulo@0 455
paulo@0 456 /**
paulo@0 457 * Sets up the randomizer.
paulo@0 458 * @return the number of this piece
paulo@0 459 */
paulo@0 460 void initRandomize(LJField *p);
paulo@0 461
paulo@0 462 /**
paulo@0 463 * Chooses a pseudo-random piece.
paulo@0 464 * @param the field on which the piece will be generated
paulo@0 465 * @return the number of this piece
paulo@0 466 * (0=i, 1=j, 2=l, 3=o, 4=s, 5=t, 6=z)
paulo@0 467 */
paulo@0 468 unsigned int randomize(LJField *p);
paulo@0 469
paulo@0 470 /**
paulo@0 471 * Counts the number of 1 bits in a bitfield.
paulo@0 472 * @param p the bitfield
paulo@0 473 * @return the number of bits in p with a value of 1.
paulo@0 474 */
paulo@0 475 unsigned int countOnes(LJBits b);
paulo@0 476
paulo@0 477 /**
paulo@0 478 * Shuffles the columns of blocks in the playfield.
paulo@0 479 * @param p the playfield
paulo@0 480 */
paulo@0 481 void shuffleColumns(LJField *p);
paulo@0 482
paulo@0 483 /**
paulo@0 484 * Random number generator. Use this for all random events
paulo@0 485 * that affect the game state.
paulo@0 486 * @param field
paulo@0 487 * @return uniformly distributed number in 0 to 0x7FFF
paulo@0 488 */
paulo@0 489 unsigned int ljRand(LJField *p);
paulo@0 490
paulo@0 491 /**
paulo@0 492 * List of lines used for hotline scoring.
paulo@0 493 * A line clear completed at row hotlineRows[i] is worth 100*(i + 1).
paulo@0 494 */
paulo@0 495 extern const char hotlineRows[LJ_PF_HT];
paulo@0 496
paulo@0 497 /**
paulo@0 498 * Counts the number of trailing zero bits on an integer.
paulo@0 499 * For instance, 00000000 00000000 00000001 11111000
paulo@0 500 * has 3 trailing zeroes.
paulo@0 501 */
paulo@0 502 unsigned int bfffo(LJBits rowBits);
paulo@0 503
paulo@0 504 void setupZigzagField(LJField *p, size_t height);
paulo@0 505 unsigned int calcZigzagGrade(const LJField *p);
paulo@0 506
paulo@0 507 #endif