annotate 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
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 }