comparison src/ljds.c @ 2:80a2761bd3a4

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