annotate src/ljgba.c @ 3:17286938e22a

change DS alt. rotate key to rotate twice
author paulo@localhost
date Wed, 08 Apr 2009 21:50:13 -0700
parents
children
rev   line source
paulo@0 1 /* GBA 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 <stdio.h>
paulo@0 26 #include <string.h>
paulo@0 27 #include "ljgba.h"
paulo@0 28 #include "ljplay.h"
paulo@0 29 #include "options.h"
paulo@0 30
paulo@0 31 #if 1
paulo@0 32 #define LJ_VERSION "0.46 ("__DATE__")"
paulo@0 33 #else
paulo@0 34 #define LJ_VERSION "WIP ("__DATE__")"
paulo@0 35 #endif
paulo@0 36
paulo@0 37 #define SCREEN_W 30
paulo@0 38 #define SCREEN_H 20
paulo@0 39 #define DS_PFTOP 0
paulo@0 40 #define DS_PFLEFT 9
paulo@0 41 #include "ljgbads.inc"
paulo@0 42
paulo@0 43 static unsigned int nSprites;
paulo@0 44
paulo@0 45 LJBits readHWKeys(void) {
paulo@0 46 return (~REG_KEYINPUT) & 0x03FF;
paulo@0 47 }
paulo@0 48
paulo@0 49 void finishSprites() {
paulo@0 50 for (int i = nSprites - 1; i >= 0; --i) {
paulo@0 51 OAM[i].attr0 = 512;
paulo@0 52 }
paulo@0 53 nSprites = 128;
paulo@0 54 }
paulo@0 55
paulo@0 56 void vsync(void) {
paulo@0 57 VBlankIntrWait();
paulo@0 58 }
paulo@0 59
paulo@0 60 void openWindow(void) {
paulo@0 61 REG_DISPCNT = MODE_0 | BG0_ON | OBJ_ON;
paulo@0 62 BGCTRL[0] = BG_TILE_BASE(0) | BG_MAP_BASE(31);
paulo@0 63 BG_PALETTE[0] = RGB5(31, 31, 31);
paulo@0 64 BG_PALETTE[1] = RGB5(0, 0, 0);
paulo@0 65 SPRITE_PALETTE[0] = RGB5(31, 0, 31);
paulo@0 66 SPRITE_PALETTE[1] = RGB5(0, 0, 0);
paulo@0 67 setupPalette(srsColors);
paulo@0 68 }
paulo@0 69
paulo@0 70 void playSoundEffects(LJView *v, LJBits sounds, int countdown) {
paulo@0 71 if (sounds & LJSND_IRS) {
paulo@0 72 gba_play_sound(v->plat, 6);
paulo@0 73 } else if (sounds & LJSND_ROTATE) {
paulo@0 74 gba_play_sound(v->plat, 1);
paulo@0 75 }
paulo@0 76 if (sounds & LJSND_SHIFT) {
paulo@0 77 gba_play_sound(v->plat, 0);
paulo@0 78 }
paulo@0 79 if (sounds & LJSND_LAND) {
paulo@0 80 gba_play_sound(v->plat, 2);
paulo@0 81 }
paulo@0 82 if (sounds & LJSND_LOCK) {
paulo@0 83 gba_play_sound(v->plat, 3);
paulo@0 84 }
paulo@0 85 if (sounds & LJSND_B2B) {
paulo@0 86 gba_play_sound(v->plat, 8);
paulo@0 87 } else if (sounds & LJSND_SETB2B) {
paulo@0 88 gba_play_sound(v->plat, 7);
paulo@0 89 } else if (sounds & LJSND_LINE) {
paulo@0 90 gba_play_sound(v->plat, 4);
paulo@0 91 }
paulo@0 92 if (sounds & LJSND_HOLD) {
paulo@0 93 gba_play_sound(v->plat, 5);
paulo@0 94 }
paulo@0 95 if (sounds & LJSND_SECTIONUP) {
paulo@0 96 gba_play_sound(v->plat, 9);
paulo@0 97 }
paulo@0 98 gba_poll_sound(v->plat);
paulo@0 99 }
paulo@0 100
paulo@0 101 /**
paulo@0 102 * Draws a tetromino whose lower left corner of the bounding box is at (x, y)
paulo@0 103 * @param b the bitmap to draw to
paulo@0 104 * @param piece the piece to be drawn
paulo@0 105 * @param x distance from to left side of 4x4 box
paulo@0 106 * @param y distance from top of bitmap to bottom of 4x4 box
paulo@0 107 * @param the rotation state (0: U; 1: R; 2: D; 3: L; 4: Initial position)
paulo@0 108 * @param w width of each block
paulo@0 109 * @param h height of each block
paulo@0 110 * @param color Drawing style
paulo@0 111 * color == 0: draw shadow
paulo@0 112 * color == 0x10 through 0x70: draw in that color
paulo@0 113 * color == 0x80: draw as garbage
paulo@0 114 * color == -255 through -1: draw with 255 through 1 percent lighting
paulo@0 115 */
paulo@0 116 LJBits drawPiece(LJView *const v, void *const b,
paulo@0 117 int piece, int x, int y, int theta,
paulo@0 118 int color, int w, int h) {
paulo@0 119 // Don't try to draw the -1 that's the sentinel for no hold piece
paulo@0 120 if (piece < 0)
paulo@0 121 return 0;
paulo@0 122
paulo@0 123 LJBits rows = 0;
paulo@0 124 LJBlkSpec blocks[4];
paulo@0 125
paulo@0 126 expandPieceToBlocks(blocks, v->field, piece, 0, 0, theta);
paulo@0 127
paulo@0 128 for (int blk = 0; blk < 4; ++blk) {
paulo@0 129 int blkValue = blocks[blk].conn;
paulo@0 130 if (blkValue) {
paulo@0 131 int blkX = blocks[blk].x;
paulo@0 132 int blkY = blocks[blk].y;
paulo@0 133 const int dstX = x + w * blkX;
paulo@0 134 const int dstY = y + h * (-1 - blkY);
paulo@0 135
paulo@0 136 if (color == 0x80) {
paulo@0 137 blkValue = 0x8001; // garbage hold
paulo@0 138 } else if (color != 0) {
paulo@0 139 blkValue = ((blkValue & 0xF0) << 8) | 1;
paulo@0 140 } else if (color == 0) {
paulo@0 141 if (v->hideShadow == LJSHADOW_COLORED) {
paulo@0 142 blkValue = ((blkValue & 0xF0) << 8) | 2;
paulo@0 143 } else {
paulo@0 144 blkValue = 0x0002;
paulo@0 145 }
paulo@0 146 }
paulo@0 147
paulo@0 148 if (dstY > -8 && dstY < 160) {
paulo@0 149 --nSprites;
paulo@0 150 OAM[nSprites].attr0 = dstY & 0x00FF;
paulo@0 151 OAM[nSprites].attr1 = dstX & 0x01FF;
paulo@0 152 OAM[nSprites].attr2 = blkValue;
paulo@0 153 }
paulo@0 154
paulo@0 155 rows |= 1 << blkY;
paulo@0 156 }
paulo@0 157 }
paulo@0 158
paulo@0 159 return rows;
paulo@0 160 }
paulo@0 161
paulo@0 162 extern unsigned char prefs[OPTIONS_MENU_LEN];
paulo@0 163
paulo@0 164 #include "gbamenus.h"
paulo@0 165
paulo@0 166 int main(void) {
paulo@0 167 LJField p = {
paulo@0 168 .leftWall = 1,
paulo@0 169 .rightWall = 11,
paulo@0 170 .ceiling = 20
paulo@0 171 };
paulo@0 172 LJControl control = {
paulo@0 173 .dasSpeed = 1,
paulo@0 174 .dasDelay = 10,
paulo@0 175 .initialDAS = 1,
paulo@0 176 .allowDiagonals = 0,
paulo@0 177 .softDropSpeed = 0,
paulo@0 178 .softDropLock = 0,
paulo@0 179 .hardDropLock = 1
paulo@0 180 };
paulo@0 181 struct LJPCView platView;
paulo@0 182 LJView mainView = {
paulo@0 183 .field = &p,
paulo@0 184 .control = &control,
paulo@0 185 .smoothGravity = 1,
paulo@0 186 .plat = &platView,
paulo@0 187 .backDirty = ~0
paulo@0 188 };
paulo@0 189
paulo@0 190 videoSetMode(MODE_0_2D);
paulo@0 191 BG_PALETTE[0] = RGB5(31, 0, 0);
paulo@0 192 install_timer();
paulo@0 193 openWindow();
paulo@0 194 install_sound(&platView);
paulo@0 195 initOptions(customPrefs);
paulo@0 196 coprNotice();
paulo@0 197
paulo@0 198 while (1) {
paulo@0 199 LJView *const players[1] = {&mainView};
paulo@0 200 REG_DISPCNT = MODE_0 | BG0_ON;
paulo@0 201 BG_PALETTE[0] = RGB5(31, 31, 31);
paulo@0 202 setupPalette(srsColors);
paulo@0 203 options(&mainView, customPrefs);
paulo@0 204 unpackCommonOptions(&mainView, customPrefs);
paulo@0 205
paulo@0 206 p.seed = curTime ^ (curTime << 16);
paulo@0 207 play(players, 1);
paulo@0 208 BG_PALETTE[0] = (control.countdown > 0)
paulo@0 209 ? RGB5(31, 15, 15)
paulo@0 210 : RGB5(15, 31, 15);
paulo@0 211 if (control.countdown > 0) {
paulo@0 212 gba_play_sound(&platView, 10);
paulo@0 213 gba_play_sound(&platView, 11);
paulo@0 214 } else {
paulo@0 215 gba_play_sound(&platView, 12);
paulo@0 216 gba_play_sound(&platView, 13);
paulo@0 217 }
paulo@0 218 for (int i = 0; i < 60; ++i) {
paulo@0 219 vsync();
paulo@0 220 gba_poll_sound(&platView);
paulo@0 221 }
paulo@0 222 #if 1
paulo@0 223 debrief(&mainView);
paulo@0 224 #else
paulo@0 225 textout(" Press ", (SCREEN_W - 8) / 2, DS_PFTOP + 8, 0);
paulo@0 226 textout(" Start ", (SCREEN_W - 8) / 2, DS_PFTOP + 9, 0);
paulo@0 227 waitForStart();
paulo@0 228 #endif
paulo@0 229 }
paulo@0 230 }