rev |
line source |
paulo@0
|
1 /* PC frontend for LOCKJAW, an implementation of the Soviet Mind Game
|
paulo@0
|
2
|
paulo@0
|
3 Copyright (C) 2006-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 #include "ljpc.h"
|
paulo@0
|
26 #include "ljreplay.h"
|
paulo@0
|
27 #include <jpgalleg.h>
|
paulo@0
|
28 #include <time.h>
|
paulo@0
|
29 #include "scenario.h"
|
paulo@0
|
30 #include "ljpath.h"
|
paulo@0
|
31
|
paulo@0
|
32 #if 1
|
paulo@0
|
33 #define LJ_VERSION "0.46a ("__DATE__")"
|
paulo@0
|
34 #else
|
paulo@0
|
35 #define LJ_VERSION "WIP ("__DATE__")"
|
paulo@0
|
36 #endif
|
paulo@0
|
37
|
paulo@0
|
38 #define USE_PICS_FOLDER 0
|
paulo@0
|
39 #define MAX_PLAYERS 2
|
paulo@0
|
40 #define LJ_TICK_RATE 3600 // frames per minute
|
paulo@0
|
41
|
paulo@0
|
42 int bgColor, fgColor = 0, hiliteColor, pfBgColor = 0, pfFgColor;
|
paulo@0
|
43 static volatile int curTime = 0;
|
paulo@0
|
44 volatile char redrawWholeScreen = 1;
|
paulo@0
|
45 static volatile int wantPause = 0;
|
paulo@0
|
46 const DATAFILE *dat = NULL, *sound_dat = NULL;
|
paulo@0
|
47 const FONT *aver32 = NULL, *aver16 = NULL;
|
paulo@0
|
48 char withSound = 0;
|
paulo@0
|
49 char autoPause;
|
paulo@0
|
50 int refreshRate = 0;
|
paulo@0
|
51 char demoFilename[512];
|
paulo@0
|
52
|
paulo@0
|
53 int withPics = -1;
|
paulo@0
|
54
|
paulo@0
|
55 char skinName[PATH_MAX] = "default.skin";
|
paulo@0
|
56 char ljblocksSRSName[PATH_MAX];
|
paulo@0
|
57 char ljblocksSegaName[PATH_MAX];
|
paulo@0
|
58 char ljconnSRSName[PATH_MAX];
|
paulo@0
|
59 char ljconnSegaName[PATH_MAX];
|
paulo@0
|
60 char ljbgName[PATH_MAX];
|
paulo@0
|
61 char menubgName[PATH_MAX];
|
paulo@0
|
62 char bgmName[PATH_MAX];
|
paulo@0
|
63 char bgmRhythmName[PATH_MAX];
|
paulo@0
|
64 unsigned long int bgmLoopPoint = 0;
|
paulo@0
|
65 int bgmReadyGo = 0;
|
paulo@0
|
66 int bgmVolume = 128;
|
paulo@0
|
67 int skinW = 800;
|
paulo@0
|
68 int skinH = 600;
|
paulo@0
|
69
|
paulo@0
|
70
|
paulo@0
|
71
|
paulo@0
|
72
|
paulo@0
|
73 static void incCurTime(void) {
|
paulo@0
|
74 ++curTime;
|
paulo@0
|
75 } END_OF_FUNCTION(incCurTime);
|
paulo@0
|
76
|
paulo@0
|
77 static void amnesia(void) {
|
paulo@0
|
78 redrawWholeScreen = 1;
|
paulo@0
|
79 } END_OF_FUNCTION(amnesia);
|
paulo@0
|
80
|
paulo@0
|
81 static void requestPause(void) {
|
paulo@0
|
82 wantPause |= autoPause;
|
paulo@0
|
83 }
|
paulo@0
|
84
|
paulo@0
|
85
|
paulo@0
|
86 int getTime(void) {
|
paulo@0
|
87 return curTime;
|
paulo@0
|
88 }
|
paulo@0
|
89
|
paulo@0
|
90 void yieldCPU(void) {
|
paulo@0
|
91 rest(5);
|
paulo@0
|
92 }
|
paulo@0
|
93
|
paulo@0
|
94 void ljBeginDraw(LJView *v, int sync) {
|
paulo@0
|
95 vsync();
|
paulo@0
|
96 if (redrawWholeScreen) {
|
paulo@0
|
97 redrawWholeScreen = 0;
|
paulo@0
|
98 playRedrawScreen(v);
|
paulo@0
|
99 }
|
paulo@0
|
100
|
paulo@0
|
101 BITMAP *sc = v->plat->skin->fullback;
|
paulo@0
|
102
|
paulo@0
|
103 // Draw shape
|
paulo@0
|
104 blit(v->plat->skin->bg, sc, 0, 0, 0, 0, 48, 16);
|
paulo@0
|
105 if (v->control->replayDst) {
|
paulo@0
|
106
|
paulo@0
|
107 // circle: record
|
paulo@0
|
108 circlefill(sc, 8, 8, 7, fgColor);
|
paulo@0
|
109 textout_ex(sc, aver16, "Rec", 18, 2, fgColor, -1);
|
paulo@0
|
110 } else if (v->control->replaySrc) {
|
paulo@0
|
111
|
paulo@0
|
112 // triangle: play
|
paulo@0
|
113 for (int wid = 0; wid < 7; ++wid) {
|
paulo@0
|
114 hline(sc, 2, 2 + wid, wid * 2 + 3, fgColor);
|
paulo@0
|
115 hline(sc, 2, 14 - wid, wid * 2 + 3, fgColor);
|
paulo@0
|
116 }
|
paulo@0
|
117 textout_ex(sc, aver16, "Play", 18, 2, fgColor, -1);
|
paulo@0
|
118 } else {
|
paulo@0
|
119
|
paulo@0
|
120 // square: stop
|
paulo@0
|
121 rectfill(sc, 2, 2, 14, 14, fgColor);
|
paulo@0
|
122 }
|
paulo@0
|
123 blit(sc, screen, 0, 0, 0, 0, 48, 16);
|
paulo@0
|
124 }
|
paulo@0
|
125
|
paulo@0
|
126 void ljEndDraw(LJView *v) {
|
paulo@0
|
127
|
paulo@0
|
128 }
|
paulo@0
|
129
|
paulo@0
|
130 static void startRecording(LJView *v) {
|
paulo@0
|
131 withPics = -1;
|
paulo@0
|
132
|
paulo@0
|
133 // close existing playback
|
paulo@0
|
134 if (v->control->replaySrc) {
|
paulo@0
|
135 replayClose(v->control->replaySrc);
|
paulo@0
|
136 v->control->replaySrc = NULL;
|
paulo@0
|
137 }
|
paulo@0
|
138
|
paulo@0
|
139 // toggle recording
|
paulo@0
|
140 if (v->control->replayDst) {
|
paulo@0
|
141 replayClose(v->control->replayDst);
|
paulo@0
|
142 v->control->replayDst = NULL;
|
paulo@0
|
143 } else {
|
paulo@0
|
144 char path[PATH_MAX];
|
paulo@0
|
145
|
paulo@0
|
146 ljpathFind_w(path, "demo.ljm");
|
paulo@0
|
147 v->control->replayDst = newReplay(path, v->field);
|
paulo@0
|
148 #if USE_PICS_FOLDER
|
paulo@0
|
149 withPics = 0;
|
paulo@0
|
150 #endif
|
paulo@0
|
151 }
|
paulo@0
|
152 }
|
paulo@0
|
153
|
paulo@0
|
154 static void startPlaying(LJView *v) {
|
paulo@0
|
155 withPics = -1;
|
paulo@0
|
156
|
paulo@0
|
157 // close existing recording
|
paulo@0
|
158 if (v->control->replayDst) {
|
paulo@0
|
159 replayClose(v->control->replayDst);
|
paulo@0
|
160 v->control->replayDst = NULL;
|
paulo@0
|
161 }
|
paulo@0
|
162
|
paulo@0
|
163 // toggle playback
|
paulo@0
|
164 if (v->control->replaySrc) {
|
paulo@0
|
165 replayClose(v->control->replaySrc);
|
paulo@0
|
166 v->control->replaySrc = NULL;
|
paulo@0
|
167 } else {
|
paulo@0
|
168 char path[PATH_MAX];
|
paulo@0
|
169
|
paulo@0
|
170 if (ljpathFind_r(path, "demo.ljm")) {
|
paulo@0
|
171 v->control->replaySrc = openReplay(path, v->field);
|
paulo@0
|
172 }
|
paulo@0
|
173 v->nLockTimes = 0;
|
paulo@0
|
174 #if USE_PICS_FOLDER
|
paulo@0
|
175 withPics = 0;
|
paulo@0
|
176 #endif
|
paulo@0
|
177 }
|
paulo@0
|
178 v->backDirty = ~0;
|
paulo@0
|
179 v->field->reloaded = 1;
|
paulo@0
|
180 }
|
paulo@0
|
181
|
paulo@0
|
182 int ljHandleConsoleButtons(LJView *v) {
|
paulo@0
|
183 int canceled = 0;
|
paulo@0
|
184
|
paulo@0
|
185 while (keypressed()) {
|
paulo@0
|
186 int scancode;
|
paulo@0
|
187 int codepoint = ureadkey(&scancode);
|
paulo@0
|
188
|
paulo@0
|
189 if (scancode == KEY_ESC) {
|
paulo@0
|
190 wantPause = 1;
|
paulo@0
|
191 } else if (scancode == KEY_PRTSCR) {
|
paulo@0
|
192 saveScreen(-1);
|
paulo@0
|
193 save_bitmap("ljbackbuf.bmp", v->plat->skin->fullback, NULL);
|
paulo@0
|
194 } else if (codepoint == '[') {
|
paulo@0
|
195 v->plat->wantRecord = 1;
|
paulo@0
|
196 } else if (codepoint == ']') {
|
paulo@0
|
197 v->plat->wantRecord = 0;
|
paulo@0
|
198 startPlaying(v);
|
paulo@0
|
199 }
|
paulo@0
|
200 }
|
paulo@0
|
201 if (v->plat->wantRecord) {
|
paulo@0
|
202 v->plat->wantRecord = 0;
|
paulo@0
|
203 startRecording(v);
|
paulo@0
|
204 }
|
paulo@0
|
205 if (wantPause) {
|
paulo@0
|
206 canceled = pauseGame(v->plat);
|
paulo@0
|
207 wantPause = 0;
|
paulo@0
|
208 }
|
paulo@0
|
209
|
paulo@0
|
210 if (wantsClose) {
|
paulo@0
|
211 canceled = 1;
|
paulo@0
|
212 }
|
paulo@0
|
213
|
paulo@0
|
214 return canceled;
|
paulo@0
|
215 }
|
paulo@0
|
216
|
paulo@0
|
217
|
paulo@0
|
218 static void drawBlock(const LJPCView *const v, int x, int y, int blk) {
|
paulo@0
|
219
|
paulo@0
|
220 if (x >= 0 && x < LJ_PF_WID && y >= 0 && y < LJ_PF_VIS_HT) {
|
paulo@0
|
221 const int w = v->skin->blkW;
|
paulo@0
|
222 const int h = v->skin->blkH;
|
paulo@0
|
223 const int dstX = w * x;
|
paulo@0
|
224 const int dstY = h * (LJ_PF_VIS_HT - 1 - y);
|
paulo@0
|
225
|
paulo@0
|
226 if (v->skin->transparentPF && (blk == 0 || blk == 0x100)) {
|
paulo@0
|
227
|
paulo@0
|
228 // Copy background
|
paulo@0
|
229 const unsigned int srcX = dstX + v->baseX;
|
paulo@0
|
230 const unsigned int srcY = dstY + v->skin->baseY
|
paulo@0
|
231 - LJ_PF_VIS_HT * h - v->skin->pfElev;
|
paulo@0
|
232 blit(v->skin->bg, v->back, srcX, srcY, dstX, dstY, w, h);
|
paulo@0
|
233 } else if (blk && v->skin->connBlocks) {
|
paulo@0
|
234
|
paulo@0
|
235 // Copy connected block
|
paulo@0
|
236 const unsigned int srcX = ((blk >> 0) & 15) * w;
|
paulo@0
|
237 const unsigned int srcY = ((blk >> 4) & 15) * h;
|
paulo@0
|
238 blit(v->skin->connBlocks, v->back, srcX, srcY, dstX, dstY, w, h);
|
paulo@0
|
239 } else {
|
paulo@0
|
240
|
paulo@0
|
241 // Copy lone block
|
paulo@0
|
242 const unsigned int srcX = ((blk >> 4) & 7) * w;
|
paulo@0
|
243 const unsigned int srcY = ((blk >> 7) & 1) * h;
|
paulo@0
|
244 blit(v->skin->blocks, v->back, srcX, srcY, dstX, dstY, w, h);
|
paulo@0
|
245 }
|
paulo@0
|
246
|
paulo@0
|
247 // 0x100: hotline
|
paulo@0
|
248 if (blk & 0x100) {
|
paulo@0
|
249 hline(v->back, dstX, dstY + h / 2 - 1, dstX + w - 1, pfFgColor);
|
paulo@0
|
250 hline(v->back, dstX, dstY + h / 2 , dstX + w - 1, pfFgColor);
|
paulo@0
|
251 hline(v->back, dstX, dstY + h / 2 + 1, dstX + w - 1, pfBgColor);
|
paulo@0
|
252 }
|
paulo@0
|
253 }
|
paulo@0
|
254 }
|
paulo@0
|
255
|
paulo@0
|
256 /**
|
paulo@0
|
257 * Draws multiple rows of the playfield
|
paulo@0
|
258 * @param p the playfield
|
paulo@0
|
259 * @param rows the rows to be updated (0x00001 on bottom, 0x80000 on top)
|
paulo@0
|
260 */
|
paulo@0
|
261 void updField(const LJView *const v, LJBits rows) {
|
paulo@0
|
262 const LJField *const p = v->field;
|
paulo@0
|
263
|
paulo@0
|
264 acquire_bitmap(v->plat->back);
|
paulo@0
|
265 for (int y = 0;
|
paulo@0
|
266 y < LJ_PF_VIS_HT && rows != 0;
|
paulo@0
|
267 ++y, rows >>= 1) {
|
paulo@0
|
268 int blankTile = 0;
|
paulo@0
|
269
|
paulo@0
|
270 // hotline: draw 0x100 as the background
|
paulo@0
|
271 if (hotlineRows[y] && v->field->scoreStyle == LJSCORE_HOTLINE) {
|
paulo@0
|
272 blankTile = 0x100;
|
paulo@0
|
273 }
|
paulo@0
|
274 // during line clear delay, draw bars to show which lines were cleared
|
paulo@0
|
275 if (p->state == LJS_LINES_FALLING && p->stateTime > 0
|
paulo@0
|
276 && ((1 << y) & p->tempRows)) {
|
paulo@0
|
277 blankTile = 0x100;
|
paulo@0
|
278 }
|
paulo@0
|
279 if (rows & 1) {
|
paulo@0
|
280 for (int x = p->leftWall; x < p->rightWall; x++) {
|
paulo@0
|
281 int b = v->hidePF ? 0 : p->b[y][x];
|
paulo@0
|
282 drawBlock(v->plat, x, y, b ? b : blankTile);
|
paulo@0
|
283 }
|
paulo@0
|
284 }
|
paulo@0
|
285 }
|
paulo@0
|
286 release_bitmap(v->plat->back);
|
paulo@0
|
287 }
|
paulo@0
|
288
|
paulo@0
|
289
|
paulo@0
|
290 #define SHADOW_BLOCK 0x00
|
paulo@0
|
291
|
paulo@0
|
292 /**
|
paulo@0
|
293 * Draws a tetromino whose lower left corner of the bounding box is at (x, y)
|
paulo@0
|
294 * @param b the bitmap to draw to
|
paulo@0
|
295 * @param piece the piece to be drawn
|
paulo@0
|
296 * @param x distance from to left side of 4x4 box
|
paulo@0
|
297 * @param y distance from top of bitmap to bottom of 4x4 box
|
paulo@0
|
298 * @param the rotation state (0: U; 1: R; 2: D; 3: L; 4: Initial position)
|
paulo@0
|
299 * @param w width of each block
|
paulo@0
|
300 * @param h height of each block
|
paulo@0
|
301 * @param color Drawing style
|
paulo@0
|
302 * color == 0: draw shadow
|
paulo@0
|
303 * color == 0x10 through 0x70: draw in that color
|
paulo@0
|
304 * color == 0x80: draw as garbage
|
paulo@0
|
305 * color == -255 through -1: draw with 255 through 1 percent lighting
|
paulo@0
|
306 */
|
paulo@0
|
307 LJBits drawPiece(LJView *const v, BITMAP *const b,
|
paulo@0
|
308 int piece, int x, int y, int theta,
|
paulo@0
|
309 int color, int w, int h) {
|
paulo@0
|
310 // Don't try to draw the -1 that's the sentinel for no hold piece
|
paulo@0
|
311 if (piece < 0)
|
paulo@0
|
312 return 0;
|
paulo@0
|
313
|
paulo@0
|
314 LJBits rows = 0;
|
paulo@0
|
315 LJBlkSpec blocks[4];
|
paulo@0
|
316 const int srcW = v->plat->skin->blkW;
|
paulo@0
|
317 const int srcH = v->plat->skin->blkH;
|
paulo@0
|
318 BITMAP *singleBlocks = v->plat->skin->blocks;
|
paulo@0
|
319 int singleSeries = (color == 0
|
paulo@0
|
320 && singleBlocks->h >= 6 * srcH)
|
paulo@0
|
321 ? 4 : 2;
|
paulo@0
|
322
|
paulo@0
|
323 // color: 0 for shadow, >0 for piece
|
paulo@0
|
324 BITMAP *connBlocks = (color != SHADOW_BLOCK)
|
paulo@0
|
325 ? v->plat->skin->connBlocks : NULL;
|
paulo@0
|
326
|
paulo@0
|
327 BITMAP *transTemp = color < 0
|
paulo@0
|
328 || (color == SHADOW_BLOCK && v->hideShadow < LJSHADOW_COLORED)
|
paulo@0
|
329 ? create_bitmap(w, h) : 0;
|
paulo@0
|
330
|
paulo@0
|
331 if (transTemp) {
|
paulo@0
|
332 set_trans_blender(0, 0, 0, v->hideShadow ? 128 : 64);
|
paulo@0
|
333 }
|
paulo@0
|
334
|
paulo@0
|
335 expandPieceToBlocks(blocks, v->field, piece, 0, 0, theta);
|
paulo@0
|
336 acquire_bitmap(b);
|
paulo@0
|
337 for (int blk = 0; blk < 4; ++blk) {
|
paulo@0
|
338 int blkValue = blocks[blk].conn;
|
paulo@0
|
339
|
paulo@0
|
340 // If blkValue == 0 then the block is not part of the piece,
|
paulo@0
|
341 // such as if it's a domino or tromino or (once pentominoes
|
paulo@0
|
342 // are added) a tetromino.
|
paulo@0
|
343 if (blkValue) {
|
paulo@0
|
344 int blkX = blocks[blk].x;
|
paulo@0
|
345 int blkY = blocks[blk].y;
|
paulo@0
|
346 const int dstX = x + w * blkX;
|
paulo@0
|
347 const int dstY = y + h * (-1 - blkY);
|
paulo@0
|
348
|
paulo@0
|
349 if (color > 0) {
|
paulo@0
|
350 blkValue = color | (blkValue & CONNECT_MASK);
|
paulo@0
|
351 } else if (color == 0 && v->hideShadow == LJSHADOW_COLORLESS) {
|
paulo@0
|
352 blkValue = 0;
|
paulo@0
|
353 }
|
paulo@0
|
354
|
paulo@0
|
355 if (connBlocks) {
|
paulo@0
|
356 const unsigned int srcX = ((blkValue >> 0) & 15) * srcW;
|
paulo@0
|
357 const unsigned int srcY = ((blkValue >> 4) & 15) * srcH;
|
paulo@0
|
358
|
paulo@0
|
359 if (transTemp) {
|
paulo@0
|
360 stretch_blit(connBlocks, transTemp,
|
paulo@0
|
361 srcX, srcY, srcW, srcH,
|
paulo@0
|
362 0, 0, w, h);
|
paulo@0
|
363 if (color < 0) {
|
paulo@0
|
364 draw_lit_sprite(b, transTemp, dstX, dstY, color + 256);
|
paulo@0
|
365 } else {
|
paulo@0
|
366 draw_trans_sprite(b, transTemp, dstX, dstY);
|
paulo@0
|
367 }
|
paulo@0
|
368 } else if (srcW != w || srcH != h) {
|
paulo@0
|
369 stretch_blit(connBlocks, b,
|
paulo@0
|
370 srcX, srcY, srcW, srcH,
|
paulo@0
|
371 dstX, dstY, w, h);
|
paulo@0
|
372 if (dstY > 600) {
|
paulo@0
|
373 allegro_message("dstY = %d\n", dstY);
|
paulo@0
|
374 }
|
paulo@0
|
375 } else {
|
paulo@0
|
376 blit(connBlocks, b,
|
paulo@0
|
377 srcX, srcY,
|
paulo@0
|
378 dstX, dstY, w, h);
|
paulo@0
|
379 }
|
paulo@0
|
380 } else {
|
paulo@0
|
381 const unsigned int srcX = ((blkValue >> 4) & 7) * srcW;
|
paulo@0
|
382 const unsigned int srcY = (((blkValue >> 7) & 1) + singleSeries) * srcH;
|
paulo@0
|
383
|
paulo@0
|
384 if (transTemp) {
|
paulo@0
|
385 stretch_blit(singleBlocks, transTemp,
|
paulo@0
|
386 srcX, srcY, srcW, srcH,
|
paulo@0
|
387 0, 0, w, h);
|
paulo@0
|
388 if (color < 0) {
|
paulo@0
|
389 draw_lit_sprite(b, transTemp, dstX, dstY, color + 256);
|
paulo@0
|
390 } else {
|
paulo@0
|
391 draw_trans_sprite(b, transTemp, dstX, dstY);
|
paulo@0
|
392 }
|
paulo@0
|
393 } else {
|
paulo@0
|
394 stretch_blit(singleBlocks, b,
|
paulo@0
|
395 srcX, srcY, srcW, srcH,
|
paulo@0
|
396 dstX, dstY, w, h);
|
paulo@0
|
397 }
|
paulo@0
|
398 }
|
paulo@0
|
399 rows |= 1 << blkY;
|
paulo@0
|
400 }
|
paulo@0
|
401 }
|
paulo@0
|
402 release_bitmap(b);
|
paulo@0
|
403 if (transTemp) {
|
paulo@0
|
404 solid_mode();
|
paulo@0
|
405 destroy_bitmap(transTemp);
|
paulo@0
|
406 }
|
paulo@0
|
407
|
paulo@0
|
408 return rows;
|
paulo@0
|
409 }
|
paulo@0
|
410
|
paulo@0
|
411 void drawPieceInPF(LJView *v, int dstX, LJFixed dstY, int theta, int color) {
|
paulo@0
|
412 LJBits bits = 0;
|
paulo@0
|
413 BITMAP *b = v->plat->back;
|
paulo@0
|
414 const LJField *const p = v->field;
|
paulo@0
|
415 int y = ljfixfloor(dstY);
|
paulo@0
|
416 const int w = v->plat->skin->blkW;
|
paulo@0
|
417 const int h = v->plat->skin->blkH;
|
paulo@0
|
418 int drawnY = fixmul(h, dstY);
|
paulo@0
|
419
|
paulo@0
|
420 bits = drawPiece(v, b, p->curPiece[0],
|
paulo@0
|
421 w * dstX, h * LJ_PF_VIS_HT - drawnY,
|
paulo@0
|
422 theta,
|
paulo@0
|
423 color, w, h);
|
paulo@0
|
424 bits = (y >= 0) ? bits << y : bits >> -y;
|
paulo@0
|
425 bits &= (1 << LJ_PF_VIS_HT) - 1;
|
paulo@0
|
426 if (dstY & 0xFFFF) {
|
paulo@0
|
427 bits |= bits << 1;
|
paulo@0
|
428 }
|
paulo@0
|
429
|
paulo@0
|
430 v->backDirty |= bits;
|
paulo@0
|
431 v->frontDirty |= bits;
|
paulo@0
|
432 }
|
paulo@0
|
433
|
paulo@0
|
434
|
paulo@0
|
435 void drawFallingPiece(LJView *v) {
|
paulo@0
|
436 const LJField *const p = v->field;
|
paulo@0
|
437 int piece = p->curPiece[0];
|
paulo@0
|
438 int y = v->smoothGravity
|
paulo@0
|
439 ? p->y
|
paulo@0
|
440 : ljitofix(ljfixfloor(p->y));
|
paulo@0
|
441 const int color = (p->state == LJS_LANDED)
|
paulo@0
|
442 ? -128 - ((p->stateTime + 1) * 128 / (p->speed.lockDelay + 1))
|
paulo@0
|
443 : pieceColors[piece];
|
paulo@0
|
444
|
paulo@0
|
445 // Draw trails
|
paulo@0
|
446 if (v->showTrails) {
|
paulo@0
|
447
|
paulo@0
|
448 // trail going up
|
paulo@0
|
449 while (v->trailY - y < ljitofix(-1)) {
|
paulo@0
|
450 v->trailY += ljitofix(1);
|
paulo@0
|
451 drawPieceInPF(v, p->x, v->trailY, p->theta, color);
|
paulo@0
|
452 }
|
paulo@0
|
453
|
paulo@0
|
454 // trail going down
|
paulo@0
|
455 while (v->trailY - y > ljitofix(1)) {
|
paulo@0
|
456 v->trailY -= ljitofix(1);
|
paulo@0
|
457 drawPieceInPF(v, p->x, v->trailY, p->theta, color);
|
paulo@0
|
458 }
|
paulo@0
|
459 }
|
paulo@0
|
460 drawPieceInPF(v, p->x, y, p->theta, color);
|
paulo@0
|
461 v->trailY = y;
|
paulo@0
|
462 }
|
paulo@0
|
463
|
paulo@0
|
464 void drawShadow(LJView *v) {
|
paulo@0
|
465 const LJField *const p = v->field;
|
paulo@0
|
466 int y = ljitofix(p->hardDropY);
|
paulo@0
|
467 const int color = SHADOW_BLOCK;
|
paulo@0
|
468 drawPieceInPF(v, p->x, y, p->theta, color);
|
paulo@0
|
469 }
|
paulo@0
|
470
|
paulo@0
|
471 void drawNextPieces(LJView *v) {
|
paulo@0
|
472 int baseX = v->plat->baseX;
|
paulo@0
|
473 int baseY = v->plat->skin->baseY - v->plat->skin->pfElev;
|
paulo@0
|
474 int blkW = v->plat->skin->blkW;
|
paulo@0
|
475 int blkH = v->plat->skin->blkH;
|
paulo@0
|
476 int holdPieceColor = v->field->alreadyHeld
|
paulo@0
|
477 ? 0x80
|
paulo@0
|
478 : pieceColors[v->field->holdPiece];
|
paulo@0
|
479 int ceil = v->field->ceiling;
|
paulo@0
|
480
|
paulo@0
|
481 BITMAP *sc = v->plat->skin->fullback;
|
paulo@0
|
482
|
paulo@0
|
483 if (v->frontDirty & LJ_DIRTY_NEXT) {
|
paulo@0
|
484 int holdW = blkW * 2 / 3;
|
paulo@0
|
485 int holdH = blkH * 2 / 3;
|
paulo@0
|
486 int holdX = baseX + blkW;
|
paulo@0
|
487 int holdY = baseY - (ceil - 1) * blkH - 4 * holdH;
|
paulo@0
|
488
|
paulo@0
|
489 // Move the hold piece within the screen
|
paulo@0
|
490 if (holdY < 0) {
|
paulo@0
|
491 holdY = 0;
|
paulo@0
|
492 }
|
paulo@0
|
493
|
paulo@0
|
494 // Draw hold piece
|
paulo@0
|
495 blit(v->plat->skin->bg, sc,
|
paulo@0
|
496 holdX, holdY,
|
paulo@0
|
497 holdX, holdY,
|
paulo@0
|
498 holdW * 4, holdH * 2);
|
paulo@0
|
499 drawPiece(v, sc,
|
paulo@0
|
500 v->field->holdPiece, holdX, holdY + 4 * holdH, 4,
|
paulo@0
|
501 holdPieceColor, holdW, holdH);
|
paulo@0
|
502 blit(sc, screen,
|
paulo@0
|
503 holdX, holdY,
|
paulo@0
|
504 holdX, holdY,
|
paulo@0
|
505 holdW * 4, holdH * 2);
|
paulo@0
|
506 }
|
paulo@0
|
507 // Draw next pieces
|
paulo@0
|
508
|
paulo@0
|
509 switch (v->plat->skin->nextPos) {
|
paulo@0
|
510 case LJNEXT_RIGHT:
|
paulo@0
|
511 case LJNEXT_RIGHT_TAPER:
|
paulo@0
|
512 if (v->frontDirty & LJ_DIRTY_NEXT) {
|
paulo@0
|
513 int y = baseY - ceil * blkH;
|
paulo@0
|
514 int x = baseX + LJ_PF_WID * blkW;
|
paulo@0
|
515 int w = blkW;
|
paulo@0
|
516 int h = blkH;
|
paulo@0
|
517 for (int i = 1; i <= v->nextPieces; ++i) {
|
paulo@0
|
518 int piece = v->field->curPiece[i];
|
paulo@0
|
519
|
paulo@0
|
520 blit(v->plat->skin->bg, sc, x, y, x, y, w * 4, h * 2);
|
paulo@0
|
521 if (!v->hideNext) {
|
paulo@0
|
522 drawPiece(v, sc,
|
paulo@0
|
523 piece, x, y + 4 * h, 4,
|
paulo@0
|
524 pieceColors[piece], w, h);
|
paulo@0
|
525 }
|
paulo@0
|
526 blit(sc, screen, x, y, x, y, w * 4, h * 2);
|
paulo@0
|
527 y += 8 + h * 2;
|
paulo@0
|
528 if (v->plat->skin->nextPos == LJNEXT_RIGHT_TAPER) {
|
paulo@0
|
529 --h;
|
paulo@0
|
530 --w;
|
paulo@0
|
531 }
|
paulo@0
|
532 }
|
paulo@0
|
533 }
|
paulo@0
|
534 break;
|
paulo@0
|
535
|
paulo@0
|
536 case LJNEXT_TOP:
|
paulo@0
|
537 if (v->frontDirty & LJ_DIRTY_NEXT) {
|
paulo@0
|
538 int y = baseY - (ceil + 2) * blkH - 8;
|
paulo@0
|
539 int x = baseX + 4 * blkW;
|
paulo@0
|
540 int blitX = x, blitY = y;
|
paulo@0
|
541
|
paulo@0
|
542 blit(v->plat->skin->bg, sc, x, y, x, y, blkW * 8, blkH * 2);
|
paulo@0
|
543 if (!v->hideNext) {
|
paulo@0
|
544 if (v->nextPieces >= 1) {
|
paulo@0
|
545 int piece = v->field->curPiece[1];
|
paulo@0
|
546 drawPiece(v, sc,
|
paulo@0
|
547 piece, x, y + 4 * blkH, 4,
|
paulo@0
|
548 pieceColors[piece], blkW, blkH);
|
paulo@0
|
549 }
|
paulo@0
|
550 if (v->nextPieces >= 2) {
|
paulo@0
|
551 int piece = v->field->curPiece[2];
|
paulo@0
|
552 x += 4 * blkW;
|
paulo@0
|
553 drawPiece(v, sc,
|
paulo@0
|
554 piece, x, y + 3 * blkH, 4,
|
paulo@0
|
555 pieceColors[piece], blkW/ 2, blkH / 2);
|
paulo@0
|
556 }
|
paulo@0
|
557 if (v->nextPieces >= 3) {
|
paulo@0
|
558 int piece = v->field->curPiece[3];
|
paulo@0
|
559 x += 2 * blkW;
|
paulo@0
|
560 drawPiece(v, sc,
|
paulo@0
|
561 piece, x, y + 3 * blkH, 4,
|
paulo@0
|
562 pieceColors[piece], blkW / 2, blkH / 2);
|
paulo@0
|
563 }
|
paulo@0
|
564 }
|
paulo@0
|
565 blit(sc, screen, blitX, blitY, blitX, blitY, blkW * 8, blkH * 2);
|
paulo@0
|
566 }
|
paulo@0
|
567 break;
|
paulo@0
|
568 }
|
paulo@0
|
569
|
paulo@0
|
570 if (v->plat->nextAbove && !v->hideNext) {
|
paulo@0
|
571 int row = (v->field->hardDropY + 4);
|
paulo@0
|
572 int x = (1 + v->field->x) * blkW;
|
paulo@0
|
573 for (int i = 1;
|
paulo@0
|
574 i <= v->plat->nextAbove
|
paulo@0
|
575 && row <= v->field->ceiling - 2;
|
paulo@0
|
576 ++i) {
|
paulo@0
|
577 int y = (LJ_PF_VIS_HT - row) * blkH;
|
paulo@0
|
578 int piece = v->field->curPiece[i];
|
paulo@0
|
579
|
paulo@0
|
580 drawPiece(v, v->plat->back,
|
paulo@0
|
581 piece, x, y, 4,
|
paulo@0
|
582 pieceColors[piece], blkW / 2, blkH / 2);
|
paulo@0
|
583 v->backDirty |= 3 << row;
|
paulo@0
|
584 row += 2;
|
paulo@0
|
585 }
|
paulo@0
|
586 }
|
paulo@0
|
587 v->frontDirty &= ~LJ_DIRTY_NEXT;
|
paulo@0
|
588 }
|
paulo@0
|
589
|
paulo@0
|
590 void drawScore(LJView *v) {
|
paulo@0
|
591 int gameTime = v->field->gameTime;
|
paulo@0
|
592 int seconds = gameTime / 60;
|
paulo@0
|
593 int minutes = seconds / 60;
|
paulo@0
|
594 int baseX = v->plat->baseX;
|
paulo@0
|
595 int tpm = -1;
|
paulo@0
|
596 int spawnLeft = v->plat->skin->blkW * LJ_SPAWN_X + baseX;
|
paulo@0
|
597 int pfRight = v->plat->skin->blkW * LJ_PF_WID + baseX;
|
paulo@0
|
598 BITMAP *sc = v->plat->skin->fullback;
|
paulo@0
|
599
|
paulo@0
|
600 if (withPics >= 0) {
|
paulo@0
|
601 if (v->field->nPieces != withPics) {
|
paulo@0
|
602 saveScreen(v->field->nPieces);
|
paulo@0
|
603 }
|
paulo@0
|
604 withPics = v->field->nPieces;
|
paulo@0
|
605 }
|
paulo@0
|
606
|
paulo@0
|
607 if (v->nLockTimes >= 2 ) {
|
paulo@0
|
608 int time = v->lockTime[0] - v->lockTime[v->nLockTimes - 1];
|
paulo@0
|
609 if (time > 0) {
|
paulo@0
|
610 tpm = 3600 * (v->nLockTimes - 1) / time;
|
paulo@0
|
611 }
|
paulo@0
|
612 }
|
paulo@0
|
613
|
paulo@0
|
614 if (v->frontDirty & LJ_DIRTY_SCORE) {
|
paulo@0
|
615 switch (v->plat->skin->nextPos) {
|
paulo@0
|
616 case LJNEXT_TOP:
|
paulo@0
|
617 blit(v->plat->skin->bg, sc,
|
paulo@0
|
618 pfRight, 72,
|
paulo@0
|
619 pfRight, 72,
|
paulo@0
|
620 112, 136);
|
paulo@0
|
621
|
paulo@0
|
622 textout_ex(sc, aver32, "Lines:", pfRight, 72, fgColor, -1);
|
paulo@0
|
623 textprintf_right_ex(sc, aver32, pfRight + 104, 102, fgColor, -1,
|
paulo@0
|
624 "%d", v->field->lines);
|
paulo@0
|
625 textout_ex(sc, aver32, "Score:", pfRight, 142, fgColor, -1);
|
paulo@0
|
626 textprintf_right_ex(sc, aver32, pfRight + 104, 172, fgColor, -1,
|
paulo@0
|
627 "%d", v->field->score);
|
paulo@0
|
628 textout_ex(sc, aver32, "Level:", pfRight, 212, fgColor, -1);
|
paulo@0
|
629 textprintf_right_ex(sc, aver32, pfRight + 104, 242, fgColor, -1,
|
paulo@0
|
630 "%d", v->field->speedState.level);
|
paulo@0
|
631 blit(sc, screen,
|
paulo@0
|
632 pfRight, 72,
|
paulo@0
|
633 pfRight, 72,
|
paulo@0
|
634 112, 136);
|
paulo@0
|
635 break;
|
paulo@0
|
636
|
paulo@0
|
637 default:
|
paulo@0
|
638 blit(v->plat->skin->bg, sc, spawnLeft, 12, spawnLeft, 12, 288, 30);
|
paulo@0
|
639 blit(v->plat->skin->bg, sc,
|
paulo@0
|
640 spawnLeft, 42, spawnLeft, 42,
|
paulo@0
|
641 pfRight - spawnLeft, 30);
|
paulo@0
|
642 textprintf_right_ex(sc, aver32, spawnLeft + 288, 12, fgColor, -1,
|
paulo@0
|
643 "Lv. %d", v->field->speedState.level);
|
paulo@0
|
644 textprintf_ex(sc, aver32, spawnLeft, 12, fgColor, -1,
|
paulo@0
|
645 "Lines: %d", v->field->lines);
|
paulo@0
|
646 textprintf_ex(sc, aver32, spawnLeft, 42, fgColor, -1,
|
paulo@0
|
647 "Score: %d", v->field->score);
|
paulo@0
|
648 blit(sc, screen, spawnLeft, 12, spawnLeft, 12, 288, 60);
|
paulo@0
|
649 break;
|
paulo@0
|
650 }
|
paulo@0
|
651 }
|
paulo@0
|
652
|
paulo@0
|
653 /* If speed is defined, and there is room to draw it, draw it. */
|
paulo@0
|
654 if (tpm > 0 && v->nextPieces <= 3) {
|
paulo@0
|
655 blit(v->plat->skin->bg, sc,
|
paulo@0
|
656 pfRight, 282,
|
paulo@0
|
657 pfRight, 282,
|
paulo@0
|
658 104, 60);
|
paulo@0
|
659 textout_ex(sc, aver32, "Speed:", pfRight, 282, fgColor, -1);
|
paulo@0
|
660 textprintf_right_ex(sc, aver32, pfRight + 104, 312, fgColor, -1,
|
paulo@0
|
661 "%d", tpm);
|
paulo@0
|
662 blit(sc, screen,
|
paulo@0
|
663 pfRight, 282,
|
paulo@0
|
664 pfRight, 282,
|
paulo@0
|
665 104, 60);
|
paulo@0
|
666 }
|
paulo@0
|
667
|
paulo@0
|
668 if (v->frontDirty & LJ_DIRTY_NEXT) {
|
paulo@0
|
669
|
paulo@0
|
670 // Erase gimmick
|
paulo@0
|
671 blit(v->plat->skin->bg, sc,
|
paulo@0
|
672 baseX, v->plat->skin->baseY + 8,
|
paulo@0
|
673 baseX, v->plat->skin->baseY + 8,
|
paulo@0
|
674 v->plat->skin->blkW * LJ_PF_WID, 30);
|
paulo@0
|
675 // Draw gimmick
|
paulo@0
|
676 if (v->field->gimmick >= 0 && v->field->gimmick < LJGM_N_GIMMICKS) {
|
paulo@0
|
677 const char *gimmickName = ljGetFourCCName(gimmickNames[v->field->gimmick]);
|
paulo@0
|
678 textout_centre_ex(sc, aver32,
|
paulo@0
|
679 gimmickName ? gimmickName : "Bad gimmick ID",
|
paulo@0
|
680 baseX + (LJ_PF_WID / 2) * v->plat->skin->blkW,
|
paulo@0
|
681 v->plat->skin->baseY + 8,
|
paulo@0
|
682 fgColor, -1);
|
paulo@0
|
683 blit(sc, screen,
|
paulo@0
|
684 baseX, v->plat->skin->baseY + 8,
|
paulo@0
|
685 baseX, v->plat->skin->baseY + 8,
|
paulo@0
|
686 v->plat->skin->blkW * LJ_PF_WID, 30);
|
paulo@0
|
687 }
|
paulo@0
|
688 }
|
paulo@0
|
689 drawNextPieces(v);
|
paulo@0
|
690
|
paulo@0
|
691 blit(v->plat->skin->bg, sc, pfRight, 42, pfRight, 42, 96, 30);
|
paulo@0
|
692 #if 0
|
paulo@0
|
693 // Use this for DEBUG inspection into a variable
|
paulo@0
|
694 textprintf_right_ex(sc, aver16, pfRight + 96, 8, fgColor, -1,
|
paulo@0
|
695 "%d", v->field->bpmCounter);
|
paulo@0
|
696 #endif
|
paulo@0
|
697 textprintf_right_ex(sc, aver32, pfRight + 96, 42, fgColor, -1,
|
paulo@0
|
698 "%d:%02d", minutes, seconds - 60 * minutes);
|
paulo@0
|
699 blit(sc, screen, pfRight, 42, pfRight, 42, 96, 30);
|
paulo@0
|
700
|
paulo@0
|
701 }
|
paulo@0
|
702
|
paulo@0
|
703 void blitField(LJView *v) {
|
paulo@0
|
704 int blkH = v->plat->skin->blkH;
|
paulo@0
|
705 int rowY = v->plat->skin->baseY
|
paulo@0
|
706 - v->plat->skin->pfElev
|
paulo@0
|
707 - blkH * v->field->ceiling;
|
paulo@0
|
708 int x = v->plat->skin->blkW * v->field->leftWall;
|
paulo@0
|
709 int w = v->plat->skin->blkW * (v->field->rightWall - v->field->leftWall);
|
paulo@0
|
710
|
paulo@0
|
711 // Copy each dirty row
|
paulo@0
|
712 for (int y = v->field->ceiling - 1; y >= 0; --y) {
|
paulo@0
|
713 if (v->frontDirty & (1 << y)) {
|
paulo@0
|
714 int top = (LJ_PF_VIS_HT - y - 1) * blkH;
|
paulo@0
|
715 int ht = 0;
|
paulo@0
|
716
|
paulo@0
|
717 // Find the height of the contiguous rows to blit
|
paulo@0
|
718 do {
|
paulo@0
|
719 ht += blkH;
|
paulo@0
|
720 --y;
|
paulo@0
|
721 } while ((y >= 0)
|
paulo@0
|
722 && (v->frontDirty & (1 << y)));
|
paulo@0
|
723 blit(v->plat->back, screen,
|
paulo@0
|
724 x, top,
|
paulo@0
|
725 x + v->plat->baseX, rowY,
|
paulo@0
|
726 w, ht);
|
paulo@0
|
727 rowY += ht;
|
paulo@0
|
728 }
|
paulo@0
|
729 rowY += blkH;
|
paulo@0
|
730 }
|
paulo@0
|
731
|
paulo@0
|
732 v->frontDirty &= (~0) << LJ_PF_HT;
|
paulo@0
|
733 }
|
paulo@0
|
734
|
paulo@0
|
735 void saveScreen(int n) {
|
paulo@0
|
736 BITMAP *b = create_bitmap(SCREEN_W, SCREEN_H);
|
paulo@0
|
737 if (b) {
|
paulo@0
|
738 PALETTE pal;
|
paulo@0
|
739
|
paulo@0
|
740 get_palette(pal);
|
paulo@0
|
741 blit(screen, b, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
|
paulo@0
|
742 if (n < 0) {
|
paulo@0
|
743 save_bitmap("ljsnap.bmp", b, pal);
|
paulo@0
|
744 } else {
|
paulo@0
|
745 char filename[64];
|
paulo@0
|
746 sprintf(filename, "pics/lj%05d.bmp", n);
|
paulo@0
|
747 save_bitmap(filename, b, pal);
|
paulo@0
|
748 }
|
paulo@0
|
749 destroy_bitmap(b);
|
paulo@0
|
750 }
|
paulo@0
|
751 }
|
paulo@0
|
752
|
paulo@0
|
753 #define PRESETS_PER_COL 6
|
paulo@0
|
754 #define N_NONPRESETS 2
|
paulo@0
|
755 #define PRESETS_TOP 140
|
paulo@0
|
756 #define PRESET_COL_WIDTH 250
|
paulo@0
|
757 #define PRESET_ROW_HT 40
|
paulo@0
|
758
|
paulo@0
|
759 static const char *const nonPresetNames[N_NONPRESETS] = {
|
paulo@0
|
760 "Full Custom", "Back"
|
paulo@0
|
761 };
|
paulo@0
|
762
|
paulo@0
|
763 static void getPresetDrawRow(unsigned int preset, int hilite) {
|
paulo@0
|
764 unsigned int ht = text_height(aver32);
|
paulo@0
|
765 const char *txt = preset < nLoadedPresets
|
paulo@0
|
766 ? loadedPresets[preset].name
|
paulo@0
|
767 : nonPresetNames[preset - nLoadedPresets];
|
paulo@0
|
768 if (!txt) {
|
paulo@0
|
769 txt = "Bad";
|
paulo@0
|
770 }
|
paulo@0
|
771 unsigned int wid = text_length(aver32, txt);
|
paulo@0
|
772
|
paulo@0
|
773 int buttonCol = preset / PRESETS_PER_COL;
|
paulo@0
|
774 int buttonX = 20 + buttonCol * PRESET_COL_WIDTH;
|
paulo@0
|
775 int buttonY = PRESETS_TOP
|
paulo@0
|
776 + PRESET_ROW_HT * (preset - buttonCol * PRESETS_PER_COL);
|
paulo@0
|
777 unsigned int buttonWidth = wid + 16;
|
paulo@0
|
778
|
paulo@0
|
779 rectfill(screen,
|
paulo@0
|
780 buttonX, buttonY,
|
paulo@0
|
781 buttonX + buttonWidth - 1, buttonY + PRESET_ROW_HT - 1,
|
paulo@0
|
782 hilite ? hiliteColor : bgColor);
|
paulo@0
|
783 if (hilite) {
|
paulo@0
|
784 rect(screen,
|
paulo@0
|
785 buttonX, buttonY,
|
paulo@0
|
786 buttonX + buttonWidth - 1, buttonY + PRESET_ROW_HT - 1,
|
paulo@0
|
787 fgColor);
|
paulo@0
|
788 }
|
paulo@0
|
789 textout_ex(screen, aver32, txt,
|
paulo@0
|
790 8 + buttonX,
|
paulo@0
|
791 20 + buttonY - ht / 2,
|
paulo@0
|
792 fgColor, -1);
|
paulo@0
|
793 }
|
paulo@0
|
794
|
paulo@0
|
795 int getPreset(int lastPreset) {
|
paulo@0
|
796 LJBits lastKeys = ~0;
|
paulo@0
|
797 redrawWholeScreen = 1;
|
paulo@0
|
798
|
paulo@0
|
799 clear_keybuf();
|
paulo@0
|
800 if (lastPreset < 0) {
|
paulo@0
|
801 lastPreset += nLoadedPresets + N_NONPRESETS;
|
paulo@0
|
802 }
|
paulo@0
|
803
|
paulo@0
|
804 for(int done = 0; done == 0; ) {
|
paulo@0
|
805 if (redrawWholeScreen) {
|
paulo@0
|
806 redrawWholeScreen = 0;
|
paulo@0
|
807 clear_to_color(screen, bgColor);
|
paulo@0
|
808 textout_ex(screen, aver32, "LOCKJAW > Play", 16, 32, fgColor, -1);
|
paulo@0
|
809 textout_ex(screen, aver32, "Select a scenario:", 16, 90, fgColor, -1);
|
paulo@0
|
810
|
paulo@0
|
811 for (int preset = 0;
|
paulo@0
|
812 preset < nLoadedPresets + N_NONPRESETS;
|
paulo@0
|
813 ++preset) {
|
paulo@0
|
814 getPresetDrawRow(preset, preset == lastPreset);
|
paulo@0
|
815 }
|
paulo@0
|
816 textout_ex(screen, aver16, "Arrows: move; Rotate Right: start",
|
paulo@0
|
817 16, PRESETS_TOP + 40 * (PRESETS_PER_COL + 1), fgColor, -1);
|
paulo@0
|
818 textout_ex(screen, aver16, "Coming soon: an editor for these!",
|
paulo@0
|
819 16, PRESETS_TOP + 40 * (PRESETS_PER_COL + 1) + 20, fgColor, -1);
|
paulo@0
|
820 }
|
paulo@0
|
821 while (keypressed()) {
|
paulo@0
|
822 int scancode;
|
paulo@0
|
823 ureadkey(&scancode);
|
paulo@0
|
824 if (scancode == KEY_PRTSCR) {
|
paulo@0
|
825 saveScreen(-1);
|
paulo@0
|
826 }
|
paulo@0
|
827 }
|
paulo@0
|
828
|
paulo@0
|
829 int preset = lastPreset;
|
paulo@0
|
830 LJBits keys = menuReadPad();
|
paulo@0
|
831 LJBits newKeys = keys & ~lastKeys;
|
paulo@0
|
832
|
paulo@0
|
833 if ((newKeys & VKEY_ROTL) || wantsClose) {
|
paulo@0
|
834 preset = nLoadedPresets + N_NONPRESETS - 1;
|
paulo@0
|
835 ezPlaySample("rotate_wav", 128);
|
paulo@0
|
836 }
|
paulo@0
|
837 if ((newKeys & VKEY_ROTR) || wantsClose) {
|
paulo@0
|
838 done = 1;
|
paulo@0
|
839 ezPlaySample("line_wav", 128);
|
paulo@0
|
840 }
|
paulo@0
|
841
|
paulo@0
|
842 if (newKeys & VKEY_UP) {
|
paulo@0
|
843 if (preset <= 0) {
|
paulo@0
|
844 preset = nLoadedPresets + N_NONPRESETS - 1;
|
paulo@0
|
845 } else {
|
paulo@0
|
846 --preset;
|
paulo@0
|
847 }
|
paulo@0
|
848 ezPlaySample("shift_wav", 128);
|
paulo@0
|
849 }
|
paulo@0
|
850 if (newKeys & VKEY_DOWN) {
|
paulo@0
|
851 ++preset;
|
paulo@0
|
852 if (preset >= nLoadedPresets + N_NONPRESETS) {
|
paulo@0
|
853 preset = 0;
|
paulo@0
|
854 }
|
paulo@0
|
855 ezPlaySample("shift_wav", 128);
|
paulo@0
|
856 }
|
paulo@0
|
857
|
paulo@0
|
858 if (newKeys & VKEY_LEFT) {
|
paulo@0
|
859 if (preset < PRESETS_PER_COL) {
|
paulo@0
|
860 preset += (((nLoadedPresets + N_NONPRESETS)
|
paulo@0
|
861 / PRESETS_PER_COL)
|
paulo@0
|
862 )
|
paulo@0
|
863 * PRESETS_PER_COL;
|
paulo@0
|
864 if (preset >= nLoadedPresets + N_NONPRESETS) {
|
paulo@0
|
865 preset -= PRESETS_PER_COL;
|
paulo@0
|
866 }
|
paulo@0
|
867 } else {
|
paulo@0
|
868 preset -= PRESETS_PER_COL;
|
paulo@0
|
869 }
|
paulo@0
|
870 ezPlaySample("shift_wav", 128);
|
paulo@0
|
871 }
|
paulo@0
|
872 if (newKeys & VKEY_RIGHT) {
|
paulo@0
|
873 preset += PRESETS_PER_COL;
|
paulo@0
|
874 if (preset >= nLoadedPresets + N_NONPRESETS) {
|
paulo@0
|
875 preset %= PRESETS_PER_COL;
|
paulo@0
|
876 }
|
paulo@0
|
877 ezPlaySample("shift_wav", 128);
|
paulo@0
|
878 }
|
paulo@0
|
879
|
paulo@0
|
880 if (preset != lastPreset) {
|
paulo@0
|
881 vsync();
|
paulo@0
|
882 getPresetDrawRow(lastPreset, 0);
|
paulo@0
|
883 getPresetDrawRow(preset, 1);
|
paulo@0
|
884 lastPreset = preset;
|
paulo@0
|
885 } else {
|
paulo@0
|
886 rest(30);
|
paulo@0
|
887 }
|
paulo@0
|
888 lastKeys = keys;
|
paulo@0
|
889 }
|
paulo@0
|
890
|
paulo@0
|
891 // Wrap the nonpresets into the negative numbers.
|
paulo@0
|
892 if (lastPreset >= nLoadedPresets) {
|
paulo@0
|
893 lastPreset -= (nLoadedPresets + N_NONPRESETS);
|
paulo@0
|
894 }
|
paulo@0
|
895
|
paulo@0
|
896 return lastPreset;
|
paulo@0
|
897 }
|
paulo@0
|
898
|
paulo@0
|
899 /**
|
paulo@0
|
900 * Pauses the game, returning nonzero if the player wants to quit.
|
paulo@0
|
901 */
|
paulo@0
|
902 int pauseGame(LJPCView *v) {
|
paulo@0
|
903 int escCount = 0;
|
paulo@0
|
904 int quit = 0;
|
paulo@0
|
905 int escHold = curTime;
|
paulo@0
|
906 redrawWholeScreen = 1;
|
paulo@0
|
907
|
paulo@0
|
908 LJMusic_pause(v->skin->bgm, 1);
|
paulo@0
|
909 while (escCount < 2 && !quit) {
|
paulo@0
|
910 LJMusic_poll(v->skin->bgm);
|
paulo@0
|
911 if (redrawWholeScreen) {
|
paulo@0
|
912 redrawWholeScreen = 0;
|
paulo@0
|
913 clear_to_color(screen, pfBgColor);
|
paulo@0
|
914 textout_centre_ex(screen, aver32, "LOCKJAW: GAME PAUSED",
|
paulo@0
|
915 SCREEN_W / 2, 200, pfFgColor, -1);
|
paulo@0
|
916 textout_centre_ex(screen, aver32, "Press Esc to continue",
|
paulo@0
|
917 SCREEN_W / 2, 250, pfFgColor, -1);
|
paulo@0
|
918 textout_centre_ex(screen, aver32, "or hold Esc to quit",
|
paulo@0
|
919 SCREEN_W / 2, 300, pfFgColor, -1);
|
paulo@0
|
920 }
|
paulo@0
|
921
|
paulo@0
|
922 if (key[KEY_ESC]) {
|
paulo@0
|
923 if (escHold == 0) {
|
paulo@0
|
924 escHold = curTime;
|
paulo@0
|
925 }
|
paulo@0
|
926 if (curTime - escHold >= 60) {
|
paulo@0
|
927 quit = 1;
|
paulo@0
|
928 }
|
paulo@0
|
929 } else {
|
paulo@0
|
930 if (escHold) {
|
paulo@0
|
931 ++escCount;
|
paulo@0
|
932 }
|
paulo@0
|
933 escHold = 0;
|
paulo@0
|
934 }
|
paulo@0
|
935 rest(30);
|
paulo@0
|
936 if (wantsClose) {
|
paulo@0
|
937 quit = 1;
|
paulo@0
|
938 }
|
paulo@0
|
939
|
paulo@0
|
940 }
|
paulo@0
|
941 LJMusic_pause(v->skin->bgm, 0);
|
paulo@0
|
942 redrawWholeScreen = 1;
|
paulo@0
|
943 clear_keybuf();
|
paulo@0
|
944 return quit;
|
paulo@0
|
945 }
|
paulo@0
|
946
|
paulo@0
|
947
|
paulo@0
|
948 void pcInit(LJView *v, struct LJPrefs *prefs) {
|
paulo@0
|
949 v->plat->b2bcd1 = 0;
|
paulo@0
|
950 v->plat->b2bcd2 = 0;
|
paulo@0
|
951 v->plat->baseX = v->plat->skin->baseX;
|
paulo@0
|
952
|
paulo@0
|
953 // If the player has chosen to use more next pieces than the
|
paulo@0
|
954 // next piece position can handle, set the number of
|
paulo@0
|
955 // next pieces for correctness of debrief().
|
paulo@0
|
956 if (v->nextPieces > 3 && v->plat->skin->nextPos == LJNEXT_TOP) {
|
paulo@0
|
957 v->nextPieces = 3;
|
paulo@0
|
958 }
|
paulo@0
|
959 }
|
paulo@0
|
960
|
paulo@0
|
961 /**
|
paulo@0
|
962 * Redraws everything on the screen.
|
paulo@0
|
963 * Called when needs redraw.
|
paulo@0
|
964 */
|
paulo@0
|
965 void playRedrawScreen(LJView *v) {
|
paulo@0
|
966 blit(v->plat->skin->bg, screen,
|
paulo@0
|
967 0, 0,
|
paulo@0
|
968 0, 0,
|
paulo@0
|
969 SCREEN_W, SCREEN_H);
|
paulo@0
|
970 v->frontDirty = ~0;
|
paulo@0
|
971 }
|
paulo@0
|
972
|
paulo@0
|
973 #if 0
|
paulo@0
|
974 void startingAniWantsSkip(LJView *v) {
|
paulo@0
|
975 LJInput unusedIn;
|
paulo@0
|
976 addKeysToInput(&unusedIn, readPad(), v->field, v->control);
|
paulo@0
|
977 }
|
paulo@0
|
978 #endif
|
paulo@0
|
979
|
paulo@0
|
980 void playSampleForTetromino(int piece);
|
paulo@0
|
981
|
paulo@0
|
982 void restPollingMusic(int nFrames, LJMusic *bgm) {
|
paulo@0
|
983 nFrames += curTime;
|
paulo@0
|
984 while (curTime - nFrames < 0) {
|
paulo@0
|
985 if (bgm) {
|
paulo@0
|
986 LJMusic_poll(bgm);
|
paulo@0
|
987 }
|
paulo@0
|
988 }
|
paulo@0
|
989 }
|
paulo@0
|
990
|
paulo@0
|
991 extern int bgmReadyGo;
|
paulo@0
|
992 void startingAnimation(LJView *v) {
|
paulo@0
|
993 int readyGoX = v->plat->baseX + v->plat->skin->blkW * LJ_PF_WID / 2;
|
paulo@0
|
994 int readyGoY = v->plat->skin->baseY
|
paulo@0
|
995 - v->plat->skin->pfElev
|
paulo@0
|
996 - v->plat->skin->blkH
|
paulo@0
|
997 * v->field->ceiling * 3 / 5;
|
paulo@0
|
998
|
paulo@0
|
999 clear_keybuf();
|
paulo@0
|
1000 v->backDirty = 0;
|
paulo@0
|
1001
|
paulo@0
|
1002 playRedrawScreen(v);
|
paulo@0
|
1003 blitField(v);
|
paulo@0
|
1004 textout_centre_ex(screen, aver32, "Ready",
|
paulo@0
|
1005 readyGoX, readyGoY, pfFgColor, -1);
|
paulo@0
|
1006
|
paulo@0
|
1007 ezPlaySample("ready_wav", 128);
|
paulo@0
|
1008 restPollingMusic(36, bgmReadyGo ? v->plat->skin->bgm : NULL);
|
paulo@0
|
1009 v->frontDirty = ~0;
|
paulo@0
|
1010
|
paulo@0
|
1011 if (!wantsClose) {
|
paulo@0
|
1012 blitField(v);
|
paulo@0
|
1013 textout_centre_ex(screen, aver32, "GO!",
|
paulo@0
|
1014 readyGoX, readyGoY, pfFgColor, -1);
|
paulo@0
|
1015 drawScore(v);
|
paulo@0
|
1016
|
paulo@0
|
1017 ezPlaySample("go_wav", 128);
|
paulo@0
|
1018 v->frontDirty = ~0;
|
paulo@0
|
1019 restPollingMusic(12, bgmReadyGo ? v->plat->skin->bgm : NULL);
|
paulo@0
|
1020 }
|
paulo@0
|
1021 if (!wantsClose) {
|
paulo@0
|
1022 playSampleForTetromino(v->field->curPiece[1]);
|
paulo@0
|
1023 restPollingMusic(24, bgmReadyGo ? v->plat->skin->bgm : NULL);
|
paulo@0
|
1024 }
|
paulo@0
|
1025 }
|
paulo@0
|
1026
|
paulo@0
|
1027
|
paulo@0
|
1028 static void gameOverAnimation(const LJPCView *const v, const LJField *p, int won) {
|
paulo@0
|
1029 int ceiling = p->ceiling;
|
paulo@0
|
1030 int left = v->baseX + p->leftWall * v->skin->blkW;
|
paulo@0
|
1031 int right = v->baseX + p->rightWall * v->skin->blkW - 1;
|
paulo@0
|
1032
|
paulo@0
|
1033 ezPlaySample("sectionup_wav", 0);
|
paulo@0
|
1034 if (!won) {
|
paulo@0
|
1035 ezPlaySample("gameover_wav", 256);
|
paulo@0
|
1036 } else {
|
paulo@0
|
1037 ezPlaySample("win_wav", 256);
|
paulo@0
|
1038 }
|
paulo@0
|
1039
|
paulo@0
|
1040 for (int t = ceiling + v->skin->blkH - 2; t >= 0; --t) {
|
paulo@0
|
1041
|
paulo@0
|
1042 // FIXME: vsync doesn't work on Vista
|
paulo@0
|
1043 vsync();
|
paulo@0
|
1044 for (int row = ceiling - 1; row >= 0; --row) {
|
paulo@0
|
1045 int ysub = t - row;
|
paulo@0
|
1046
|
paulo@0
|
1047 if (ysub >= 0 && ysub < v->skin->blkH) {
|
paulo@0
|
1048 int y = v->skin->baseY - v->skin->pfElev
|
paulo@0
|
1049 - row * v->skin->blkH - ysub - 1;
|
paulo@0
|
1050 hline(screen, left, y, right, pfBgColor);
|
paulo@0
|
1051 }
|
paulo@0
|
1052 }
|
paulo@0
|
1053 if (wantsClose) {
|
paulo@0
|
1054 t = 0;
|
paulo@0
|
1055 }
|
paulo@0
|
1056 }
|
paulo@0
|
1057 }
|
paulo@0
|
1058
|
paulo@0
|
1059 #define MENU_COPR_NOTICE_LINES 4
|
paulo@0
|
1060 const char *const menuCoprNotice[MENU_COPR_NOTICE_LINES] = {
|
paulo@0
|
1061 "Copr. 2006-2008 Damian Yerrick",
|
paulo@0
|
1062 "Not sponsored or endorsed by The Tetris Company.",
|
paulo@0
|
1063 "LOCKJAW comes with ABSOLUTELY NO WARRANTY. This is free software, and you are",
|
paulo@0
|
1064 "welcome to redistribute it under certain conditions as described in GPL.txt."
|
paulo@0
|
1065 };
|
paulo@0
|
1066
|
paulo@0
|
1067 static BITMAP *buildTitleScreen(void) {
|
paulo@0
|
1068 BITMAP *back = create_system_bitmap(SCREEN_W, SCREEN_H);
|
paulo@0
|
1069 if (!back) {
|
paulo@0
|
1070 return NULL;
|
paulo@0
|
1071 }
|
paulo@0
|
1072
|
paulo@0
|
1073 // Gradient from (0, 0, 0) to (0, 0, 153)
|
paulo@0
|
1074 for (int y = 0; y < 192; ++y) {
|
paulo@0
|
1075 for (int x = -((y * 13) & 0x1F);
|
paulo@0
|
1076 x < SCREEN_W;
|
paulo@0
|
1077 x += 32) {
|
paulo@0
|
1078 int colValue = y + ((rand() & 0x7000) >> 12);
|
paulo@0
|
1079 int c = makecol(0, 0, 153 * colValue / 192);
|
paulo@0
|
1080 hline(back, x, y, x + 31, c);
|
paulo@0
|
1081 }
|
paulo@0
|
1082 }
|
paulo@0
|
1083
|
paulo@0
|
1084 // Gradient from (102, 51, 0) to (204, 102, 0)
|
paulo@0
|
1085 for (int y = 192; y < 384; ++y) {
|
paulo@0
|
1086 for (int x = -((y * 13) & 0x1F);
|
paulo@0
|
1087 x < SCREEN_W;
|
paulo@0
|
1088 x += 32) {
|
paulo@0
|
1089 int colValue = y + ((rand() & 0x7800) >> 11);
|
paulo@0
|
1090 int c = makecol(102 * colValue / 192, 51 * colValue / 192, 0);
|
paulo@0
|
1091 hline(back, x, y, x + 31, c);
|
paulo@0
|
1092 }
|
paulo@0
|
1093 }
|
paulo@0
|
1094
|
paulo@0
|
1095 // Gradient from (204, 102, 0) to (255, 128, 0)
|
paulo@0
|
1096 for (int y = 384; y < SCREEN_H; ++y) {
|
paulo@0
|
1097 for (int x = -((y * 13) & 0x1F);
|
paulo@0
|
1098 x < SCREEN_W;
|
paulo@0
|
1099 x += 32) {
|
paulo@0
|
1100 int colValue = y - 400 + ((rand() & 0x7C00) >> 10);
|
paulo@0
|
1101 if (colValue > 600 - 384) {
|
paulo@0
|
1102 colValue = 600 - 384;
|
paulo@0
|
1103 }
|
paulo@0
|
1104 int c = makecol(204 + 50 * colValue / (600 - 384),
|
paulo@0
|
1105 102 + 25 * colValue / (600 - 384),
|
paulo@0
|
1106 0);
|
paulo@0
|
1107 hline(back, x, y, x + 31, c);
|
paulo@0
|
1108 }
|
paulo@0
|
1109 }
|
paulo@0
|
1110
|
paulo@0
|
1111 DATAFILE *obj = find_datafile_object(dat, "arttitle_bmp");
|
paulo@0
|
1112 BITMAP *logo = obj ? obj->dat : NULL;
|
paulo@0
|
1113 obj = find_datafile_object(dat, "arttitle_pal");
|
paulo@0
|
1114 const RGB *pal = obj ? obj->dat : NULL;
|
paulo@0
|
1115
|
paulo@0
|
1116 if (logo && pal) {
|
paulo@0
|
1117 set_palette(pal);
|
paulo@0
|
1118 draw_sprite(back, logo,
|
paulo@0
|
1119 (SCREEN_W - logo->w) / 2, (384 - logo->h) / 2);
|
paulo@0
|
1120 //unselect_palette();
|
paulo@0
|
1121 }
|
paulo@0
|
1122
|
paulo@0
|
1123 textout_centre_ex(back, aver32, "Arrows: change; Enter: choose",
|
paulo@0
|
1124 SCREEN_W / 2, 440,
|
paulo@0
|
1125 0, -1);
|
paulo@0
|
1126
|
paulo@0
|
1127 textout_centre_ex(back, aver32, "LOCKJAW: The Reference "LJ_VERSION,
|
paulo@0
|
1128 SCREEN_W / 2, SCREEN_H - 40,
|
paulo@0
|
1129 0, -1);
|
paulo@0
|
1130
|
paulo@0
|
1131 return back;
|
paulo@0
|
1132 }
|
paulo@0
|
1133
|
paulo@0
|
1134 enum {
|
paulo@0
|
1135 TITLE_EXIT = 0,
|
paulo@0
|
1136 TITLE_PLAY,
|
paulo@0
|
1137 TITLE_REPLAY,
|
paulo@0
|
1138 TITLE_OPTIONS,
|
paulo@0
|
1139 TITLE_SKIN,
|
paulo@0
|
1140 TITLE_KEYS,
|
paulo@0
|
1141 N_TITLE_ACTIONS
|
paulo@0
|
1142 };
|
paulo@0
|
1143
|
paulo@0
|
1144 static const char *titleActions[N_TITLE_ACTIONS] = {
|
paulo@0
|
1145 [TITLE_EXIT] = "Exit",
|
paulo@0
|
1146 [TITLE_PLAY] = "Play",
|
paulo@0
|
1147 [TITLE_REPLAY] = "Replay",
|
paulo@0
|
1148 [TITLE_SKIN] = "Skin...",
|
paulo@0
|
1149 [TITLE_OPTIONS] = "Options...",
|
paulo@0
|
1150 [TITLE_KEYS] = "Game Keys..."
|
paulo@0
|
1151 };
|
paulo@0
|
1152 /*
|
paulo@0
|
1153 0: Exit
|
paulo@0
|
1154 1: Play
|
paulo@0
|
1155 2
|
paulo@0
|
1156 */
|
paulo@0
|
1157 int title(void) {
|
paulo@0
|
1158
|
paulo@0
|
1159 // don't even draw if the player is trying to close the window
|
paulo@0
|
1160 if (wantsClose) {
|
paulo@0
|
1161 return 0;
|
paulo@0
|
1162 }
|
paulo@0
|
1163
|
paulo@0
|
1164 BITMAP *back = buildTitleScreen();
|
paulo@0
|
1165 LJBits lastKeys = ~0;
|
paulo@0
|
1166 int redraw = 1;
|
paulo@0
|
1167 int choice = 1;
|
paulo@0
|
1168
|
paulo@0
|
1169 if (!back) {
|
paulo@0
|
1170 alert("Not enough memory to display the title screen.",
|
paulo@0
|
1171 "(If you don't even have RAM for a title screen,",
|
paulo@0
|
1172 "then what do you have RAM for?)",
|
paulo@0
|
1173 "Exit", 0, 13, 0);
|
paulo@0
|
1174 return 0;
|
paulo@0
|
1175 }
|
paulo@0
|
1176
|
paulo@0
|
1177 redrawWholeScreen = 1;
|
paulo@0
|
1178
|
paulo@0
|
1179 for(int done = 0; done == 0; ) {
|
paulo@0
|
1180 if (redrawWholeScreen) {
|
paulo@0
|
1181 redrawWholeScreen = 0;
|
paulo@0
|
1182 blit(back, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
|
paulo@0
|
1183 redraw = 1;
|
paulo@0
|
1184 }
|
paulo@0
|
1185 if (redraw) {
|
paulo@0
|
1186 int dehilite = makecol(221, 153, 85);
|
paulo@0
|
1187 int white = makecol(255, 255, 255);
|
paulo@0
|
1188 redraw = 0;
|
paulo@0
|
1189 vsync();
|
paulo@0
|
1190 blit(back, screen, 0, 400, 0, 400, SCREEN_W, 30);
|
paulo@0
|
1191 textout_centre_ex(screen, aver32,
|
paulo@0
|
1192 titleActions[choice],
|
paulo@0
|
1193 SCREEN_W / 2, 400, white, -1);
|
paulo@0
|
1194 textout_centre_ex(screen, aver32,
|
paulo@0
|
1195 titleActions[choice == 0 ? N_TITLE_ACTIONS - 1 : choice - 1],
|
paulo@0
|
1196 SCREEN_W / 2 - 160, 400, dehilite, -1);
|
paulo@0
|
1197 textout_centre_ex(screen, aver32,
|
paulo@0
|
1198 titleActions[choice == N_TITLE_ACTIONS - 1 ? 0 : choice + 1],
|
paulo@0
|
1199 SCREEN_W / 2 + 160, 400, dehilite, -1);
|
paulo@0
|
1200 }
|
paulo@0
|
1201
|
paulo@0
|
1202 while (keypressed()) {
|
paulo@0
|
1203 int scancode;
|
paulo@0
|
1204 ureadkey(&scancode);
|
paulo@0
|
1205 if (scancode == KEY_PRTSCR) {
|
paulo@0
|
1206 saveScreen(-1);
|
paulo@0
|
1207 }
|
paulo@0
|
1208 }
|
paulo@0
|
1209
|
paulo@0
|
1210 LJBits keys = menuReadPad();
|
paulo@0
|
1211 LJBits newKeys = keys & ~lastKeys;
|
paulo@0
|
1212
|
paulo@0
|
1213 if (newKeys & VKEY_LEFT) {
|
paulo@0
|
1214 --choice;
|
paulo@0
|
1215 redraw = 1;
|
paulo@0
|
1216 ezPlaySample("shift_wav", 128);
|
paulo@0
|
1217 }
|
paulo@0
|
1218 if (newKeys & VKEY_RIGHT) {
|
paulo@0
|
1219 ++choice;
|
paulo@0
|
1220 redraw = 1;
|
paulo@0
|
1221 ezPlaySample("shift_wav", 128);
|
paulo@0
|
1222 }
|
paulo@0
|
1223 if (newKeys & VKEY_ROTL) {
|
paulo@0
|
1224 choice = 0;
|
paulo@0
|
1225 redraw = 1;
|
paulo@0
|
1226 ezPlaySample("rotate_wav", 128);
|
paulo@0
|
1227 }
|
paulo@0
|
1228 if (newKeys & VKEY_ROTR) {
|
paulo@0
|
1229 done = 1;
|
paulo@0
|
1230 ezPlaySample("line_wav", 128);
|
paulo@0
|
1231 }
|
paulo@0
|
1232 if (choice < 0) {
|
paulo@0
|
1233 choice += N_TITLE_ACTIONS;
|
paulo@0
|
1234 }
|
paulo@0
|
1235 if (choice >= N_TITLE_ACTIONS) {
|
paulo@0
|
1236 choice -= N_TITLE_ACTIONS;
|
paulo@0
|
1237 }
|
paulo@0
|
1238
|
paulo@0
|
1239 lastKeys = keys;
|
paulo@0
|
1240
|
paulo@0
|
1241 if (!redraw) {
|
paulo@0
|
1242 rest(30);
|
paulo@0
|
1243 }
|
paulo@0
|
1244 if (wantsClose) {
|
paulo@0
|
1245 done = 1;
|
paulo@0
|
1246 choice = 0;
|
paulo@0
|
1247 }
|
paulo@0
|
1248 }
|
paulo@0
|
1249 destroy_bitmap(back);
|
paulo@0
|
1250 return choice;
|
paulo@0
|
1251 }
|
paulo@0
|
1252
|
paulo@0
|
1253
|
paulo@0
|
1254 void setupWindow(void) {
|
paulo@0
|
1255 set_window_title("LOCKJAW");
|
paulo@0
|
1256 bgColor = makecol(255, 255, 255);
|
paulo@0
|
1257 pfFgColor = bgColor;
|
paulo@0
|
1258 hiliteColor = makecol(255, 255, 204);
|
paulo@0
|
1259 refreshRate = get_refresh_rate();
|
paulo@0
|
1260 }
|
paulo@0
|
1261
|
paulo@0
|
1262 void drawCoprNotice(void) {
|
paulo@0
|
1263 clear_to_color(screen, pfBgColor);
|
paulo@0
|
1264 for (int i = 0; i < MENU_COPR_NOTICE_LINES; ++i) {
|
paulo@0
|
1265 textout_ex(screen, font, menuCoprNotice[i],
|
paulo@0
|
1266 16, 580 + 12 * (i - MENU_COPR_NOTICE_LINES),
|
paulo@0
|
1267 pfFgColor, -1);
|
paulo@0
|
1268 }
|
paulo@0
|
1269 }
|
paulo@0
|
1270
|
paulo@0
|
1271
|
paulo@0
|
1272 /**
|
paulo@0
|
1273 * Destroys the back buffers for both playfields.
|
paulo@0
|
1274 */
|
paulo@0
|
1275 static void destroyBackBuf(LJPCView *plat) {
|
paulo@0
|
1276 for (int i = 0; i < MAX_PLAYERS; ++i) {
|
paulo@0
|
1277 if (plat->back) {
|
paulo@0
|
1278 destroy_bitmap(plat->back);
|
paulo@0
|
1279 plat->back = NULL;
|
paulo@0
|
1280 }
|
paulo@0
|
1281 }
|
paulo@0
|
1282 if (plat->skin->fullback) {
|
paulo@0
|
1283 destroy_bitmap(plat->skin->fullback);
|
paulo@0
|
1284 plat->skin->fullback = NULL;
|
paulo@0
|
1285 }
|
paulo@0
|
1286 }
|
paulo@0
|
1287
|
paulo@0
|
1288 /**
|
paulo@0
|
1289 * Creates the back buffers for both playfields.
|
paulo@0
|
1290 */
|
paulo@0
|
1291 static int createBackBuf(LJView *v) {
|
paulo@0
|
1292 v->plat->skin->fullback = create_system_bitmap(SCREEN_W, SCREEN_H);
|
paulo@0
|
1293 if(!v->plat->skin->fullback) {
|
paulo@0
|
1294 allegro_message("Could not create back buffer.\n");
|
paulo@0
|
1295 return 0;
|
paulo@0
|
1296 }
|
paulo@0
|
1297
|
paulo@0
|
1298 int blkW = v->plat->skin->blkW;
|
paulo@0
|
1299 int blkH = v->plat->skin->blkH;
|
paulo@0
|
1300 int y = v->plat->skin->baseY
|
paulo@0
|
1301 - v->plat->skin->pfElev
|
paulo@0
|
1302 - blkH * v->field->ceiling;
|
paulo@0
|
1303
|
paulo@0
|
1304 for (int i = 0; i < MAX_PLAYERS; ++i) {
|
paulo@0
|
1305 int x = v->plat->skin->baseX
|
paulo@0
|
1306 + blkW * v[i].field->leftWall;
|
paulo@0
|
1307
|
paulo@0
|
1308 v[i].plat->back = create_sub_bitmap(v->plat->skin->fullback,
|
paulo@0
|
1309 x + SCREEN_W / 2 * i,
|
paulo@0
|
1310 y,
|
paulo@0
|
1311 v->plat->skin->blkW * LJ_PF_WID,
|
paulo@0
|
1312 v->plat->skin->blkH * LJ_PF_VIS_HT);
|
paulo@0
|
1313 if (!v[i].plat->back) {
|
paulo@0
|
1314 destroyBackBuf(v->plat);
|
paulo@0
|
1315 return 0;
|
paulo@0
|
1316 }
|
paulo@0
|
1317 }
|
paulo@0
|
1318 return 1;
|
paulo@0
|
1319 }
|
paulo@0
|
1320
|
paulo@0
|
1321 /**
|
paulo@0
|
1322 * Destroys all system bitmaps that a given view owns.
|
paulo@0
|
1323 * Useful before changing screen mode.
|
paulo@0
|
1324 */
|
paulo@0
|
1325 void destroySystemBitmaps(LJPCView *plat) {
|
paulo@0
|
1326 destroyBackBuf(plat);
|
paulo@0
|
1327 if (plat->skin->connBlocks) {
|
paulo@0
|
1328 destroy_bitmap(plat->skin->connBlocks);
|
paulo@0
|
1329 plat->skin->connBlocks = NULL;
|
paulo@0
|
1330 }
|
paulo@0
|
1331 }
|
paulo@0
|
1332
|
paulo@0
|
1333 int openWindow(int windowed)
|
paulo@0
|
1334 {
|
paulo@0
|
1335 int depth = desktop_color_depth();
|
paulo@0
|
1336 int card = windowed ? GFX_AUTODETECT_WINDOWED : GFX_AUTODETECT_FULLSCREEN;
|
paulo@0
|
1337
|
paulo@0
|
1338 /* Reference implementation for Allegro is not compatible with
|
paulo@0
|
1339 indexed color. */
|
paulo@0
|
1340 if (depth < 15) {
|
paulo@0
|
1341 depth = 16;
|
paulo@0
|
1342 }
|
paulo@0
|
1343
|
paulo@0
|
1344 // Full screen procedure
|
paulo@0
|
1345 set_color_depth(depth);
|
paulo@0
|
1346 if (set_gfx_mode(card, skinW, skinH, 0, 0) == 0) {
|
paulo@0
|
1347 setupWindow();
|
paulo@0
|
1348 return 0;
|
paulo@0
|
1349 }
|
paulo@0
|
1350
|
paulo@0
|
1351 // Windows can't tell 16 bit from 15 bit. If desktop color depth is reported as 16, try 15 too.
|
paulo@0
|
1352 if (depth == 16) {
|
paulo@0
|
1353 set_color_depth(15);
|
paulo@0
|
1354 if (set_gfx_mode(card, skinW, skinH, 0, 0) == 0) {
|
paulo@0
|
1355 setupWindow();
|
paulo@0
|
1356 return 0;
|
paulo@0
|
1357 }
|
paulo@0
|
1358 }
|
paulo@0
|
1359
|
paulo@0
|
1360 return -1;
|
paulo@0
|
1361 }
|
paulo@0
|
1362
|
paulo@0
|
1363 BITMAP *loadConnections(const char *filename, int blkW, int blkH) {
|
paulo@0
|
1364 BITMAP *src = load_bitmap(filename, NULL);
|
paulo@0
|
1365
|
paulo@0
|
1366 if (!src) {
|
paulo@0
|
1367 return NULL;
|
paulo@0
|
1368 }
|
paulo@0
|
1369 BITMAP *dst = create_system_bitmap(blkW*16, blkH*16);
|
paulo@0
|
1370 if (!dst) {
|
paulo@0
|
1371 destroy_bitmap(src);
|
paulo@0
|
1372 return NULL;
|
paulo@0
|
1373 }
|
paulo@0
|
1374 acquire_bitmap(dst);
|
paulo@0
|
1375 for (unsigned int col = 0; col < 16; ++col) {
|
paulo@0
|
1376 unsigned int srcXBase = (col & 0x03) * blkW * 2;
|
paulo@0
|
1377 unsigned int srcYBase = (col >> 2) * blkH * 2;
|
paulo@0
|
1378 unsigned int dstYBase = col * blkH;
|
paulo@0
|
1379 for (unsigned int conn = 0; conn < 16; ++conn) {
|
paulo@0
|
1380 unsigned int dstXBase = conn * blkW;
|
paulo@0
|
1381 unsigned int topSegY = (conn & CONNECT_U) ? blkH : 0;
|
paulo@0
|
1382 unsigned int botSegY = (conn & CONNECT_D) ? blkH/2 : 3*blkH/2;
|
paulo@0
|
1383 unsigned int leftSegX = (conn & CONNECT_L) ? blkW : 0;
|
paulo@0
|
1384 unsigned int rightSegX = (conn & CONNECT_R) ? blkW/2 : 3*blkW/2;
|
paulo@0
|
1385 blit(src, dst,
|
paulo@0
|
1386 srcXBase + leftSegX, srcYBase + topSegY,
|
paulo@0
|
1387 dstXBase + 0, dstYBase + 0,
|
paulo@0
|
1388 blkW/2, blkH/2);
|
paulo@0
|
1389 blit(src, dst,
|
paulo@0
|
1390 srcXBase + rightSegX, srcYBase + topSegY,
|
paulo@0
|
1391 dstXBase + blkW/2, dstYBase + 0,
|
paulo@0
|
1392 blkW/2, blkH/2);
|
paulo@0
|
1393 blit(src, dst,
|
paulo@0
|
1394 srcXBase + leftSegX, srcYBase + botSegY,
|
paulo@0
|
1395 dstXBase + 0, dstYBase + blkH/2,
|
paulo@0
|
1396 blkW/2, blkH/2);
|
paulo@0
|
1397 blit(src, dst,
|
paulo@0
|
1398 srcXBase + rightSegX, srcYBase + botSegY,
|
paulo@0
|
1399 dstXBase + blkW/2, dstYBase + blkH/2,
|
paulo@0
|
1400 blkW/2, blkH/2);
|
paulo@0
|
1401 }
|
paulo@0
|
1402 }
|
paulo@0
|
1403 release_bitmap(dst);
|
paulo@0
|
1404 destroy_bitmap(src);
|
paulo@0
|
1405 return dst;
|
paulo@0
|
1406 }
|
paulo@0
|
1407
|
paulo@0
|
1408 void closeWindow(void) {
|
paulo@0
|
1409 set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
|
paulo@0
|
1410 }
|
paulo@0
|
1411
|
paulo@0
|
1412 static void mainCleanup(LJPCView *v) {
|
paulo@0
|
1413 destroyBackBuf(v);
|
paulo@0
|
1414 if (v->skin->blocks) {
|
paulo@0
|
1415 destroy_bitmap(v->skin->blocks);
|
paulo@0
|
1416 }
|
paulo@0
|
1417 if (v->skin->connBlocks) {
|
paulo@0
|
1418 destroy_bitmap(v->skin->connBlocks);
|
paulo@0
|
1419 }
|
paulo@0
|
1420 LJMusic_delete(v->skin->bgm);
|
paulo@0
|
1421 if (withSound) {
|
paulo@0
|
1422 remove_sound();
|
paulo@0
|
1423 }
|
paulo@0
|
1424 closeWindow();
|
paulo@0
|
1425 }
|
paulo@0
|
1426
|
paulo@0
|
1427 /**
|
paulo@0
|
1428 * Resets all skin settings to their initial values
|
paulo@0
|
1429 * so that skins can override them.
|
paulo@0
|
1430 */
|
paulo@0
|
1431 void loadSkinDefaults(LJPCSkin *s) {
|
paulo@0
|
1432 ustrzcpy(ljblocksSRSName, sizeof(ljblocksSRSName) - 1,
|
paulo@0
|
1433 "ljblocks.bmp");
|
paulo@0
|
1434 ustrzcpy(ljblocksSegaName, sizeof(ljblocksSegaName) - 1,
|
paulo@0
|
1435 "ljblocks-sega.bmp");
|
paulo@0
|
1436 ustrzcpy(ljconnSRSName, sizeof(ljconnSRSName) - 1,
|
paulo@0
|
1437 "ljconn.bmp");
|
paulo@0
|
1438 ustrzcpy(ljconnSegaName, sizeof(ljconnSegaName) - 1,
|
paulo@0
|
1439 "ljconn-sega.bmp");
|
paulo@0
|
1440 ustrzcpy(ljbgName, sizeof(ljbgName) - 1,
|
paulo@0
|
1441 "ljbg.jpg");
|
paulo@0
|
1442 ustrzcpy(menubgName, sizeof(ljbgName) - 1,
|
paulo@0
|
1443 "menubg.jpg");
|
paulo@0
|
1444 ustrzcpy(bgmName, sizeof(bgmName) - 1,
|
paulo@0
|
1445 "bgm.s3m");
|
paulo@0
|
1446 ustrzcpy(bgmRhythmName, sizeof(bgmRhythmName) - 1,
|
paulo@0
|
1447 "bgm-rhythm.s3m");
|
paulo@0
|
1448 bgmLoopPoint = 0;
|
paulo@0
|
1449 bgmReadyGo = 0;
|
paulo@0
|
1450 bgmVolume = 128;
|
paulo@0
|
1451 bgColor = makecol(255, 255, 255);
|
paulo@0
|
1452 fgColor = makecol(0, 0, 0);
|
paulo@0
|
1453 hiliteColor = makecol(255, 255, 204);
|
paulo@0
|
1454 pfBgColor = makecol(0, 0, 0);
|
paulo@0
|
1455 pfFgColor = makecol(255, 255, 255);
|
paulo@0
|
1456 s->blkW = 24;
|
paulo@0
|
1457 s->blkH = 24;
|
paulo@0
|
1458 s->transparentPF = 0;
|
paulo@0
|
1459 s->shiftScale = 0;
|
paulo@0
|
1460 s->baseX = 0;
|
paulo@0
|
1461 s->nextPos = 0;
|
paulo@0
|
1462 }
|
paulo@0
|
1463
|
paulo@0
|
1464 /**
|
paulo@0
|
1465 * Converts a single hexadecimal digit to its value.
|
paulo@0
|
1466 * @param in USASCII/Unicode value of hex digit character
|
paulo@0
|
1467 * @return value
|
paulo@0
|
1468 */
|
paulo@0
|
1469 int hexDigitValue(int in) {
|
paulo@0
|
1470 if (in >= '0' && in <= '9') {
|
paulo@0
|
1471 return in - '0';
|
paulo@0
|
1472 } else if (in >= 'A' && in <= 'F') {
|
paulo@0
|
1473 return in - 'A' + 10;
|
paulo@0
|
1474 } else if (in >= 'a' && in <= 'f') {
|
paulo@0
|
1475 return in - 'a' + 10;
|
paulo@0
|
1476 } else {
|
paulo@0
|
1477 return -1;
|
paulo@0
|
1478 }
|
paulo@0
|
1479 }
|
paulo@0
|
1480
|
paulo@0
|
1481 int translateComponent(const char **in, size_t nDigits) {
|
paulo@0
|
1482 const char *here = *in;
|
paulo@0
|
1483 int hi = hexDigitValue(*here++);
|
paulo@0
|
1484 int lo = nDigits > 3 ? hexDigitValue(*here++) : hi;
|
paulo@0
|
1485 *in = here;
|
paulo@0
|
1486 if (hi >= 0 && lo >= 0) {
|
paulo@0
|
1487 return hi * 16 + lo;
|
paulo@0
|
1488 } else {
|
paulo@0
|
1489 return -1;
|
paulo@0
|
1490 }
|
paulo@0
|
1491 }
|
paulo@0
|
1492
|
paulo@0
|
1493 /**
|
paulo@0
|
1494 * Interprets a hexadecimal color specifier.
|
paulo@0
|
1495 * @param in hexadecimal color specifier, in #ABC or #AABBCC format
|
paulo@0
|
1496 * @return Allegro device-dependent color, in makecol() format
|
paulo@0
|
1497 */
|
paulo@0
|
1498 int translateColor(const char *in) {
|
paulo@0
|
1499 size_t nDigits = 0;
|
paulo@0
|
1500
|
paulo@0
|
1501 // Verify and skip #
|
paulo@0
|
1502 if (*in != '#') {
|
paulo@0
|
1503 return -1;
|
paulo@0
|
1504 }
|
paulo@0
|
1505 ++in;
|
paulo@0
|
1506
|
paulo@0
|
1507 // Determine whether we have a 3-digit color or a 6-digit color
|
paulo@0
|
1508 for (const char *here = in;
|
paulo@0
|
1509 hexDigitValue(*here) >= 0;
|
paulo@0
|
1510 ++here) {
|
paulo@0
|
1511 ++nDigits;
|
paulo@0
|
1512 }
|
paulo@0
|
1513 if (nDigits != 3 && nDigits != 6) {
|
paulo@0
|
1514 return -1;
|
paulo@0
|
1515 }
|
paulo@0
|
1516
|
paulo@0
|
1517 int red = translateComponent(&in, nDigits);
|
paulo@0
|
1518 int green = translateComponent(&in, nDigits);
|
paulo@0
|
1519 int blue = translateComponent(&in, nDigits);
|
paulo@0
|
1520 if (red >= 0 && green >= 0 && blue >= 0) {
|
paulo@0
|
1521 return makecol(red, green, blue);
|
paulo@0
|
1522 } else {
|
paulo@0
|
1523 return -1;
|
paulo@0
|
1524 }
|
paulo@0
|
1525 };
|
paulo@0
|
1526
|
paulo@0
|
1527 /**
|
paulo@0
|
1528 * Loads skin parameters from the file.
|
paulo@0
|
1529 * @param skinName Name of skin ini file
|
paulo@0
|
1530 */
|
paulo@0
|
1531 int loadSkinFile(LJPCSkin *s, const char *skinName) {
|
paulo@0
|
1532
|
paulo@0
|
1533 // Don't use ljfopen here because lj.ini specifies the absolute skin file
|
paulo@0
|
1534 FILE *fp = fopen(skinName, "rt");
|
paulo@0
|
1535 char key[1024], var[1024], val[1024], input_buf[1024];
|
paulo@0
|
1536
|
paulo@0
|
1537 key[0] = 0;
|
paulo@0
|
1538 var[0] = 0;
|
paulo@0
|
1539 val[0] = 0;
|
paulo@0
|
1540 loadSkinDefaults(s);
|
paulo@0
|
1541
|
paulo@0
|
1542 if (!fp) return 0;
|
paulo@0
|
1543 while(1) {
|
paulo@0
|
1544 int rval;
|
paulo@0
|
1545
|
paulo@0
|
1546 if(!fgets (input_buf, sizeof(input_buf), fp))
|
paulo@0
|
1547 break;
|
paulo@0
|
1548 rval = parse_ini_line(input_buf, key, var, val);
|
paulo@0
|
1549
|
paulo@0
|
1550 if(!ustrcmp ("ljblocksSRS", var)) {
|
paulo@0
|
1551 ustrzcpy(ljblocksSRSName, sizeof(ljblocksSRSName) - 1, val);
|
paulo@0
|
1552 }
|
paulo@0
|
1553 else if(!ustrcmp ("ljblocksSega", var)) {
|
paulo@0
|
1554 ustrzcpy(ljblocksSegaName, sizeof(ljblocksSegaName) - 1, val);
|
paulo@0
|
1555 }
|
paulo@0
|
1556 else if(!ustrcmp ("ljconnSRS", var)) {
|
paulo@0
|
1557 ustrzcpy(ljconnSRSName, sizeof(ljconnSRSName) - 1, val);
|
paulo@0
|
1558 }
|
paulo@0
|
1559 else if(!ustrcmp ("ljconnSega", var)) {
|
paulo@0
|
1560 ustrzcpy(ljconnSegaName, sizeof(ljconnSegaName) - 1, val);
|
paulo@0
|
1561 }
|
paulo@0
|
1562 else if(!ustrcmp ("bgm", var)) {
|
paulo@0
|
1563 ustrzcpy(bgmName, sizeof(bgmName) - 1, val);
|
paulo@0
|
1564 }
|
paulo@0
|
1565 else if(!ustrcmp ("bgmRhythm", var)) {
|
paulo@0
|
1566 ustrzcpy(bgmRhythmName, sizeof(bgmRhythmName) - 1, val);
|
paulo@0
|
1567 }
|
paulo@0
|
1568 else if(!ustrcmp ("ljbg", var)) {
|
paulo@0
|
1569 ustrzcpy(ljbgName, sizeof(ljbgName) - 1, val);
|
paulo@0
|
1570 }
|
paulo@0
|
1571 else if(!ustrcmp ("bgmLoopPoint", var)) {
|
paulo@0
|
1572 unsigned long int c = strtoul(val, NULL, 0);
|
paulo@0
|
1573 if (c >= 0) {
|
paulo@0
|
1574 bgmLoopPoint = c;
|
paulo@0
|
1575 }
|
paulo@0
|
1576 }
|
paulo@0
|
1577 else if(!ustrcmp ("bgmVolume", var)) {
|
paulo@0
|
1578 unsigned long int c = strtol(val, NULL, 0);
|
paulo@0
|
1579 if (c >= 0) {
|
paulo@0
|
1580 bgmVolume = c;
|
paulo@0
|
1581 }
|
paulo@0
|
1582 }
|
paulo@0
|
1583 else if(!ustrcmp ("bgmReadyGo", var)) {
|
paulo@0
|
1584 unsigned long int c = strtoul(val, NULL, 0);
|
paulo@0
|
1585 if (c >= 0) {
|
paulo@0
|
1586 bgmReadyGo = c;
|
paulo@0
|
1587 }
|
paulo@0
|
1588 }
|
paulo@0
|
1589 else if(!ustrcmp ("pfbgcolor", var)) {
|
paulo@0
|
1590 int c = translateColor(val);
|
paulo@0
|
1591 if (c >= 0) {
|
paulo@0
|
1592 pfBgColor = c;
|
paulo@0
|
1593 }
|
paulo@0
|
1594 }
|
paulo@0
|
1595 else if(!ustrcmp ("pfcolor", var)) {
|
paulo@0
|
1596 int c = translateColor(val);
|
paulo@0
|
1597 if (c >= 0) {
|
paulo@0
|
1598 pfFgColor = c;
|
paulo@0
|
1599 }
|
paulo@0
|
1600 }
|
paulo@0
|
1601 else if(!ustrcmp ("bgcolor", var)) {
|
paulo@0
|
1602 int c = translateColor(val);
|
paulo@0
|
1603 if (c >= 0) {
|
paulo@0
|
1604 bgColor = c;
|
paulo@0
|
1605 }
|
paulo@0
|
1606 }
|
paulo@0
|
1607 else if(!ustrcmp ("color", var)) {
|
paulo@0
|
1608 int c = translateColor(val);
|
paulo@0
|
1609 if (c >= 0) {
|
paulo@0
|
1610 fgColor = c;
|
paulo@0
|
1611 }
|
paulo@0
|
1612 }
|
paulo@0
|
1613 else if(!ustrcmp ("hilitecolor", var)) {
|
paulo@0
|
1614 int c = translateColor(val);
|
paulo@0
|
1615 if (c >= 0) {
|
paulo@0
|
1616 hiliteColor = c;
|
paulo@0
|
1617 }
|
paulo@0
|
1618 }
|
paulo@0
|
1619 else if(!ustrcmp ("blkW", var)) {
|
paulo@0
|
1620 int c = strtol(val, NULL, 0);
|
paulo@0
|
1621 if (c >= 0) {
|
paulo@0
|
1622 s->blkW = c;
|
paulo@0
|
1623 }
|
paulo@0
|
1624 }
|
paulo@0
|
1625 else if(!ustrcmp ("blkH", var)) {
|
paulo@0
|
1626 int c = strtol(val, NULL, 0);
|
paulo@0
|
1627 if (c >= 0) {
|
paulo@0
|
1628 s->blkH = c;
|
paulo@0
|
1629 }
|
paulo@0
|
1630 }
|
paulo@0
|
1631 else if(!ustrcmp ("transparentPF", var)) {
|
paulo@0
|
1632 int c = atoi(val);
|
paulo@0
|
1633 if (c >= 0) {
|
paulo@0
|
1634 s->transparentPF = c;
|
paulo@0
|
1635 }
|
paulo@0
|
1636 }
|
paulo@0
|
1637 else if(!ustrcmp ("shiftScale", var)) {
|
paulo@0
|
1638 int c = atoi(val);
|
paulo@0
|
1639 if (c >= 0) {
|
paulo@0
|
1640 s->shiftScale = c;
|
paulo@0
|
1641 }
|
paulo@0
|
1642 }
|
paulo@0
|
1643 else if(!ustrcmp ("baseX", var)) {
|
paulo@0
|
1644 int c = atoi(val);
|
paulo@0
|
1645 if (c >= 0) {
|
paulo@0
|
1646 s->baseX = c;
|
paulo@0
|
1647 }
|
paulo@0
|
1648 }
|
paulo@0
|
1649 else if(!ustrcmp ("nextPos", var)) {
|
paulo@0
|
1650 int c = atoi(val);
|
paulo@0
|
1651 if (c >= 0) {
|
paulo@0
|
1652 s->nextPos = c;
|
paulo@0
|
1653 }
|
paulo@0
|
1654 }
|
paulo@0
|
1655 else if(!ustrcmp ("wndW", var)) {
|
paulo@0
|
1656 unsigned long int c = strtol(val, NULL, 0);
|
paulo@0
|
1657 if (c >= 0) {
|
paulo@0
|
1658 skinW = c;
|
paulo@0
|
1659 }
|
paulo@0
|
1660 }
|
paulo@0
|
1661 else if(!ustrcmp ("wndH", var)) {
|
paulo@0
|
1662 unsigned long int c = strtoul(val, NULL, 0);
|
paulo@0
|
1663 if (c >= 0) {
|
paulo@0
|
1664 skinH = c;
|
paulo@0
|
1665 }
|
paulo@0
|
1666 }
|
paulo@0
|
1667
|
paulo@0
|
1668 }
|
paulo@0
|
1669 fclose(fp);
|
paulo@0
|
1670 ljpathSetSkinFolder(skinName);
|
paulo@0
|
1671 return 0;
|
paulo@0
|
1672 }
|
paulo@0
|
1673
|
paulo@0
|
1674 static void drawProgressSegment(int min, int max) {
|
paulo@0
|
1675 min = min * SCREEN_W / 100;
|
paulo@0
|
1676 max = max * SCREEN_W / 100;
|
paulo@0
|
1677 int blue = makecol(0, 0, 255);
|
paulo@0
|
1678 rectfill(screen, min, SCREEN_H - 8, max - 1, SCREEN_H - 5, blue);
|
paulo@0
|
1679 int orange = makecol(255, 128, 0);
|
paulo@0
|
1680 rectfill(screen, min, SCREEN_H - 4, max - 1, SCREEN_H - 1, orange);
|
paulo@0
|
1681 }
|
paulo@0
|
1682
|
paulo@0
|
1683 static int loadSkin(LJView *v, const char *skinName) {
|
paulo@0
|
1684 BITMAP *bmp;
|
paulo@0
|
1685 const LJRotSystem *rs = rotSystems[v->field->rotationSystem];
|
paulo@0
|
1686 int colorScheme = rs->colorScheme;
|
paulo@0
|
1687
|
paulo@0
|
1688 rectfill(screen, 0, 592, 799, 599, 0);
|
paulo@0
|
1689 loadSkinFile(v->plat->skin, skinName);
|
paulo@0
|
1690
|
paulo@0
|
1691 destroyBackBuf(v->plat);
|
paulo@0
|
1692 if (!createBackBuf(v)) {
|
paulo@0
|
1693 allegro_message("Could not create back buffer.\n");
|
paulo@0
|
1694 return 1;
|
paulo@0
|
1695 }
|
paulo@0
|
1696
|
paulo@0
|
1697 drawProgressSegment(0, 20);
|
paulo@0
|
1698
|
paulo@0
|
1699 // Load background image
|
paulo@0
|
1700 char path[PATH_MAX];
|
paulo@0
|
1701 bmp = ljpathFind_r(path, ljbgName)
|
paulo@0
|
1702 ? load_bitmap(path, NULL) : NULL;
|
paulo@0
|
1703 if (v->plat->skin->bg) {
|
paulo@0
|
1704 destroy_bitmap(v->plat->skin->bg);
|
paulo@0
|
1705 }
|
paulo@0
|
1706 if (bmp) {
|
paulo@0
|
1707
|
paulo@0
|
1708 // If the image size doesn't match the window size, resize it
|
paulo@0
|
1709 if (bmp->w != SCREEN_W || bmp->h != SCREEN_H) {
|
paulo@0
|
1710 BITMAP *resized = create_bitmap(SCREEN_W, SCREEN_H);
|
paulo@0
|
1711
|
paulo@0
|
1712 if (resized) {
|
paulo@0
|
1713 stretch_blit(bmp, resized, 0, 0, bmp->w, bmp->h,
|
paulo@0
|
1714 0, 0, SCREEN_W, SCREEN_H);
|
paulo@0
|
1715 destroy_bitmap(bmp);
|
paulo@0
|
1716 }
|
paulo@0
|
1717 if (bmp) {
|
paulo@0
|
1718 bmp = resized;
|
paulo@0
|
1719 } else {
|
paulo@0
|
1720 allegro_message("Background image \"%s\" resize failed.\n",
|
paulo@0
|
1721 ljbgName);
|
paulo@0
|
1722 }
|
paulo@0
|
1723 }
|
paulo@0
|
1724 }
|
paulo@0
|
1725 if(!bmp) {
|
paulo@0
|
1726 bmp = create_bitmap(SCREEN_W, SCREEN_H);
|
paulo@0
|
1727 if (bmp) {
|
paulo@0
|
1728 allegro_message("Background image \"%s\" not found.\n"
|
paulo@0
|
1729 "Using plain background instead.\n",
|
paulo@0
|
1730 ljbgName);
|
paulo@0
|
1731 clear_to_color(bmp, bgColor);
|
paulo@0
|
1732 } else {
|
paulo@0
|
1733 allegro_message("Background image \"%s\" not found.\n",
|
paulo@0
|
1734 ljbgName);
|
paulo@0
|
1735 return 0;
|
paulo@0
|
1736 }
|
paulo@0
|
1737 }
|
paulo@0
|
1738 v->plat->skin->bg = bmp;
|
paulo@0
|
1739 drawProgressSegment(20, 40);
|
paulo@0
|
1740
|
paulo@0
|
1741 // load block images
|
paulo@0
|
1742 if (v->plat->skin->blocks) {
|
paulo@0
|
1743 destroy_bitmap(v->plat->skin->blocks);
|
paulo@0
|
1744 }
|
paulo@0
|
1745 bmp = ljpathFind_r(path, colorScheme
|
paulo@0
|
1746 ? ljblocksSegaName
|
paulo@0
|
1747 : ljblocksSRSName)
|
paulo@0
|
1748 ? load_bitmap(path, NULL) : NULL;
|
paulo@0
|
1749 v->plat->skin->blocks = bmp;
|
paulo@0
|
1750 if(!v->plat->skin->blocks) {
|
paulo@0
|
1751 allegro_message("Background image \"%s\" not found.\n",
|
paulo@0
|
1752 ljbgName);
|
paulo@0
|
1753 return 0;
|
paulo@0
|
1754 }
|
paulo@0
|
1755 drawProgressSegment(40, 60);
|
paulo@0
|
1756
|
paulo@0
|
1757 // load connected block images
|
paulo@0
|
1758 if (v->plat->skin->connBlocks) {
|
paulo@0
|
1759 destroy_bitmap(v->plat->skin->connBlocks);
|
paulo@0
|
1760 }
|
paulo@0
|
1761 bmp = ljpathFind_r(path, colorScheme
|
paulo@0
|
1762 ? ljconnSegaName
|
paulo@0
|
1763 : ljconnSRSName)
|
paulo@0
|
1764 ? loadConnections(path,
|
paulo@0
|
1765 v->plat->skin->blkW,
|
paulo@0
|
1766 v->plat->skin->blkH)
|
paulo@0
|
1767 : NULL;
|
paulo@0
|
1768 v->plat->skin->connBlocks = bmp;
|
paulo@0
|
1769 drawProgressSegment(60, 80);
|
paulo@0
|
1770
|
paulo@0
|
1771 // load music
|
paulo@0
|
1772 int isRhythm = (v->field->speedState.curve == LJSPD_RHYTHM);
|
paulo@0
|
1773 if (ljpathFind_r(path, isRhythm ? bgmRhythmName : bgmName)) {
|
paulo@0
|
1774 LJMusic_load(v->plat->skin->bgm, path);
|
paulo@0
|
1775 }
|
paulo@0
|
1776 if (!isRhythm) {
|
paulo@0
|
1777 LJMusic_setLoop(v->plat->skin->bgm, bgmLoopPoint);
|
paulo@0
|
1778 }
|
paulo@0
|
1779 drawProgressSegment(80, 100);
|
paulo@0
|
1780 return 1;
|
paulo@0
|
1781 }
|
paulo@0
|
1782
|
paulo@0
|
1783 void drop_mouse(void) {
|
paulo@0
|
1784 while (mouse_y < SCREEN_H - 25) {
|
paulo@0
|
1785 position_mouse(mouse_x, mouse_y + 20);
|
paulo@0
|
1786 rest(10);
|
paulo@0
|
1787 }
|
paulo@0
|
1788 ezPlaySample("land_wav", 192);
|
paulo@0
|
1789 position_mouse(mouse_x, SCREEN_H - 5);
|
paulo@0
|
1790 ezPlaySample("lock_wav", 192);
|
paulo@0
|
1791 }
|
paulo@0
|
1792
|
paulo@0
|
1793 int pickReplay(void) {
|
paulo@0
|
1794 FONT *oldFont = font;
|
paulo@0
|
1795 font = (FONT *)aver16;
|
paulo@0
|
1796 install_mouse();
|
paulo@0
|
1797 int got = file_select_ex("Choose a demo:", demoFilename, "ljm", sizeof(demoFilename), 600, 400);
|
paulo@0
|
1798 drop_mouse();
|
paulo@0
|
1799 remove_mouse();
|
paulo@0
|
1800 font = oldFont;
|
paulo@0
|
1801 return got ? 0 : -1;
|
paulo@0
|
1802 }
|
paulo@0
|
1803
|
paulo@0
|
1804 void badReplay(void) {
|
paulo@0
|
1805 acquire_screen();
|
paulo@0
|
1806 clear_to_color(screen, bgColor);
|
paulo@0
|
1807 textout_ex(screen, aver32, "The demo", 100, 100, fgColor, -1);
|
paulo@0
|
1808 textout_ex(screen, aver16, demoFilename, 100, 130, fgColor, -1);
|
paulo@0
|
1809 textout_ex(screen, aver32, "could not be played because it was", 100, 150, fgColor, -1);
|
paulo@0
|
1810 textout_ex(screen, aver32, "recorded with a different version", 100, 180, fgColor, -1);
|
paulo@0
|
1811 textout_ex(screen, aver32, "of LOCKJAW software.", 100, 210, fgColor, -1);
|
paulo@0
|
1812 release_screen();
|
paulo@0
|
1813
|
paulo@0
|
1814 LJBits lastKeys = ~0;
|
paulo@0
|
1815 LJBits keys, newKeys = 0;
|
paulo@0
|
1816
|
paulo@0
|
1817 do {
|
paulo@0
|
1818 keys = menuReadPad();
|
paulo@0
|
1819 newKeys = keys & ~lastKeys;
|
paulo@0
|
1820 lastKeys = keys;
|
paulo@0
|
1821 rest(30);
|
paulo@0
|
1822 } while (!(newKeys & (VKEY_ROTL | VKEY_ROTR)));
|
paulo@0
|
1823 }
|
paulo@0
|
1824
|
paulo@0
|
1825 int pickSkin(void) {
|
paulo@0
|
1826 FONT *oldFont = font;
|
paulo@0
|
1827 font = (FONT *)aver16;
|
paulo@0
|
1828 install_mouse();
|
paulo@0
|
1829 int got = file_select_ex("Choose a skin:", skinName, "skin", sizeof(skinName), 600, 400);
|
paulo@0
|
1830 drop_mouse();
|
paulo@0
|
1831 remove_mouse();
|
paulo@0
|
1832 font = oldFont;
|
paulo@0
|
1833 return got ? 0 : -1;
|
paulo@0
|
1834 }
|
paulo@0
|
1835
|
paulo@0
|
1836 void calcElev(LJView *v) {
|
paulo@0
|
1837 int blkH = v->plat->skin->blkH;
|
paulo@0
|
1838 int ceiling = v->field->ceiling;
|
paulo@0
|
1839 int elev = (LJ_PF_VIS_HT - ceiling) * blkH;
|
paulo@0
|
1840
|
paulo@0
|
1841 if (elev > 480 - ceiling * blkH) {
|
paulo@0
|
1842 elev = 480 - ceiling * blkH;
|
paulo@0
|
1843 }
|
paulo@0
|
1844 if (elev < 0) {
|
paulo@0
|
1845 elev = 0;
|
paulo@0
|
1846 }
|
paulo@0
|
1847 v->plat->skin->pfElev = elev;
|
paulo@0
|
1848 }
|
paulo@0
|
1849
|
paulo@0
|
1850 int main(const int argc, const char *const *argv) {
|
paulo@0
|
1851 const char *cmdLineDemo = NULL;
|
paulo@0
|
1852 int lastPreset = -2; // start out with full custom
|
paulo@0
|
1853 LJPCSkin skin = {
|
paulo@0
|
1854 .baseY = 552,
|
paulo@0
|
1855 .blkW = 24,
|
paulo@0
|
1856 .blkH = 24
|
paulo@0
|
1857 };
|
paulo@0
|
1858 LJField p[MAX_PLAYERS];
|
paulo@0
|
1859 LJControl control[2] = {
|
paulo@0
|
1860 {
|
paulo@0
|
1861 .replaySrc = 0,
|
paulo@0
|
1862 .replayDst = 0
|
paulo@0
|
1863 }
|
paulo@0
|
1864 };
|
paulo@0
|
1865 LJPCView platView[MAX_PLAYERS] = {
|
paulo@0
|
1866 {
|
paulo@0
|
1867 .skin = &skin
|
paulo@0
|
1868 },
|
paulo@0
|
1869 {
|
paulo@0
|
1870 .skin = &skin
|
paulo@0
|
1871 }
|
paulo@0
|
1872 };
|
paulo@0
|
1873 LJView mainView[MAX_PLAYERS] = {
|
paulo@0
|
1874 {
|
paulo@0
|
1875 .field = &p[0],
|
paulo@0
|
1876 .control = &control[0],
|
paulo@0
|
1877 .plat = &platView[0],
|
paulo@0
|
1878 .backDirty = ~0
|
paulo@0
|
1879 },
|
paulo@0
|
1880 {
|
paulo@0
|
1881 .field = &p[1],
|
paulo@0
|
1882 .control = &control[1],
|
paulo@0
|
1883 .plat = &platView[1],
|
paulo@0
|
1884 .backDirty = ~0,
|
paulo@0
|
1885 }
|
paulo@0
|
1886 };
|
paulo@0
|
1887
|
paulo@0
|
1888 struct LJPrefs prefs = {
|
paulo@0
|
1889 .number = {
|
paulo@0
|
1890 [OPTIONS_TRAILS] = 1,
|
paulo@0
|
1891 [OPTIONS_AUTO_PAUSE] = 1,
|
paulo@0
|
1892 [OPTIONS_AUTO_RECORD] = 0,
|
paulo@0
|
1893 [OPTIONS_WINDOWED] = 1
|
paulo@0
|
1894 }
|
paulo@0
|
1895 };
|
paulo@0
|
1896
|
paulo@0
|
1897 // as of 0.46, we're starting to make it a bit more 2-player-clean
|
paulo@0
|
1898 int nPlayers = 1;
|
paulo@0
|
1899
|
paulo@0
|
1900 allegro_init();
|
paulo@0
|
1901 ljpathInit(argc > 0 ? argv[0] : ".");
|
paulo@0
|
1902 install_timer();
|
paulo@0
|
1903 initOptions(prefs.number);
|
paulo@0
|
1904 loadOptions(&prefs);
|
paulo@0
|
1905 loadSkinFile(&skin, skinName);
|
paulo@0
|
1906
|
paulo@0
|
1907 if (argc > 1) {
|
paulo@0
|
1908 if (argv[1][0] == '-') {
|
paulo@0
|
1909 if (!ustrcmp("--help", argv[1])
|
paulo@0
|
1910 || !ustrcmp("-h", argv[1])) {
|
paulo@0
|
1911 allegro_message("Usage: lj [DEMOFILE]\n");
|
paulo@0
|
1912 return 0;
|
paulo@0
|
1913 }
|
paulo@0
|
1914 } else {
|
paulo@0
|
1915 cmdLineDemo = argv[1];
|
paulo@0
|
1916 }
|
paulo@0
|
1917 }
|
paulo@0
|
1918
|
paulo@0
|
1919 if (openWindow(prefs.number[OPTIONS_WINDOWED]) != 0) {
|
paulo@0
|
1920 allegro_message("LOCKJAW fatal error: Could not open an %dx%d pixel %s.\n"
|
paulo@0
|
1921 "Trying %s next time.\n",
|
paulo@0
|
1922 skinW, skinH,
|
paulo@0
|
1923 prefs.number[OPTIONS_WINDOWED] ? "window": "screen mode",
|
paulo@0
|
1924 prefs.number[OPTIONS_WINDOWED] ? "the full screen": "a window");
|
paulo@0
|
1925 prefs.number[OPTIONS_WINDOWED] = !prefs.number[OPTIONS_WINDOWED];
|
paulo@0
|
1926 saveOptions(&prefs);
|
paulo@0
|
1927 return EXIT_FAILURE;
|
paulo@0
|
1928 }
|
paulo@0
|
1929 drawCoprNotice();
|
paulo@0
|
1930 LOCK_FUNCTION(incCurTime);
|
paulo@0
|
1931 LOCK_VARIABLE(curTime);
|
paulo@0
|
1932 install_int_ex(incCurTime, BPM_TO_TIMER(LJ_TICK_RATE));
|
paulo@0
|
1933
|
paulo@0
|
1934 jpgalleg_init();
|
paulo@0
|
1935 set_color_conversion(COLORCONV_NONE);
|
paulo@0
|
1936 {
|
paulo@0
|
1937 char path[PATH_MAX];
|
paulo@0
|
1938 if (ljpathFind_r(path, "lj.dat")) {
|
paulo@0
|
1939 dat = load_datafile(path);
|
paulo@0
|
1940 }
|
paulo@0
|
1941 }
|
paulo@0
|
1942 set_color_conversion(COLORCONV_TOTAL);
|
paulo@0
|
1943 if(!dat) {
|
paulo@0
|
1944 closeWindow();
|
paulo@0
|
1945 allegro_message("LOCKJAW fatal error: Could not load datafile lj.dat\n");
|
paulo@0
|
1946 return 1;
|
paulo@0
|
1947 }
|
paulo@0
|
1948
|
paulo@0
|
1949 {
|
paulo@0
|
1950 const DATAFILE *aver16dat = find_datafile_object(dat, "Aver16_bmp");
|
paulo@0
|
1951 aver16 = aver16dat ? aver16dat->dat : font;
|
paulo@0
|
1952 const DATAFILE *aver32dat = find_datafile_object(dat, "Aver32_bmp");
|
paulo@0
|
1953 aver32 = aver32dat ? aver32dat->dat : aver16;
|
paulo@0
|
1954 }
|
paulo@0
|
1955
|
paulo@0
|
1956 LOCK_FUNCTION(amnesia);
|
paulo@0
|
1957 LOCK_VARIABLE(redrawWholeScreen);
|
paulo@0
|
1958
|
paulo@0
|
1959 // If we can be notified on switching out, take this notification.
|
paulo@0
|
1960 if (set_display_switch_mode(SWITCH_BACKGROUND) >= 0
|
paulo@0
|
1961 || set_display_switch_mode(SWITCH_BACKAMNESIA) >= 0) {
|
paulo@0
|
1962 set_display_switch_callback(SWITCH_OUT, requestPause);
|
paulo@0
|
1963 }
|
paulo@0
|
1964 set_display_switch_callback(SWITCH_IN, amnesia);
|
paulo@0
|
1965
|
paulo@0
|
1966 install_keyboard();
|
paulo@0
|
1967 initKeys();
|
paulo@0
|
1968
|
paulo@0
|
1969 for (int i = 0; i < MAX_PLAYERS; ++i) {
|
paulo@0
|
1970 p[i].seed = time(NULL) + 123456789*i;
|
paulo@0
|
1971 }
|
paulo@0
|
1972
|
paulo@0
|
1973 reserve_voices(8, 0);
|
paulo@0
|
1974 set_volume_per_voice(0);
|
paulo@0
|
1975 #ifdef ALLEGRO_WINDOWS
|
paulo@0
|
1976 // Under Windows, use the Allegro mixer because on my machine
|
paulo@0
|
1977 // and probably others, the built-in mixer will replace the very
|
paulo@0
|
1978 // beginning of one sound with the end of the last sound played
|
paulo@0
|
1979 // on that voice.
|
paulo@0
|
1980 withSound = !install_sound(DIGI_DIRECTAMX(0), MIDI_NONE, NULL);
|
paulo@0
|
1981 #else
|
paulo@0
|
1982 withSound = !install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL);
|
paulo@0
|
1983 #endif
|
paulo@0
|
1984 skin.bgm = LJMusic_new();
|
paulo@0
|
1985 {
|
paulo@0
|
1986 char path[PATH_MAX];
|
paulo@0
|
1987 if (ljpathFind_r(path, "sound.dat")) {
|
paulo@0
|
1988 sound_dat = load_datafile(path);
|
paulo@0
|
1989 }
|
paulo@0
|
1990 }
|
paulo@0
|
1991
|
paulo@0
|
1992 for (int i = 0; i < MAX_PLAYERS; ++i) {
|
paulo@0
|
1993 unpackOptions(&mainView[i], &prefs);
|
paulo@0
|
1994 }
|
paulo@0
|
1995 if (loadSkin(&mainView[0], skinName) < 0) {
|
paulo@0
|
1996 mainCleanup(platView);
|
paulo@0
|
1997 return EXIT_FAILURE;
|
paulo@0
|
1998 } else {
|
paulo@0
|
1999
|
paulo@0
|
2000 }
|
paulo@0
|
2001
|
paulo@0
|
2002 if(!skin.blocks) {
|
paulo@0
|
2003 mainCleanup(platView);
|
paulo@0
|
2004 allegro_message("Blocks image \"%s\" not found.\n",
|
paulo@0
|
2005 p[0].rotationSystem
|
paulo@0
|
2006 ? ljblocksSegaName
|
paulo@0
|
2007 : ljblocksSRSName);
|
paulo@0
|
2008 return 1;
|
paulo@0
|
2009 }
|
paulo@0
|
2010
|
paulo@0
|
2011 srand(time(NULL));
|
paulo@0
|
2012
|
paulo@0
|
2013 // Wait for copyright notice to be displayed "conspicuously"
|
paulo@0
|
2014 if (curTime < 180) {
|
paulo@0
|
2015 rest(3100 - curTime * 16);
|
paulo@0
|
2016 }
|
paulo@0
|
2017
|
paulo@0
|
2018 for (int action = cmdLineDemo ? TITLE_REPLAY : title();
|
paulo@0
|
2019 action > TITLE_EXIT && !wantsClose;
|
paulo@0
|
2020 action = title()) {
|
paulo@0
|
2021 switch (action) {
|
paulo@0
|
2022 case TITLE_PLAY:
|
paulo@0
|
2023 for (int preset = getPreset(lastPreset);
|
paulo@0
|
2024 preset != -1 && !wantsClose;
|
paulo@0
|
2025 preset = getPreset(lastPreset))
|
paulo@0
|
2026 {
|
paulo@0
|
2027 lastPreset = preset;
|
paulo@0
|
2028 for (int i = 0; i < MAX_PLAYERS; ++i) {
|
paulo@0
|
2029 unpackOptions(&mainView[i], &prefs);
|
paulo@0
|
2030 }
|
paulo@0
|
2031 if (preset >= 0) {
|
paulo@0
|
2032 presetStart();
|
paulo@0
|
2033 presetAdd(preset);
|
paulo@0
|
2034 for (int i = 0; i < MAX_PLAYERS; ++i) {
|
paulo@0
|
2035 unpackOptions(&mainView[i], &prefs);
|
paulo@0
|
2036 presetFinish(&mainView[i]);
|
paulo@0
|
2037 }
|
paulo@0
|
2038 }
|
paulo@0
|
2039 // reload the skin
|
paulo@0
|
2040 if (loadSkin(&mainView[0], skinName) < 0) {
|
paulo@0
|
2041 mainCleanup(platView);
|
paulo@0
|
2042 return EXIT_FAILURE;
|
paulo@0
|
2043 };
|
paulo@0
|
2044 for (int i = 0; i < nPlayers; ++i) {
|
paulo@0
|
2045 calcElev(&mainView[0]);
|
paulo@0
|
2046 pcInit(&mainView[0], &prefs);
|
paulo@0
|
2047 }
|
paulo@0
|
2048 wantPause = 0;
|
paulo@0
|
2049 platView[0].wantRecord = prefs.number[OPTIONS_AUTO_RECORD];
|
paulo@0
|
2050 LJMusic_start(skin.bgm,
|
paulo@0
|
2051 4096, // mix buffer size
|
paulo@0
|
2052 bgmVolume); // volume scale
|
paulo@0
|
2053
|
paulo@0
|
2054 LJView *const players[MAX_PLAYERS] = {&mainView[0], &mainView[1]};
|
paulo@0
|
2055 play(players, nPlayers);
|
paulo@0
|
2056 LJMusic_stop(skin.bgm);
|
paulo@0
|
2057 if (!wantsClose) {
|
paulo@0
|
2058 gameOverAnimation(&platView[0], &p[0],
|
paulo@0
|
2059 control[0].countdown <= 0);
|
paulo@0
|
2060 debrief(&mainView[0]);
|
paulo@0
|
2061 }
|
paulo@0
|
2062 }
|
paulo@0
|
2063 break;
|
paulo@0
|
2064
|
paulo@0
|
2065 case TITLE_REPLAY:
|
paulo@0
|
2066 {
|
paulo@0
|
2067 if (cmdLineDemo) {
|
paulo@0
|
2068 ustrzcpy(demoFilename, sizeof(demoFilename) - 1,
|
paulo@0
|
2069 cmdLineDemo);
|
paulo@0
|
2070 cmdLineDemo = NULL;
|
paulo@0
|
2071 } else if (pickReplay() < 0) {
|
paulo@0
|
2072 break;
|
paulo@0
|
2073 }
|
paulo@0
|
2074
|
paulo@0
|
2075 unpackOptions(&mainView[0], &prefs);
|
paulo@0
|
2076 calcElev(&mainView[0]);
|
paulo@0
|
2077 pcInit(&mainView[0], &prefs);
|
paulo@0
|
2078 wantPause = 0;
|
paulo@0
|
2079 platView[0].wantRecord = 0;
|
paulo@0
|
2080 LJMusic_start(skin.bgm,
|
paulo@0
|
2081 4096, // mix buffer size
|
paulo@0
|
2082 bgmVolume); // volume scale
|
paulo@0
|
2083
|
paulo@0
|
2084 LJView *const players[2] = {&mainView[0], &mainView[1]};
|
paulo@0
|
2085
|
paulo@0
|
2086 p->gimmick = -1; // gimmick must be < 0 to activate replay
|
paulo@0
|
2087 play(players, 1);
|
paulo@0
|
2088 LJMusic_stop(skin.bgm);
|
paulo@0
|
2089 if (p[0].gimmick < 0) {
|
paulo@0
|
2090 badReplay();
|
paulo@0
|
2091 } else {
|
paulo@0
|
2092 if (!wantsClose) {
|
paulo@0
|
2093 gameOverAnimation(&platView[0], &p[0],
|
paulo@0
|
2094 control[0].countdown <= 0);
|
paulo@0
|
2095 debrief(&mainView[0]);
|
paulo@0
|
2096 }
|
paulo@0
|
2097 }
|
paulo@0
|
2098 }
|
paulo@0
|
2099 break;
|
paulo@0
|
2100
|
paulo@0
|
2101 case TITLE_SKIN:
|
paulo@0
|
2102 pickSkin();
|
paulo@0
|
2103
|
paulo@0
|
2104 // if resolution changed, reopen the window
|
paulo@0
|
2105 {
|
paulo@0
|
2106 int oldW = skinW;
|
paulo@0
|
2107 int oldH = skinH;
|
paulo@0
|
2108 loadSkinFile(&skin, skinName);
|
paulo@0
|
2109 if (skinH != oldH || skinW != oldW) {
|
paulo@0
|
2110 destroySystemBitmaps(&platView[0]);
|
paulo@0
|
2111 openWindow(prefs.number[OPTIONS_WINDOWED]);
|
paulo@0
|
2112 }
|
paulo@0
|
2113 }
|
paulo@0
|
2114
|
paulo@0
|
2115 // reload the skin
|
paulo@0
|
2116 if (loadSkin(&mainView[0], skinName) < 0) {
|
paulo@0
|
2117 mainCleanup(platView);
|
paulo@0
|
2118 return EXIT_FAILURE;
|
paulo@0
|
2119 };
|
paulo@0
|
2120
|
paulo@0
|
2121 // save options
|
paulo@0
|
2122 saveOptions(&prefs);
|
paulo@0
|
2123 break;
|
paulo@0
|
2124
|
paulo@0
|
2125 case TITLE_OPTIONS:
|
paulo@0
|
2126 {
|
paulo@0
|
2127 int oldWindowed = prefs.number[OPTIONS_WINDOWED];
|
paulo@0
|
2128 options(&mainView[0], prefs.number);
|
paulo@0
|
2129 if (oldWindowed != prefs.number[OPTIONS_WINDOWED]) {
|
paulo@0
|
2130 destroySystemBitmaps(&platView[0]);
|
paulo@0
|
2131 openWindow(prefs.number[OPTIONS_WINDOWED]);
|
paulo@0
|
2132 }
|
paulo@0
|
2133 }
|
paulo@0
|
2134 saveOptions(&prefs);
|
paulo@0
|
2135
|
paulo@0
|
2136 // reload the skin if the player changed the rotation system
|
paulo@0
|
2137 unpackOptions(&mainView[0], &prefs);
|
paulo@0
|
2138 if (wantsClose) {
|
paulo@0
|
2139 break;
|
paulo@0
|
2140 }
|
paulo@0
|
2141 if (loadSkin(&mainView[0], skinName) < 0) {
|
paulo@0
|
2142 mainCleanup(platView);
|
paulo@0
|
2143 return EXIT_FAILURE;
|
paulo@0
|
2144 };
|
paulo@0
|
2145 break;
|
paulo@0
|
2146
|
paulo@0
|
2147 case TITLE_KEYS:
|
paulo@0
|
2148 configureKeys();
|
paulo@0
|
2149 break;
|
paulo@0
|
2150
|
paulo@0
|
2151 }
|
paulo@0
|
2152 }
|
paulo@0
|
2153
|
paulo@0
|
2154 mainCleanup(platView);
|
paulo@0
|
2155 return 0;
|
paulo@0
|
2156 } END_OF_MAIN();
|