rev |
line source |
paulo@0
|
1 /* DS frontend for LOCKJAW, an implementation of the Soviet Mind Game
|
paulo@0
|
2
|
paulo@0
|
3 Copyright (C) 2006-2007 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 "ljplay.h"
|
paulo@0
|
26 #include "ljds.h"
|
paulo@0
|
27 #include "talkback.h"
|
paulo@0
|
28 #include <stdio.h>
|
paulo@0
|
29 #include <string.h>
|
paulo@0
|
30 #include "options.h"
|
paulo@0
|
31 #include "gbamenus.h"
|
paulo@0
|
32 #include "ljpath.h"
|
paulo@0
|
33
|
paulo@0
|
34 #if 1
|
paulo@0
|
35 #define LJ_VERSION "0.46 ("__DATE__")"
|
paulo@0
|
36 #else
|
paulo@0
|
37 #define LJ_VERSION "WIP ("__DATE__")"
|
paulo@0
|
38 #endif
|
paulo@0
|
39
|
paulo@0
|
40 #define SCREEN_W 32
|
paulo@0
|
41 #define SCREEN_H 24
|
paulo@0
|
42 #define DS_PFTOP 3
|
paulo@0
|
43 #define DS_PFLEFT 10
|
paulo@0
|
44
|
paulo@0
|
45 /* My ghetto IPC system */
|
paulo@0
|
46 volatile P8A7Talkback tb_cached = {
|
paulo@0
|
47 .cmd = 0,
|
paulo@0
|
48 .sounds = 0
|
paulo@0
|
49 };
|
paulo@0
|
50
|
paulo@0
|
51 #define tb (*(volatile P8A7Talkback *) \
|
paulo@0
|
52 ((volatile char *)&tb_cached + 0x00400000))
|
paulo@0
|
53
|
paulo@0
|
54 short mouse_x, mouse_y;
|
paulo@0
|
55 LJBits mouse_b;
|
paulo@0
|
56
|
paulo@0
|
57 #include "ljgbads.inc"
|
paulo@0
|
58
|
paulo@0
|
59 unsigned int nSprites = 0;
|
paulo@0
|
60 volatile int curTime;
|
paulo@0
|
61
|
paulo@0
|
62 void gba_play_sound(struct LJPCView *v, int n) {
|
paulo@0
|
63
|
paulo@0
|
64 }
|
paulo@0
|
65
|
paulo@0
|
66 void gba_poll_sound(struct LJPCView *plat) {
|
paulo@0
|
67
|
paulo@0
|
68 }
|
paulo@0
|
69
|
paulo@0
|
70 LJBits readHWKeys(void) {
|
paulo@0
|
71 scanKeys();
|
paulo@0
|
72 LJBits j = keysHeld();
|
paulo@0
|
73 touchPosition xy = touchReadXY();
|
paulo@0
|
74
|
paulo@0
|
75 if (j & KEY_TOUCH) {
|
paulo@0
|
76 mouse_x = xy.px;
|
paulo@0
|
77 mouse_y = xy.py;
|
paulo@0
|
78 mouse_b = 1;
|
paulo@0
|
79 j &= ~(KEY_TOUCH_RIGHT | KEY_TOUCH_LEFT
|
paulo@0
|
80 | KEY_TOUCH_UP | KEY_TOUCH_DOWN);
|
paulo@0
|
81 if (xy.px < 96) {
|
paulo@0
|
82 j |= KEY_TOUCH_LEFT;
|
paulo@0
|
83 } else if (xy.px >= 160) {
|
paulo@0
|
84 j |= KEY_TOUCH_RIGHT;
|
paulo@0
|
85 }
|
paulo@0
|
86 if (xy.py < 64) {
|
paulo@0
|
87 j |= KEY_TOUCH_UP;
|
paulo@0
|
88 } else if (xy.py >= 128) {
|
paulo@0
|
89 j |= KEY_TOUCH_DOWN;
|
paulo@0
|
90 }
|
paulo@0
|
91 } else {
|
paulo@0
|
92 mouse_b = 0;
|
paulo@0
|
93 }
|
paulo@0
|
94 return j;
|
paulo@0
|
95 }
|
paulo@0
|
96
|
paulo@0
|
97 void finishSprites(void) {
|
paulo@0
|
98 for (int i = nSprites - 1; i >= 0; --i) {
|
paulo@0
|
99 MAINOAM[i].attribute[0] = 512;
|
paulo@0
|
100 }
|
paulo@0
|
101 nSprites = 128;
|
paulo@0
|
102 }
|
paulo@0
|
103
|
paulo@0
|
104 void vsync(void) {
|
paulo@0
|
105 swiWaitForVBlank();
|
paulo@0
|
106 wantPause |= needLidSleep();
|
paulo@0
|
107 }
|
paulo@0
|
108
|
paulo@0
|
109 void isr(void)
|
paulo@0
|
110 {
|
paulo@0
|
111 int interrupts = REG_IF;
|
paulo@0
|
112
|
paulo@0
|
113 VBLANK_INTR_WAIT_FLAGS |= interrupts;
|
paulo@0
|
114 REG_IF = interrupts;
|
paulo@0
|
115 ++curTime;
|
paulo@0
|
116 }
|
paulo@0
|
117
|
paulo@0
|
118 #define KEY_X (IPC_X << 16)
|
paulo@0
|
119 #define KEY_Y (IPC_Y << 16)
|
paulo@0
|
120 #define KEY_PEN (IPC_PEN_DOWN << 16)
|
paulo@0
|
121 #define VRAM_MAIN ((uint16 *)0x06000000)
|
paulo@0
|
122 #define VRAM_SUB ((uint16 *)0x06200000)
|
paulo@0
|
123
|
paulo@0
|
124
|
paulo@0
|
125
|
paulo@0
|
126 /**
|
paulo@0
|
127 * Tells the ARM7 to play these sound effects.
|
paulo@0
|
128 */
|
paulo@0
|
129 void playSoundEffects(LJView *v, LJBits sounds, int countdown) {
|
paulo@0
|
130 tb.countdown = countdown;
|
paulo@0
|
131 tb.sounds |= sounds;
|
paulo@0
|
132 }
|
paulo@0
|
133
|
paulo@0
|
134 #define SHADOW_BLOCK 0x00
|
paulo@0
|
135
|
paulo@0
|
136 /**
|
paulo@0
|
137 * Draws a tetromino whose lower left corner of the bounding box is at (x, y)
|
paulo@0
|
138 * @param b the bitmap to draw to
|
paulo@0
|
139 * @param piece the piece to be drawn
|
paulo@0
|
140 * @param x distance from to left side of 4x4 box
|
paulo@0
|
141 * @param y distance from top of bitmap to bottom of 4x4 box
|
paulo@0
|
142 * @param the rotation state (0: U; 1: R; 2: D; 3: L; 4: Initial position)
|
paulo@0
|
143 * @param w width of each block
|
paulo@0
|
144 * @param h height of each block
|
paulo@0
|
145 * @param color Drawing style
|
paulo@0
|
146 * color == 0: draw shadow
|
paulo@0
|
147 * color == 0x10 through 0x70: draw in that color
|
paulo@0
|
148 * color == 0x80: draw as garbage
|
paulo@0
|
149 * color == -255 through -1: draw with 255 through 1 percent lighting
|
paulo@0
|
150 */
|
paulo@0
|
151 LJBits drawPiece(LJView *const v, void *const b,
|
paulo@0
|
152 int piece, int x, int y, int theta,
|
paulo@0
|
153 int color, int w, int h) {
|
paulo@0
|
154 // Don't try to draw the -1 that's the sentinel for no hold piece
|
paulo@0
|
155 if (piece < 0)
|
paulo@0
|
156 return 0;
|
paulo@0
|
157
|
paulo@0
|
158 LJBits rows = 0;
|
paulo@0
|
159 LJBlkSpec blocks[4];
|
paulo@0
|
160
|
paulo@0
|
161 expandPieceToBlocks(blocks, v->field, piece, 0, 0, theta);
|
paulo@0
|
162
|
paulo@0
|
163 for (int blk = 0; blk < 4; ++blk) {
|
paulo@0
|
164 int blkValue = blocks[blk].conn;
|
paulo@0
|
165 if (blkValue) {
|
paulo@0
|
166 int blkX = blocks[blk].x;
|
paulo@0
|
167 int blkY = blocks[blk].y;
|
paulo@0
|
168 const int dstX = x + w * blkX;
|
paulo@0
|
169 const int dstY = y + h * (-1 - blkY);
|
paulo@0
|
170
|
paulo@0
|
171 if (color == 0x80) {
|
paulo@0
|
172 blkValue = 0x8001; // garbage hold
|
paulo@0
|
173 } else if (color != 0) {
|
paulo@0
|
174 blkValue = ((blkValue & 0xF0) << 8) | 1;
|
paulo@0
|
175 } else if (color == 0) {
|
paulo@0
|
176 if (v->hideShadow == LJSHADOW_COLORED) {
|
paulo@0
|
177 blkValue = ((blkValue & 0xF0) << 8) | 2;
|
paulo@0
|
178 } else {
|
paulo@0
|
179 blkValue = 0x8002;
|
paulo@0
|
180 }
|
paulo@0
|
181 }
|
paulo@0
|
182
|
paulo@0
|
183 if (dstY > -8 && dstY < 192) {
|
paulo@0
|
184 --nSprites;
|
paulo@0
|
185 MAINOAM[nSprites].attribute[0] = dstY & 0x00FF;
|
paulo@0
|
186 MAINOAM[nSprites].attribute[1] = dstX & 0x01FF;
|
paulo@0
|
187 MAINOAM[nSprites].attribute[2] = blkValue;
|
paulo@0
|
188 }
|
paulo@0
|
189
|
paulo@0
|
190 rows |= 1 << blkY;
|
paulo@0
|
191 }
|
paulo@0
|
192 }
|
paulo@0
|
193
|
paulo@0
|
194 return rows;
|
paulo@0
|
195 }
|
paulo@0
|
196
|
paulo@0
|
197 void openWindow(void) {
|
paulo@0
|
198 videoSetMode(MODE_0_2D
|
paulo@0
|
199 | DISPLAY_BG0_ACTIVE
|
paulo@0
|
200 | DISPLAY_SPR_1D_LAYOUT
|
paulo@0
|
201 | DISPLAY_SPR_ACTIVE);
|
paulo@0
|
202 videoSetModeSub(MODE_0_2D
|
paulo@0
|
203 | DISPLAY_BG0_ACTIVE);
|
paulo@0
|
204 BGCTRL[0] = BG_16_COLOR | BG_TILE_BASE(0) | BG_MAP_BASE(31);
|
paulo@0
|
205 BGCTRL_SUB[0] = BG_16_COLOR | BG_TILE_BASE(0) | BG_MAP_BASE(31);
|
paulo@0
|
206
|
paulo@0
|
207 vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_SPRITE_0x06400000,
|
paulo@0
|
208 VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE);
|
paulo@0
|
209 /* load_font(); */
|
paulo@0
|
210 // Load palette
|
paulo@0
|
211 BG_PALETTE[0] = RGB5(31,31,31);
|
paulo@0
|
212 BG_PALETTE[1] = RGB5( 0, 0,15);
|
paulo@0
|
213 BG_PALETTE_SUB[0] = RGB5(0, 0, 0);
|
paulo@0
|
214 setupPalette(srsColors);
|
paulo@0
|
215
|
paulo@0
|
216 // Set scrolling
|
paulo@0
|
217 BG_OFFSET[0].x = 0;
|
paulo@0
|
218 BG_OFFSET[0].y = 0;
|
paulo@0
|
219 BG_OFFSET_SUB[0].x = 0;
|
paulo@0
|
220 BG_OFFSET_SUB[0].y = 0;
|
paulo@0
|
221
|
paulo@0
|
222 SUB_BG2_XDX = 0x100;
|
paulo@0
|
223 SUB_BG2_XDY = 0;
|
paulo@0
|
224 SUB_BG2_YDX = 0;
|
paulo@0
|
225 SUB_BG2_YDY = 0x100;
|
paulo@0
|
226 SUB_BG2_CY = 0;
|
paulo@0
|
227 SUB_BG2_CX = 0;
|
paulo@0
|
228
|
paulo@0
|
229 lcdMainOnTop();
|
paulo@0
|
230 }
|
paulo@0
|
231
|
paulo@0
|
232 void install_sound(void) {
|
paulo@0
|
233 IPC->soundData = (void *)&tb;
|
paulo@0
|
234 }
|
paulo@0
|
235
|
paulo@0
|
236 #ifdef TRAP_SPRINTF
|
paulo@0
|
237 int sprintf (char *dst, const char *format, ...) {
|
paulo@0
|
238 BG_PALETTE[0] = RGB5(31, 0, 0);
|
paulo@0
|
239 strcpy(dst, "[NO FPU]");
|
paulo@0
|
240 return 8;
|
paulo@0
|
241 }
|
paulo@0
|
242 #endif
|
paulo@0
|
243
|
paulo@0
|
244 int main(void) {
|
paulo@0
|
245 LJField p = {
|
paulo@0
|
246 .leftWall = 1,
|
paulo@0
|
247 .rightWall = 11,
|
paulo@0
|
248 .ceiling = 20
|
paulo@0
|
249 };
|
paulo@0
|
250 LJControl control = {
|
paulo@0
|
251 .dasSpeed = 1,
|
paulo@0
|
252 .dasDelay = 10,
|
paulo@0
|
253 .initialDAS = 1,
|
paulo@0
|
254 .allowDiagonals = 0,
|
paulo@0
|
255 .softDropSpeed = 0,
|
paulo@0
|
256 .softDropLock = 0,
|
paulo@0
|
257 .hardDropLock = 1
|
paulo@0
|
258 };
|
paulo@0
|
259 struct LJPCView platView;
|
paulo@0
|
260 LJView mainView = {
|
paulo@0
|
261 .field = &p,
|
paulo@0
|
262 .control = &control,
|
paulo@0
|
263 .smoothGravity = 1,
|
paulo@0
|
264 .nextPieces = 3,
|
paulo@0
|
265 .plat = &platView,
|
paulo@0
|
266 .backDirty = ~0
|
paulo@0
|
267 };
|
paulo@0
|
268
|
paulo@0
|
269 powerON(POWER_ALL_2D);
|
paulo@0
|
270 initOptions(customPrefs);
|
paulo@0
|
271 install_timer();
|
paulo@0
|
272 install_sound();
|
paulo@0
|
273 openWindow();
|
paulo@0
|
274
|
paulo@0
|
275 BG_PALETTE_SUB[0] = RGB5( 0, 0, 0);
|
paulo@0
|
276 BG_PALETTE_SUB[1] = RGB5(10,20,10);
|
paulo@0
|
277 BG_PALETTE_SUB[2] = RGB5(15,31,15);
|
paulo@0
|
278 BG_PALETTE_SUB[3] = RGB5(15,31,15);
|
paulo@0
|
279 vwfWinInit(&vwfTouch);
|
paulo@0
|
280 {
|
paulo@0
|
281 int x = vwfPuts(&vwfTouch, "finding memory card... ", 0, 0);
|
paulo@0
|
282 if (ljpathInit("/data/lockjaw/lj.nds")) {
|
paulo@0
|
283 vwfPuts(&vwfTouch, "success!", x, 0);
|
paulo@0
|
284 } else {
|
paulo@0
|
285 vwfPuts(&vwfTouch, "failed.", x, 0);
|
paulo@0
|
286 vwfPuts(&vwfTouch, "To learn how to fix this, see", 0, 12);
|
paulo@0
|
287 vwfPuts(&vwfTouch, "http://dldi.drunkencoders.com/", 0, 24);
|
paulo@0
|
288 }
|
paulo@0
|
289 }
|
paulo@0
|
290
|
paulo@0
|
291 coprNotice();
|
paulo@0
|
292
|
paulo@0
|
293 load_font();
|
paulo@0
|
294 drawFrame(&mainView);
|
paulo@0
|
295
|
paulo@0
|
296 while (1) {
|
paulo@0
|
297 LJView *const players[1] = {&mainView};
|
paulo@0
|
298
|
paulo@0
|
299 for (int y = 0; y < LJ_PF_VIS_HT; ++y) {
|
paulo@0
|
300 for (int x = 0; x < LJ_PF_WID; ++x) {
|
paulo@0
|
301 p.b[y][x] = 0;
|
paulo@0
|
302 }
|
paulo@0
|
303 }
|
paulo@0
|
304 updField(&mainView, ~0);
|
paulo@0
|
305
|
paulo@0
|
306 // turn on sub display only long enough for options
|
paulo@0
|
307 videoSetModeSub(MODE_0_2D
|
paulo@0
|
308 | DISPLAY_BG0_ACTIVE);
|
paulo@0
|
309 setupPalette(srsColors);
|
paulo@0
|
310 options(&mainView, customPrefs);
|
paulo@0
|
311 videoSetModeSub(MODE_0_2D);
|
paulo@0
|
312 BGCTRL_SUB[0] = BG_16_COLOR | BG_TILE_BASE(0) | BG_MAP_BASE(31);
|
paulo@0
|
313 BG_PALETTE_SUB[0] = RGB5(0, 0, 0);
|
paulo@0
|
314 unpackCommonOptions(&mainView, customPrefs);
|
paulo@0
|
315
|
paulo@0
|
316 p.seed = curTime ^ (curTime << 16);
|
paulo@0
|
317 play(players, 1);
|
paulo@0
|
318
|
paulo@0
|
319 tb.cmd = TALKBACK_STOP_MUSIC;
|
paulo@0
|
320 BG_PALETTE[0] = (control.countdown > 0)
|
paulo@0
|
321 ? RGB5(31, 15, 15)
|
paulo@0
|
322 : RGB5(15, 31, 15);
|
paulo@0
|
323
|
paulo@0
|
324 // play game over sound
|
paulo@0
|
325 if (control.countdown > 0) {
|
paulo@0
|
326 playSoundEffects(&mainView, 3 << 16, control.countdown);
|
paulo@0
|
327 }
|
paulo@0
|
328 for (int i = 0; i < 60; ++i) {
|
paulo@0
|
329 vsync();
|
paulo@0
|
330 //gba_poll_sound(&platView);
|
paulo@0
|
331 }
|
paulo@0
|
332 debrief(&mainView);
|
paulo@0
|
333 }
|
paulo@0
|
334 }
|