Mercurial > hg > index.fcgi > lj > lj046-2players
diff src/ljgbads.inc @ 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/ljgbads.inc Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,579 @@ 1.4 +/* DS/GBA frontend for LOCKJAW, an implementation of the Soviet Mind Game 1.5 + 1.6 +Copyright (C) 2006-2007 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 +#include "fontdraw.h" 1.29 + 1.30 +unsigned char wantPause; 1.31 +volatile char redrawWholeScreen = 0; 1.32 + 1.33 +void finishSprites(); 1.34 + 1.35 +void cls(void) { 1.36 + for (int y = 0; y < SCREEN_H; ++y) { 1.37 + for (int x = 0; x < SCREEN_W; ++x) { 1.38 + MAP[31][y][x] = ' '; 1.39 + } 1.40 + } 1.41 +} 1.42 + 1.43 +void drawFrame(LJView *v) { 1.44 + int left = v->field->leftWall; 1.45 + int right = v->field->rightWall; 1.46 + cls(); 1.47 + if (DS_PFTOP > 0) { 1.48 + for (int x = left - 1; x < right + 1; ++x) { 1.49 + MAP[31][DS_PFTOP - 1][DS_PFLEFT + x] = 0x8005; 1.50 + } 1.51 + } 1.52 + if (DS_PFTOP + LJ_PF_VIS_HT < SCREEN_H) { 1.53 + for (int x = left - 1; x < right + 1; ++x) { 1.54 + MAP[31][DS_PFTOP + LJ_PF_VIS_HT][DS_PFLEFT + x] = 0x8004; 1.55 + } 1.56 + } 1.57 + for (int i = 0; i < LJ_PF_VIS_HT; ++i) { 1.58 + MAP[31][i + DS_PFTOP][DS_PFLEFT + left - 1] = 0x8003; 1.59 + MAP[31][i + DS_PFTOP][DS_PFLEFT + right] = 0x8003; 1.60 + } 1.61 + textout("Score", 1, 6 + DS_PFTOP, 0); 1.62 + textout("Lines", 1, 8 + DS_PFTOP, 0); 1.63 + textout("Speed", 1, 10 + DS_PFTOP, 0); 1.64 +} 1.65 + 1.66 +static void drawBlock(struct LJPCView *unused, int x, int y, int b) { 1.67 + if (x >= 0 && x < LJ_PF_WID && y >= 0 && y < LJ_PF_VIS_HT) { 1.68 + int c; 1.69 + 1.70 + if (b == 0x100) { 1.71 + c = '-'; 1.72 + } else if (b == 0x110) { 1.73 + c = 0x8005; // ceiling tile 1.74 + } else if (b >= 0xA0 && b < 0xC0) { 1.75 + c = (b & 0xF0) << 8 | (b & 0x0F) | 0x100; 1.76 + } else if (b >= 0x10) { 1.77 + c = (b & 0xF0) << 8 | (b & 0x0F) | 0x10; 1.78 + } else { 1.79 + c = ' '; 1.80 + } 1.81 + MAP[31][DS_PFTOP + LJ_PF_VIS_HT - 1 - y][DS_PFLEFT + x] = c; 1.82 + } 1.83 +} 1.84 + 1.85 +void updField(const LJView *const v, LJBits rows) { 1.86 + const LJField *const p = v->field; 1.87 + 1.88 + for (int y = 0; 1.89 + y < LJ_PF_VIS_HT && rows != 0; 1.90 + ++y, rows >>= 1) { 1.91 + int blankTile = 0; 1.92 + 1.93 + if (y == p->ceiling) { 1.94 + blankTile = 0x110; 1.95 + } else if (hotlineRows[y] && v->field->scoreStyle == LJSCORE_HOTLINE) { 1.96 + blankTile = 0x100; 1.97 + } 1.98 + if (p->state == LJS_LINES_FALLING && p->stateTime > 0 1.99 + && ((1 << y) & p->tempRows)) { 1.100 + blankTile = 0x100; 1.101 + } 1.102 + if (rows & 1) { 1.103 + for (int x = p->leftWall; x < p->rightWall; x++) { 1.104 + int b = v->hidePF ? 0 : p->b[y][x]; 1.105 + drawBlock(v->plat, x, y, b ? b : blankTile); 1.106 + } 1.107 + } 1.108 + } 1.109 +} 1.110 + 1.111 +void blitField(LJView *v) { 1.112 + 1.113 +} 1.114 + 1.115 +int getTime() { 1.116 + return curTime; 1.117 +} 1.118 + 1.119 +#if !defined(DISP_VBLANK_IRQ) 1.120 +#define DISP_VBLANK_IRQ LCDC_VBL 1.121 +#endif 1.122 +#if !defined(IRQ_HANDLER) 1.123 +#define IRQ_HANDLER INT_VECTOR 1.124 +#endif 1.125 + 1.126 +void install_timer(void) 1.127 +{ 1.128 + 1.129 + // Turn off interrupts before doing anything 1.130 + REG_IME = 0; 1.131 + 1.132 + // Overwrite the ISR 1.133 + IRQ_HANDLER = isr; 1.134 + 1.135 + // Hook up the interrupt destination 1.136 + REG_IE = IRQ_VBLANK; 1.137 + 1.138 + // Acknowledge all pending interrupts 1.139 + REG_IF = ~0; 1.140 + 1.141 + // Set up an interrupt source 1.142 + REG_DISPSTAT = DISP_VBLANK_IRQ; 1.143 + 1.144 + // Turn interrupts back on 1.145 + REG_IME = 1; 1.146 +} 1.147 + 1.148 +void yieldCPU(void) { 1.149 + // we're not multitasking so we don't need this 1.150 + // on the GBA and DS, vsync() does all the waiting we need 1.151 +} 1.152 + 1.153 +static void upcvt_4bit(void *dst, const u8 *src, size_t len) 1.154 +{ 1.155 + u32 *out = dst; 1.156 + 1.157 + for(; len > 0; len--) 1.158 + { 1.159 + u32 dst_bits = 0; 1.160 + u32 src_bits = *src++; 1.161 + u32 x; 1.162 + 1.163 + for(x = 0; x < 8; x++) 1.164 + { 1.165 + dst_bits <<= 4; 1.166 + dst_bits |= src_bits & 1; 1.167 + src_bits >>= 1; 1.168 + } 1.169 + *out++ = dst_bits; 1.170 + } 1.171 +} 1.172 + 1.173 +extern const unsigned char text_chr[]; 1.174 +extern const unsigned int text_chr_size; 1.175 +extern const unsigned char gbablk_chr[]; 1.176 +extern const unsigned int gbablk_chr_size; 1.177 + 1.178 +static void loadOneConnection(void *in_dst, const void *in_src) { 1.179 + u16 *dst = in_dst; 1.180 + const u16 *src = in_src; 1.181 + for (unsigned int conn = 0; conn < 16; ++conn) { 1.182 + unsigned int topSegY = (conn & CONNECT_U) ? 32 : 0; 1.183 + unsigned int botSegY = (conn & CONNECT_D) ? 8 : 40; 1.184 + unsigned int leftSegX = (conn & CONNECT_L) ? 16 : 0; 1.185 + unsigned int rightSegX = (conn & CONNECT_R) ? 1 : 17; 1.186 + for (unsigned int i = 0; i < 8; i += 2) { 1.187 + *dst++ = src[leftSegX + topSegY + i]; 1.188 + *dst++ = src[rightSegX + topSegY + i]; 1.189 + } 1.190 + for (unsigned int i = 0; i < 8; i += 2) { 1.191 + *dst++ = src[leftSegX + botSegY + i]; 1.192 + *dst++ = src[rightSegX + botSegY + i]; 1.193 + } 1.194 + } 1.195 +} 1.196 + 1.197 +static void loadConnections(void) { 1.198 + loadOneConnection(PATRAM4(0, 16), gbablk_chr + 8*32); 1.199 + loadOneConnection(PATRAM4(0, 256), gbablk_chr + 12*32); 1.200 +} 1.201 + 1.202 +static void load_font(void) { 1.203 + upcvt_4bit(PATRAM4(0, 0), text_chr, text_chr_size); 1.204 + memcpy(PATRAM4(0, 0), gbablk_chr, 8*32); 1.205 + memcpy(SPR_VRAM(0), gbablk_chr, 8*32); 1.206 + loadConnections(); 1.207 +} 1.208 + 1.209 +void textout(const char *str, int x, int y, int c) { 1.210 + u16 *dst = &(MAP[31][y][x]); 1.211 + int spacesLeft = SCREEN_W - x; 1.212 + 1.213 + c <<= 12; 1.214 + while (*str != 0 && spacesLeft > 0) { 1.215 + *dst++ = c | *(unsigned char *)str++; 1.216 + --spacesLeft; 1.217 + } 1.218 +} 1.219 + 1.220 +static const u16 srsColors[12] = { 1.221 + RGB5(2, 2, 2), 1.222 + RGB5(0, 3, 3), 1.223 + RGB5(0, 0, 3), 1.224 + RGB5(3, 2, 0), 1.225 + RGB5(3, 3, 0), 1.226 + RGB5(0, 3, 0), 1.227 + RGB5(2, 0, 3), 1.228 + RGB5(3, 0, 0), 1.229 + RGB5(2, 2, 2), 1.230 + RGB5(3, 0, 0), 1.231 + RGB5(2, 2, 2), 1.232 + RGB5(3, 2, 1), 1.233 +}; 1.234 + 1.235 +static const u16 arsColors[12] = { 1.236 + RGB5(2, 2, 2), 1.237 + RGB5(3, 1, 0), 1.238 + RGB5(0, 0, 3), 1.239 + RGB5(3, 2, 0), 1.240 + RGB5(3, 3, 0), 1.241 + RGB5(2, 0, 3), 1.242 + RGB5(0, 3, 3), 1.243 + RGB5(0, 3, 0), 1.244 + RGB5(2, 2, 2), 1.245 + RGB5(3, 0, 0), 1.246 + RGB5(2, 2, 2), 1.247 + RGB5(3, 2, 1), 1.248 +}; 1.249 + 1.250 +void setupPalette(const u16 *colors) { 1.251 + for (int i = 1; i < 12; ++i) { 1.252 + int c = colors[i]; 1.253 + 1.254 + BG_PALETTE[i * 16 + 1] = RGB5(22,22,22) + 3 * c; 1.255 + BG_PALETTE[i * 16 + 2] = RGB5(13,13,13) + 6 * c; 1.256 + BG_PALETTE[i * 16 + 3] = RGB5( 4, 4, 4) + 9 * c; 1.257 + BG_PALETTE[i * 16 + 4] = RGB5( 4, 4, 4) + 7 * c; 1.258 + BG_PALETTE[i * 16 + 5] = RGB5( 4, 4, 4) + 5 * c; 1.259 + BG_PALETTE[i * 16 + 6] = RGB5( 4, 4, 4) + 3 * c; 1.260 + } 1.261 + memcpy(SPRITE_PALETTE, BG_PALETTE, 12 * 32); 1.262 +} 1.263 + 1.264 +// libnds style wrapper around libgba header 1.265 +#ifndef DISPLAY_BG0_ACTIVE 1.266 +#define DISPLAY_BG0_ACTIVE BG0_ON 1.267 +#define DISPLAY_SPR_ACTIVE OBJ_ON 1.268 +#define MODE_0_2D MODE_0 1.269 +#define DISPLAY_SPR_1D_LAYOUT OBJ_1D_MAP 1.270 +static inline void videoSetMode(int x) { 1.271 + REG_DISPCNT = x; 1.272 +} 1.273 + 1.274 +#endif 1.275 + 1.276 +void waitForStart(void) { 1.277 + LJBits lastJ = ~0; 1.278 + LJBits jnew = 0; 1.279 + 1.280 + do { 1.281 + LJBits j = ~REG_KEYINPUT; 1.282 + jnew = j & ~lastJ; 1.283 + lastJ = j; 1.284 + vsync(); 1.285 + } while(!(jnew & (KEY_A | KEY_START))); 1.286 +} 1.287 + 1.288 + 1.289 +static const char *const coprNoticeLines[] = { 1.290 + "LOCKJAW: The Reference", 1.291 + "Version "LJ_VERSION, 1.292 + NULL, 1.293 + "© 2008 Damian Yerrick", 1.294 + "Not sponsored or endorsed by Nintendo", 1.295 + "or Tetris Holding.", 1.296 + "Comes with ABSOLUTELY NO WARRANTY.", 1.297 + "This is free software, and you are welcome", 1.298 + "to share it under the conditions described", 1.299 + "in GPL.txt." 1.300 +}; 1.301 + 1.302 +void coprNotice(void) { 1.303 + videoSetMode(MODE_0_2D); 1.304 + BGCTRL[0] = BG_TILE_BASE(0) | BG_MAP_BASE(31); 1.305 + BG_OFFSET[0].x = 0; 1.306 + BG_OFFSET[0].y = 0; 1.307 + 1.308 + BG_PALETTE[0] = RGB5(31,31,31); 1.309 + BG_PALETTE[1] = RGB5(20,20,20); 1.310 + BG_PALETTE[2] = RGB5( 0, 0, 0); 1.311 + vwfWinInit(&vwfTop); 1.312 + for (int i = 0, y = 8; 1.313 + i < sizeof(coprNoticeLines) / sizeof(coprNoticeLines[0]); 1.314 + ++i) { 1.315 + if (coprNoticeLines[i]) { 1.316 + vwfPuts(&vwfTop, coprNoticeLines[i], 8, y); 1.317 + y += 12; 1.318 + } else { 1.319 + y += 6; 1.320 + } 1.321 + } 1.322 + vwfPuts(&vwfTop, "Press Start", 8, SCREEN_H * 8 - 16); 1.323 + videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE); 1.324 + waitForStart(); 1.325 +} 1.326 + 1.327 +LJBits menuReadPad(void) { 1.328 + LJBits keys = readPad(0); 1.329 + if (keys & VKEY_START) { 1.330 + keys |= VKEY_ROTR; 1.331 + } 1.332 + return keys; 1.333 +} 1.334 + 1.335 +void ljBeginDraw(LJView *v, int sync) { 1.336 + vsync(); 1.337 + finishSprites(); 1.338 +} 1.339 + 1.340 +void ljEndDraw(LJView *v) { 1.341 + 1.342 +} 1.343 + 1.344 +/* Replay stubs */ 1.345 +void replayRecord(struct LJReplay *r, LJBits keys, const LJInput *in) { 1.346 + 1.347 +} 1.348 + 1.349 +void replayClose(struct LJReplay *r) { 1.350 + 1.351 +} 1.352 + 1.353 +int getReplayFrame(struct LJReplay *r, LJInput *d) { 1.354 + return 0; 1.355 +} 1.356 + 1.357 +#define READY_GO_LINE 13 1.358 + 1.359 +void startingAnimation(LJView *v) { 1.360 + vsync(); 1.361 + gba_poll_sound(v->plat); 1.362 + setupPalette(rotSystems[v->field->rotationSystem]->colorScheme ? arsColors : srsColors); 1.363 + videoSetMode(MODE_0_2D); 1.364 + cls(); 1.365 + load_font(); 1.366 + BG_PALETTE[0] = RGB5(31,31,31); 1.367 + BG_PALETTE[1] = RGB5( 0, 0, 0); 1.368 + drawFrame(v); 1.369 + finishSprites(); 1.370 + vsync(); 1.371 + gba_poll_sound(v->plat); 1.372 + videoSetMode(MODE_0_2D 1.373 + | DISPLAY_BG0_ACTIVE); 1.374 + BGCTRL[0] = BG_TILE_BASE(0) | BG_MAP_BASE(31); 1.375 + BG_OFFSET[0].x = 0; 1.376 + BG_OFFSET[0].y = 0; 1.377 + 1.378 + textout("Ready", 1.379 + (LJ_PF_WID - 5) / 2 + DS_PFLEFT, 1.380 + DS_PFTOP + LJ_PF_VIS_HT - 1 - READY_GO_LINE, 1.381 + 0); 1.382 + for (int i = 0; i < 30; ++i) { 1.383 + vsync(); 1.384 + gba_poll_sound(v->plat); 1.385 + } 1.386 + v->backDirty = ~0; 1.387 + updField(v, ~0); 1.388 + videoSetMode(MODE_0_2D 1.389 + | DISPLAY_BG0_ACTIVE 1.390 + | DISPLAY_SPR_1D_LAYOUT 1.391 + | DISPLAY_SPR_ACTIVE); 1.392 + drawScore(v); 1.393 + finishSprites(); 1.394 + 1.395 + textout(" GO! ", 1.396 + (LJ_PF_WID - 5) / 2 + DS_PFLEFT, 1.397 + DS_PFTOP + LJ_PF_VIS_HT - 1 - READY_GO_LINE, 1.398 + 0); 1.399 + for (int i = 0; i < 30; ++i) { 1.400 + vsync(); 1.401 + gba_poll_sound(v->plat); 1.402 + } 1.403 + drawFrame(v); 1.404 + wantPause = 0; 1.405 + 1.406 +#ifdef ARM9 1.407 + tb.cmd = TALKBACK_PLAY_MUSIC; 1.408 +#endif 1.409 +} 1.410 + 1.411 +int pauseGame(struct LJPCView *v) { 1.412 + LJBits lastKeys = ~0; 1.413 + int unpaused = 0; 1.414 + int canceled = 0; 1.415 + 1.416 + // hide playfield 1.417 + for (int y = DS_PFTOP; y < DS_PFTOP + LJ_PF_VIS_HT; ++y) { 1.418 + for (int x = DS_PFLEFT; 1.419 + x < DS_PFLEFT + LJ_PF_WID; 1.420 + ++x) { 1.421 + MAP[31][y][x] = ' '; 1.422 + } 1.423 + } 1.424 + textout("Game", 2 + DS_PFLEFT, 6 + DS_PFTOP, 0); 1.425 + textout("Paused", 2 + DS_PFLEFT, 7 + DS_PFTOP, 0); 1.426 + textout("Start:", 2 + DS_PFLEFT, 10 + DS_PFTOP, 0); 1.427 + textout("Resume", 2 + DS_PFLEFT, 11 + DS_PFTOP, 0); 1.428 + textout("Select:", 2 + DS_PFLEFT, 13 + DS_PFTOP, 0); 1.429 + textout("Exit", 2 + DS_PFLEFT, 14 + DS_PFTOP, 0); 1.430 + 1.431 +#ifdef ARM9 1.432 + tb.cmd = TALKBACK_PAUSE_MUSIC; 1.433 +#endif 1.434 + while (!unpaused || (lastKeys & (KEY_SELECT | KEY_START))) { 1.435 + int keys = ~REG_KEYINPUT; 1.436 + if (keys & ~lastKeys & KEY_START) { 1.437 + unpaused = 1; 1.438 + } 1.439 + if (keys & ~lastKeys & KEY_SELECT) { 1.440 + unpaused = 1; 1.441 + canceled = 1; 1.442 + } 1.443 + finishSprites(); 1.444 + vsync(); 1.445 + gba_poll_sound(v); 1.446 + lastKeys = keys; 1.447 + } 1.448 +#ifdef ARM9 1.449 + tb.cmd = TALKBACK_PLAY_MUSIC; 1.450 +#endif 1.451 + return canceled; 1.452 +} 1.453 + 1.454 +int ljHandleConsoleButtons(LJView *v) { 1.455 + LJBits keys = ~REG_KEYINPUT; 1.456 + int canceled = 0; 1.457 + 1.458 + wantPause |= !!(keys & KEY_START); 1.459 + if (wantPause) { 1.460 + canceled = pauseGame(v->plat); 1.461 + wantPause = 0; 1.462 + drawFrame(v); 1.463 + v->backDirty = ~0; 1.464 + } 1.465 + return canceled; 1.466 +} 1.467 + 1.468 +LJBits drawPiece(LJView *const v, void *const b, 1.469 + int piece, int x, int y, int theta, 1.470 + int color, int w, int h); 1.471 + 1.472 +void drawFallingPiece(LJView *v) { 1.473 + LJBits bits = 0; 1.474 + const LJField *const p = v->field; 1.475 + int piece = p->curPiece[0]; 1.476 + int y = ljfixfloor(p->y); 1.477 + const int w = 8; 1.478 + const int h = 8; 1.479 + int drawnY = v->smoothGravity ? ljfixfloor(h * p->y) : h * y; 1.480 + const int color = (p->state == LJS_LANDED) 1.481 + ? -128 - ((p->stateTime + 1) * 128 / (p->speed.lockDelay + 1)) 1.482 + : pieceColors[piece]; 1.483 + 1.484 + bits = drawPiece(v, NULL, piece, 1.485 + w * (p->x + DS_PFLEFT), 1.486 + h * (LJ_PF_VIS_HT + DS_PFTOP) - drawnY, 1.487 + p->theta, 1.488 + color, w, h); 1.489 + bits = (y >= 0) ? bits << y : bits >> -y; 1.490 + bits &= (1 << LJ_PF_VIS_HT) - 1; 1.491 + 1.492 + v->backDirty |= bits | (bits << 1); 1.493 + v->frontDirty |= bits | (bits << 1); 1.494 +} 1.495 + 1.496 +#define SHADOW_BLOCK 0x00 1.497 + 1.498 +void drawShadow(LJView *v) { 1.499 + LJBits bits = 0; 1.500 + const LJField *const p = v->field; 1.501 + int piece = p->curPiece[0]; 1.502 + int y = p->hardDropY; 1.503 + const int w = 8; 1.504 + const int h = 8; 1.505 + 1.506 + bits = drawPiece(v, NULL, piece, 1.507 + w * (p->x + DS_PFLEFT), 1.508 + h * (LJ_PF_VIS_HT + DS_PFTOP - y), 1.509 + p->theta, 1.510 + SHADOW_BLOCK, w, h); 1.511 + bits = (y >= 0) ? bits << y : bits >> -y; 1.512 + bits &= (1 << LJ_PF_VIS_HT) - 1; 1.513 + 1.514 + v->backDirty |= bits; 1.515 + v->frontDirty |= bits; 1.516 +} 1.517 + 1.518 +void drawNextPieces(LJView *v) { 1.519 + int holdPieceColor = v->field->alreadyHeld 1.520 + ? 0x80 1.521 + : pieceColors[v->field->holdPiece]; 1.522 + 1.523 + // Draw hold piece 1.524 + drawPiece(v, NULL, 1.525 + v->field->holdPiece, 1.526 + (DS_PFLEFT - 5) * 8, (DS_PFTOP + 5) * 8, 4, 1.527 + holdPieceColor, 8, 8); 1.528 + 1.529 + // Draw next pieces 1.530 + int y = 32 + 8 * DS_PFTOP; 1.531 + int x = (DS_PFLEFT + LJ_PF_WID) * 8; 1.532 + for(int i = 1; i <= v->nextPieces; ++i) { 1.533 + int piece = v->field->curPiece[i]; 1.534 + 1.535 + if (!v->hideNext) { 1.536 + drawPiece(v, NULL, 1.537 + piece, x, y, 4, 1.538 + pieceColors[piece], 8, 8); 1.539 + } 1.540 + y += 20; 1.541 + } 1.542 + v->frontDirty &= (1 << LJ_PF_VIS_HT) - 1; 1.543 +} 1.544 + 1.545 +void drawScore(LJView *v) { 1.546 + char txt[16]; 1.547 + int tpm = -1; 1.548 + int lvl = v->field->speedState.level; 1.549 + 1.550 + siprintf(txt, "%8u", v->field->score); 1.551 + textout(txt, 0, 7 + DS_PFTOP, 0); 1.552 + siprintf(txt, "%8u", v->field->lines); 1.553 + textout(txt, 0, 9 + DS_PFTOP, 0); 1.554 + 1.555 + if (lvl > 0) { 1.556 + textout("Level:", 1, SCREEN_H - 3, 0); 1.557 + siprintf(txt, "%9u", lvl); 1.558 + textout(txt, 0, SCREEN_H - 2, 0); 1.559 + } 1.560 + 1.561 + if (v->nLockTimes >= 2) { 1.562 + int time = v->lockTime[0] - v->lockTime[v->nLockTimes - 1]; 1.563 + if (time > 0) { 1.564 + tpm = 3600 * (v->nLockTimes - 1) / time; 1.565 + } 1.566 + } 1.567 + if (tpm > 0) { 1.568 + siprintf(txt, "%8d", tpm); 1.569 + textout(txt, 0, 11 + DS_PFTOP, 0); 1.570 + } else { 1.571 + textout(" ---", 0, 11 + DS_PFTOP, 0); 1.572 + } 1.573 + 1.574 + { 1.575 + int seconds = v->field->gameTime / 60; 1.576 + int minutes = seconds / 60; 1.577 + seconds -= minutes * 60; 1.578 + siprintf(txt, "%6d:%02d", minutes, seconds); 1.579 + textout(txt, 0, SCREEN_H - 1, 0); 1.580 + } 1.581 + drawNextPieces(v); 1.582 +}