Mercurial > hg > index.fcgi > lj > lj046
comparison src/ljds.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39: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 } |