Mercurial > hg > index.fcgi > lj > lj046-2players
diff src/ljds.c @ 0:c84446dfb3f5
initial add
author | paulo@localhost |
---|---|
date | Fri, 13 Mar 2009 00:39:12 -0700 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/ljds.c Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,334 @@ 1.4 +/* DS frontend for LOCKJAW, an implementation of the Soviet Mind Game 1.5 + 1.6 +Copyright (C) 2006-2007 Damian Yerrick <tepples+lj@spamcop.net> 1.7 + 1.8 +This work is free software; you can redistribute it and/or modify 1.9 +it under the terms of the GNU General Public License as published by 1.10 +the Free Software Foundation; either version 2 of the License, or 1.11 +(at your option) any later version. 1.12 + 1.13 +This program is distributed in the hope that it will be useful, 1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1.16 +GNU General Public License for more details. 1.17 + 1.18 +You should have received a copy of the GNU General Public License 1.19 +along with this program; if not, write to the Free Software 1.20 +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 1.21 + 1.22 +Original game concept and design by Alexey Pajitnov. 1.23 +The Software is not sponsored or endorsed by Alexey Pajitnov, Elorg, 1.24 +or The Tetris Company LLC. 1.25 + 1.26 +*/ 1.27 + 1.28 +#include "ljplay.h" 1.29 +#include "ljds.h" 1.30 +#include "talkback.h" 1.31 +#include <stdio.h> 1.32 +#include <string.h> 1.33 +#include "options.h" 1.34 +#include "gbamenus.h" 1.35 +#include "ljpath.h" 1.36 + 1.37 +#if 1 1.38 + #define LJ_VERSION "0.46 ("__DATE__")" 1.39 +#else 1.40 + #define LJ_VERSION "WIP ("__DATE__")" 1.41 +#endif 1.42 + 1.43 +#define SCREEN_W 32 1.44 +#define SCREEN_H 24 1.45 +#define DS_PFTOP 3 1.46 +#define DS_PFLEFT 10 1.47 + 1.48 +/* My ghetto IPC system */ 1.49 +volatile P8A7Talkback tb_cached = { 1.50 + .cmd = 0, 1.51 + .sounds = 0 1.52 +}; 1.53 + 1.54 +#define tb (*(volatile P8A7Talkback *) \ 1.55 + ((volatile char *)&tb_cached + 0x00400000)) 1.56 + 1.57 +short mouse_x, mouse_y; 1.58 +LJBits mouse_b; 1.59 + 1.60 +#include "ljgbads.inc" 1.61 + 1.62 +unsigned int nSprites = 0; 1.63 +volatile int curTime; 1.64 + 1.65 +void gba_play_sound(struct LJPCView *v, int n) { 1.66 + 1.67 +} 1.68 + 1.69 +void gba_poll_sound(struct LJPCView *plat) { 1.70 + 1.71 +} 1.72 + 1.73 +LJBits readHWKeys(void) { 1.74 + scanKeys(); 1.75 + LJBits j = keysHeld(); 1.76 + touchPosition xy = touchReadXY(); 1.77 + 1.78 + if (j & KEY_TOUCH) { 1.79 + mouse_x = xy.px; 1.80 + mouse_y = xy.py; 1.81 + mouse_b = 1; 1.82 + j &= ~(KEY_TOUCH_RIGHT | KEY_TOUCH_LEFT 1.83 + | KEY_TOUCH_UP | KEY_TOUCH_DOWN); 1.84 + if (xy.px < 96) { 1.85 + j |= KEY_TOUCH_LEFT; 1.86 + } else if (xy.px >= 160) { 1.87 + j |= KEY_TOUCH_RIGHT; 1.88 + } 1.89 + if (xy.py < 64) { 1.90 + j |= KEY_TOUCH_UP; 1.91 + } else if (xy.py >= 128) { 1.92 + j |= KEY_TOUCH_DOWN; 1.93 + } 1.94 + } else { 1.95 + mouse_b = 0; 1.96 + } 1.97 + return j; 1.98 +} 1.99 + 1.100 +void finishSprites(void) { 1.101 + for (int i = nSprites - 1; i >= 0; --i) { 1.102 + MAINOAM[i].attribute[0] = 512; 1.103 + } 1.104 + nSprites = 128; 1.105 +} 1.106 + 1.107 +void vsync(void) { 1.108 + swiWaitForVBlank(); 1.109 + wantPause |= needLidSleep(); 1.110 +} 1.111 + 1.112 +void isr(void) 1.113 +{ 1.114 + int interrupts = REG_IF; 1.115 + 1.116 + VBLANK_INTR_WAIT_FLAGS |= interrupts; 1.117 + REG_IF = interrupts; 1.118 + ++curTime; 1.119 +} 1.120 + 1.121 +#define KEY_X (IPC_X << 16) 1.122 +#define KEY_Y (IPC_Y << 16) 1.123 +#define KEY_PEN (IPC_PEN_DOWN << 16) 1.124 +#define VRAM_MAIN ((uint16 *)0x06000000) 1.125 +#define VRAM_SUB ((uint16 *)0x06200000) 1.126 + 1.127 + 1.128 + 1.129 +/** 1.130 + * Tells the ARM7 to play these sound effects. 1.131 + */ 1.132 +void playSoundEffects(LJView *v, LJBits sounds, int countdown) { 1.133 + tb.countdown = countdown; 1.134 + tb.sounds |= sounds; 1.135 +} 1.136 + 1.137 +#define SHADOW_BLOCK 0x00 1.138 + 1.139 +/** 1.140 + * Draws a tetromino whose lower left corner of the bounding box is at (x, y) 1.141 + * @param b the bitmap to draw to 1.142 + * @param piece the piece to be drawn 1.143 + * @param x distance from to left side of 4x4 box 1.144 + * @param y distance from top of bitmap to bottom of 4x4 box 1.145 + * @param the rotation state (0: U; 1: R; 2: D; 3: L; 4: Initial position) 1.146 + * @param w width of each block 1.147 + * @param h height of each block 1.148 + * @param color Drawing style 1.149 + * color == 0: draw shadow 1.150 + * color == 0x10 through 0x70: draw in that color 1.151 + * color == 0x80: draw as garbage 1.152 + * color == -255 through -1: draw with 255 through 1 percent lighting 1.153 + */ 1.154 +LJBits drawPiece(LJView *const v, void *const b, 1.155 + int piece, int x, int y, int theta, 1.156 + int color, int w, int h) { 1.157 + // Don't try to draw the -1 that's the sentinel for no hold piece 1.158 + if (piece < 0) 1.159 + return 0; 1.160 + 1.161 + LJBits rows = 0; 1.162 + LJBlkSpec blocks[4]; 1.163 + 1.164 + expandPieceToBlocks(blocks, v->field, piece, 0, 0, theta); 1.165 + 1.166 + for (int blk = 0; blk < 4; ++blk) { 1.167 + int blkValue = blocks[blk].conn; 1.168 + if (blkValue) { 1.169 + int blkX = blocks[blk].x; 1.170 + int blkY = blocks[blk].y; 1.171 + const int dstX = x + w * blkX; 1.172 + const int dstY = y + h * (-1 - blkY); 1.173 + 1.174 + if (color == 0x80) { 1.175 + blkValue = 0x8001; // garbage hold 1.176 + } else if (color != 0) { 1.177 + blkValue = ((blkValue & 0xF0) << 8) | 1; 1.178 + } else if (color == 0) { 1.179 + if (v->hideShadow == LJSHADOW_COLORED) { 1.180 + blkValue = ((blkValue & 0xF0) << 8) | 2; 1.181 + } else { 1.182 + blkValue = 0x8002; 1.183 + } 1.184 + } 1.185 + 1.186 + if (dstY > -8 && dstY < 192) { 1.187 + --nSprites; 1.188 + MAINOAM[nSprites].attribute[0] = dstY & 0x00FF; 1.189 + MAINOAM[nSprites].attribute[1] = dstX & 0x01FF; 1.190 + MAINOAM[nSprites].attribute[2] = blkValue; 1.191 + } 1.192 + 1.193 + rows |= 1 << blkY; 1.194 + } 1.195 + } 1.196 + 1.197 + return rows; 1.198 +} 1.199 + 1.200 +void openWindow(void) { 1.201 + videoSetMode(MODE_0_2D 1.202 + | DISPLAY_BG0_ACTIVE 1.203 + | DISPLAY_SPR_1D_LAYOUT 1.204 + | DISPLAY_SPR_ACTIVE); 1.205 + videoSetModeSub(MODE_0_2D 1.206 + | DISPLAY_BG0_ACTIVE); 1.207 + BGCTRL[0] = BG_16_COLOR | BG_TILE_BASE(0) | BG_MAP_BASE(31); 1.208 + BGCTRL_SUB[0] = BG_16_COLOR | BG_TILE_BASE(0) | BG_MAP_BASE(31); 1.209 + 1.210 + vramSetMainBanks(VRAM_A_MAIN_BG, VRAM_B_MAIN_SPRITE_0x06400000, 1.211 + VRAM_C_SUB_BG, VRAM_D_SUB_SPRITE); 1.212 + /* load_font(); */ 1.213 + // Load palette 1.214 + BG_PALETTE[0] = RGB5(31,31,31); 1.215 + BG_PALETTE[1] = RGB5( 0, 0,15); 1.216 + BG_PALETTE_SUB[0] = RGB5(0, 0, 0); 1.217 + setupPalette(srsColors); 1.218 + 1.219 + // Set scrolling 1.220 + BG_OFFSET[0].x = 0; 1.221 + BG_OFFSET[0].y = 0; 1.222 + BG_OFFSET_SUB[0].x = 0; 1.223 + BG_OFFSET_SUB[0].y = 0; 1.224 + 1.225 + SUB_BG2_XDX = 0x100; 1.226 + SUB_BG2_XDY = 0; 1.227 + SUB_BG2_YDX = 0; 1.228 + SUB_BG2_YDY = 0x100; 1.229 + SUB_BG2_CY = 0; 1.230 + SUB_BG2_CX = 0; 1.231 + 1.232 + lcdMainOnTop(); 1.233 +} 1.234 + 1.235 +void install_sound(void) { 1.236 + IPC->soundData = (void *)&tb; 1.237 +} 1.238 + 1.239 +#ifdef TRAP_SPRINTF 1.240 +int sprintf (char *dst, const char *format, ...) { 1.241 + BG_PALETTE[0] = RGB5(31, 0, 0); 1.242 + strcpy(dst, "[NO FPU]"); 1.243 + return 8; 1.244 +} 1.245 +#endif 1.246 + 1.247 +int main(void) { 1.248 + LJField p = { 1.249 + .leftWall = 1, 1.250 + .rightWall = 11, 1.251 + .ceiling = 20 1.252 + }; 1.253 + LJControl control = { 1.254 + .dasSpeed = 1, 1.255 + .dasDelay = 10, 1.256 + .initialDAS = 1, 1.257 + .allowDiagonals = 0, 1.258 + .softDropSpeed = 0, 1.259 + .softDropLock = 0, 1.260 + .hardDropLock = 1 1.261 + }; 1.262 + struct LJPCView platView; 1.263 + LJView mainView = { 1.264 + .field = &p, 1.265 + .control = &control, 1.266 + .smoothGravity = 1, 1.267 + .nextPieces = 3, 1.268 + .plat = &platView, 1.269 + .backDirty = ~0 1.270 + }; 1.271 + 1.272 + powerON(POWER_ALL_2D); 1.273 + initOptions(customPrefs); 1.274 + install_timer(); 1.275 + install_sound(); 1.276 + openWindow(); 1.277 + 1.278 + BG_PALETTE_SUB[0] = RGB5( 0, 0, 0); 1.279 + BG_PALETTE_SUB[1] = RGB5(10,20,10); 1.280 + BG_PALETTE_SUB[2] = RGB5(15,31,15); 1.281 + BG_PALETTE_SUB[3] = RGB5(15,31,15); 1.282 + vwfWinInit(&vwfTouch); 1.283 + { 1.284 + int x = vwfPuts(&vwfTouch, "finding memory card... ", 0, 0); 1.285 + if (ljpathInit("/data/lockjaw/lj.nds")) { 1.286 + vwfPuts(&vwfTouch, "success!", x, 0); 1.287 + } else { 1.288 + vwfPuts(&vwfTouch, "failed.", x, 0); 1.289 + vwfPuts(&vwfTouch, "To learn how to fix this, see", 0, 12); 1.290 + vwfPuts(&vwfTouch, "http://dldi.drunkencoders.com/", 0, 24); 1.291 + } 1.292 + } 1.293 + 1.294 + coprNotice(); 1.295 + 1.296 + load_font(); 1.297 + drawFrame(&mainView); 1.298 + 1.299 + while (1) { 1.300 + LJView *const players[1] = {&mainView}; 1.301 + 1.302 + for (int y = 0; y < LJ_PF_VIS_HT; ++y) { 1.303 + for (int x = 0; x < LJ_PF_WID; ++x) { 1.304 + p.b[y][x] = 0; 1.305 + } 1.306 + } 1.307 + updField(&mainView, ~0); 1.308 + 1.309 + // turn on sub display only long enough for options 1.310 + videoSetModeSub(MODE_0_2D 1.311 + | DISPLAY_BG0_ACTIVE); 1.312 + setupPalette(srsColors); 1.313 + options(&mainView, customPrefs); 1.314 + videoSetModeSub(MODE_0_2D); 1.315 + BGCTRL_SUB[0] = BG_16_COLOR | BG_TILE_BASE(0) | BG_MAP_BASE(31); 1.316 + BG_PALETTE_SUB[0] = RGB5(0, 0, 0); 1.317 + unpackCommonOptions(&mainView, customPrefs); 1.318 + 1.319 + p.seed = curTime ^ (curTime << 16); 1.320 + play(players, 1); 1.321 + 1.322 + tb.cmd = TALKBACK_STOP_MUSIC; 1.323 + BG_PALETTE[0] = (control.countdown > 0) 1.324 + ? RGB5(31, 15, 15) 1.325 + : RGB5(15, 31, 15); 1.326 + 1.327 + // play game over sound 1.328 + if (control.countdown > 0) { 1.329 + playSoundEffects(&mainView, 3 << 16, control.countdown); 1.330 + } 1.331 + for (int i = 0; i < 60; ++i) { 1.332 + vsync(); 1.333 + //gba_poll_sound(&platView); 1.334 + } 1.335 + debrief(&mainView); 1.336 + } 1.337 +}