Mercurial > hg > index.fcgi > lj > lj046-2players
diff src/gbamenus.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/gbamenus.c Fri Mar 13 00:39:12 2009 -0700 1.3 @@ -0,0 +1,458 @@ 1.4 +/* 1.5 + 1.6 +BGCTRL layout 1.7 +Layer 0: Current menu 1.8 +Layer 1: Menu that is fading away 1.9 +Layer 2: Gradient background 1.10 + 1.11 +VRAM layout 1.12 +(1 map == 64 tiles) 1.13 +Tiles 0.000-2FF: layer 0 bitmap 1.14 +Tiles 0.300-3FF: unused 1.15 +Tiles 2.000-2FF: layer 1 bitmap 1.16 +Tiles 2.300-33F: unused 1.17 +Tiles 2.340-36F: map 29 (layer 2) 1.18 +Tiles 2.370-37F: layer 2 gradient tiles 1.19 +Tiles 2.380-3FF: layer 0 map 1.20 +Tiles 2.3C0-3FF: layer 1 map 1.21 + 1.22 + 1.23 +*/ 1.24 + 1.25 +#include <stdint.h> 1.26 +#include <string.h> 1.27 +#include "fontdraw.h" 1.28 +typedef u32 TileSliver; 1.29 + 1.30 +#ifdef ARM9 1.31 +#include <nds.h> 1.32 +#define MENU_GFX_CORE 1 1.33 +#define MENU_GFX_VRAM(bank, tile) (TileSliver *)(BG_TILE_RAM_SUB(bank) + 32 * tile) 1.34 +#define MENU_GFX_MAP ((NAMETABLE *)0x06200000) 1.35 +#define MENU_GFX_BGCTRL BGCTRL_SUB 1.36 +#define MENU_GFX_OFFSET ((bg_scroll *)(0x04001010)) 1.37 +#define HIDDEN_ROWS 0 1.38 +#define HIDDEN_COLS 0 1.39 +#define BG0_ON DISPLAY_BG0_ACTIVE 1.40 +#define BG1_ON DISPLAY_BG1_ACTIVE 1.41 +#define BG2_ON DISPLAY_BG2_ACTIVE 1.42 +#define videoSetModeMenu(x) videoSetModeSub(x) 1.43 +#define MENU_GFX_PALETTE BG_PALETTE_SUB 1.44 +#define USING_TOUCH 1 1.45 +#else 1.46 +#include <gba.h> 1.47 +#define MENU_GFX_CORE 0 1.48 +#define MENU_GFX_VRAM(bank, tile) (TileSliver *)PATRAM4(bank, tile) 1.49 +#define MENU_GFX_MAP MAP 1.50 +#define MENU_GFX_BGCTRL BGCTRL 1.51 +#define MENU_GFX_OFFSET BG_OFFSET 1.52 +#define HIDDEN_ROWS 2 1.53 +#define HIDDEN_COLS 1 1.54 +#define videoSetModeMenu(x) (REG_DISPCNT = x) 1.55 +#define MODE_0_2D 0 1.56 +#define MENU_GFX_PALETTE BG_PALETTE 1.57 +#define USING_TOUCH 0 1.58 +#endif 1.59 + 1.60 +static const VWFWindow vwfLayer0 = { 1.61 + .left = 0, .top = 0, .width = 32, .height = 24, 1.62 + .chrBase = MENU_GFX_VRAM(0, 0), 1.63 + .map = 30, 1.64 + .core = MENU_GFX_CORE, 1.65 + .mapTileBase = 0 1.66 +}; 1.67 + 1.68 +static const VWFWindow vwfLayer1 = { 1.69 + .left = 0, .top = 0, .width = 32, .height = 24, 1.70 + .chrBase = MENU_GFX_VRAM(2, 0), 1.71 + .map = 31, 1.72 + .core = MENU_GFX_CORE, 1.73 + .mapTileBase = 0 1.74 +}; 1.75 + 1.76 + 1.77 +void vsync(void); 1.78 + 1.79 +static const TileSliver gradientBackgroundDelta[8] = { 1.80 + 0x00000000, 1.81 + 0x10101010, 1.82 + 0x00000000, 1.83 + 0x01010101, 1.84 + 0x10101010, 1.85 + 0x01010101, 1.86 + 0x11111111, 1.87 + 0x10101010 1.88 +}; 1.89 + 1.90 +/* Makes 12 gradient background tiles starting at dst. 1.91 +*/ 1.92 + 1.93 +static void makeGradientBackgroundTiles(TileSliver *dst) { 1.94 + for (TileSliver tile = 0x11111111; 1.95 + tile < 0xDDDDDDDD; 1.96 + tile += 0x11111111) { 1.97 + for (unsigned int y = 0; y < 8; ++y) { 1.98 + *dst++ = tile + gradientBackgroundDelta[y]; 1.99 + } 1.100 + } 1.101 +} 1.102 + 1.103 +static void makeLayer2(void) { 1.104 + makeGradientBackgroundTiles(MENU_GFX_VRAM(2, 0x300)); 1.105 + for (int y = 0; y < 12; ++y) { 1.106 + for (int x = 0; x < 32; ++x) { 1.107 + MENU_GFX_MAP[29][y][x] = 0xE300 + y; 1.108 + } 1.109 + } 1.110 + for (int y = 0; y < 12; ++y) { 1.111 + for (int x = 0; x < 32; ++x) { 1.112 + MENU_GFX_MAP[29][y + 12][x] = 0xF300 + y; 1.113 + } 1.114 + } 1.115 + MENU_GFX_BGCTRL[2] = BG_TILE_BASE(2) | BG_MAP_BASE(29); 1.116 + MENU_GFX_OFFSET[2].x = HIDDEN_COLS * 8; 1.117 + MENU_GFX_OFFSET[2].y = HIDDEN_ROWS * 8; 1.118 +} 1.119 + 1.120 + 1.121 + 1.122 +/* 1.123 +Button palette: 1.124 +0 transparent 1.125 +1 White (button top) 1.126 +2 Medium gray (button side) 1.127 +3 Darkest gray (button bottom) 1.128 +4 Light gray (button background) 1.129 +5 Dark gray (button text aa, lower corner) 1.130 +6 Black (button text) 1.131 +7 Black 1.132 + 1.133 +This comes in both ordinary and highlighted versions. There are two copies of the highlighted text. 1.134 + 1.135 +*/ 1.136 + 1.137 +static const TileSliver buttonSideTiles[16] = { 1.138 + 0x11111114, 1.139 + 0x11111142, 1.140 + 0x11111422, 1.141 + 0x44444222, 1.142 + 0x44444222, 1.143 + 0x44444222, 1.144 + 0x44444222, 1.145 + 0x44444222, 1.146 + 0x44444222, 1.147 + 0x44444222, 1.148 + 0x44444222, 1.149 + 0x44444222, 1.150 + 0x44444222, 1.151 + 0x33333522, 1.152 + 0x33333352, 1.153 + 0x33333335 1.154 +}; 1.155 + 1.156 +static void loadButtonSideTiles(void) { 1.157 + for (int bank = 0; bank <= 2; bank += 2) { 1.158 + TileSliver *dst = MENU_GFX_VRAM(bank, 0x30C); 1.159 + memcpy(dst, buttonSideTiles, 32); 1.160 + memcpy(dst + 8, buttonSideTiles + 4, 32); 1.161 + memcpy(dst + 16, buttonSideTiles + 8, 32); 1.162 + } 1.163 +} 1.164 + 1.165 +static const u8 buttonIntensity[8] = 1.166 + {28, 31, 23, 15, 28, 19, 0, 0}; 1.167 + 1.168 +/** 1.169 + * Loads the unhighlighted (gray) button palette. 1.170 + */ 1.171 +static void loadButtonPalette(void) { 1.172 + for (int i = 0; i < 8; ++i) { 1.173 + unsigned int intensity = buttonIntensity[i]; 1.174 + 1.175 + MENU_GFX_PALETTE[192 + i] = intensity * RGB5(1, 1, 1); 1.176 + } 1.177 +} 1.178 + 1.179 +void ljmenu_setHilitePalette(int phase) { 1.180 + 1.181 + // generate triangle wave 1.182 + phase = (phase & 0x3F) ^ 0x20; 1.183 + if (phase & 0x20) { 1.184 + phase ^= 0x3F; 1.185 + } 1.186 + 1.187 + for (int i = 0; i < 8; ++i) { 1.188 + int intensity = buttonIntensity[i]; 1.189 + int intensity34 = (3 * intensity) >> 2; 1.190 + int rg = intensity34 + (phase >> 2) + 4; 1.191 + int b = rg >> 1; 1.192 + if (rg > 31) { 1.193 + rg = 31; 1.194 + } 1.195 + unsigned int c = RGB5(1, 1, 0) * rg + RGB5(0, 0, 1) * b; 1.196 + 1.197 + MENU_GFX_PALETTE[200 + i] = c; 1.198 + MENU_GFX_PALETTE[208 + i] = c; 1.199 + } 1.200 +} 1.201 + 1.202 +#define TILE_HFLIP 0x0400 1.203 + 1.204 +void ljmenu_hiliteButton(int l, int t, int r, int b, int hilite) { 1.205 + hilite = hilite ? 0xD000 : 0xC000; 1.206 + 1.207 + /* Draw sides of button */ 1.208 + MENU_GFX_MAP[30][t][l] = 0x30C | hilite; 1.209 + MENU_GFX_MAP[30][t][r - 1] = 0x30C | TILE_HFLIP | hilite; 1.210 + for (int y = t + 1; y < b - 1; ++y) { 1.211 + MENU_GFX_MAP[30][y][l] = 0x30D | hilite; 1.212 + MENU_GFX_MAP[30][y][r - 1] = 0x30D | TILE_HFLIP | hilite; 1.213 + } 1.214 + MENU_GFX_MAP[30][b - 1][l] = 0x30E | hilite; 1.215 + MENU_GFX_MAP[30][b - 1][r - 1] = 0x30E | TILE_HFLIP | hilite; 1.216 + vwfPutMap(&vwfLayer0, l + 1, t, r - 1, b, hilite); 1.217 +} 1.218 + 1.219 +void ljmenu_drawButton(int l, int t, int r, int b, const char *text) { 1.220 + vwfRectfill(&vwfLayer0, 1.221 + l * 8 + 8, t * 8, r * 8 - 8, t * 8 + 3, 1); 1.222 + vwfRectfill(&vwfLayer0, 1.223 + l * 8 + 8, t * 8 + 3, r * 8 - 8, b * 8 - 3, 4); 1.224 + vwfRectfill(&vwfLayer0, 1.225 + l * 8 + 8, b * 8 - 3, r * 8 - 8, b * 8, 3); 1.226 + 1.227 + int w = fontdraw_strWidth(text); 1.228 + int x = l * 8 + (r - l) * 4 - w / 2; 1.229 + int y = t * 8 + (b - t) * 4 - 12 / 2; 1.230 + 1.231 + vwfPuts(&vwfLayer0, text, x, y); 1.232 + ljmenu_hiliteButton(l, t, r, b, 0); 1.233 +} 1.234 + 1.235 +static void makePalettes(void) { 1.236 + // make background layer palettes 1.237 + for (unsigned int i = 0; i <= 12; ++i) { 1.238 + int blue = 2 * i; 1.239 + MENU_GFX_PALETTE[225 + i]= RGB5(0, 0, blue); 1.240 + } 1.241 + for (unsigned int i = 0; i <= 12; ++i) { 1.242 + int red = ((i + 9) * 3) >> 1; 1.243 + MENU_GFX_PALETTE[241 + i]= RGB5(red, red / 2, 0); 1.244 + } 1.245 + 1.246 + MENU_GFX_PALETTE[1] = RGB5(21,21,23); 1.247 + MENU_GFX_PALETTE[2] = RGB5(31,31,31); 1.248 + MENU_GFX_PALETTE[3] = RGB5(31,31,31); 1.249 + loadButtonPalette(); 1.250 +} 1.251 + 1.252 +void ljmenu_cls(void) { 1.253 + vwfWinInit(&vwfLayer0); 1.254 + vwfPutMap(&vwfLayer0, 2, 4, 30, 22, 0xC000); 1.255 +} 1.256 + 1.257 +void ljmenu_init(void) { 1.258 + makeLayer2(); 1.259 + loadButtonSideTiles(); 1.260 + makePalettes(); 1.261 + ljmenu_cls(); 1.262 + MENU_GFX_BGCTRL[0] = BG_TILE_BASE(0) | BG_MAP_BASE(30); 1.263 + MENU_GFX_OFFSET[0].x = HIDDEN_COLS * 8; 1.264 + MENU_GFX_OFFSET[0].y = HIDDEN_ROWS * 8; 1.265 + MENU_GFX_BGCTRL[1] = BG_TILE_BASE(2) | BG_MAP_BASE(31); 1.266 + MENU_GFX_OFFSET[1].x = HIDDEN_COLS * 8; 1.267 + MENU_GFX_OFFSET[1].y = HIDDEN_ROWS * 8; 1.268 + videoSetModeMenu(MODE_0_2D | BG0_ON | BG1_ON | BG2_ON); 1.269 +} 1.270 + 1.271 +void ljmenu_freeze(void) { 1.272 + 1.273 + // Copy background 1.274 + memcpy(vwfLayer0.chrBase, vwfLayer1.chrBase, 240*160/2); 1.275 + 1.276 + // Copy map 1.277 + memcpy(MENU_GFX_MAP[30], MENU_GFX_MAP[31], sizeof(NAMETABLE)); 1.278 +} 1.279 + 1.280 +void ljmenu_setTitle(const char *topLeft, const char *topRight) { 1.281 + vwfRectfill(&vwfLayer0, 16, 16, 240, 16 + 12, 0); 1.282 + vwfPuts(&vwfLayer0, topLeft, 16, 16); 1.283 + if (topRight) { 1.284 + int x = 240 - fontdraw_strWidth(topRight); 1.285 + vwfPuts(&vwfLayer0, topRight, x, 16); 1.286 + } 1.287 +} 1.288 + 1.289 +static unsigned short tabsX; 1.290 +static unsigned short tabsPadding; 1.291 +#define TAB_TOP 32 1.292 +#define TAB_BOTTOM 44 1.293 +#define TAB_LEFT 16 1.294 +#define TAB_RIGHT 240 1.295 + 1.296 +void ljmenu_beginTabs(unsigned int padding) { 1.297 + tabsX = TAB_LEFT; 1.298 + tabsPadding = padding; 1.299 +} 1.300 + 1.301 +void ljmenu_addTab(const char *text, int hilite) { 1.302 + unsigned int bgColor = hilite ? 12 : 4; 1.303 + unsigned int w = text ? fontdraw_strWidth(text) : 0; 1.304 + unsigned int left = tabsX; 1.305 + unsigned int right = left + 2 * tabsPadding + w; 1.306 + 1.307 + if (right > TAB_RIGHT) { 1.308 + return; 1.309 + } 1.310 + vwfRectfill(&vwfLayer0, 1.311 + left, TAB_TOP, right, TAB_BOTTOM, 1.312 + bgColor); 1.313 + if (hilite) { 1.314 + vwfHline(&vwfLayer0, 1.315 + left, TAB_TOP, right, 1.316 + bgColor + 1); 1.317 + vwfVline(&vwfLayer0, 1.318 + left, TAB_TOP, TAB_BOTTOM, 1.319 + bgColor + 1); 1.320 + vwfVline(&vwfLayer0, 1.321 + right - 1, TAB_TOP, TAB_BOTTOM, 1.322 + bgColor + 1); 1.323 + } else { 1.324 + vwfHline(&vwfLayer0, 1.325 + left, TAB_BOTTOM - 1, right, 1.326 + bgColor + 1); 1.327 + } 1.328 + if (text) { 1.329 + vwfPuts(&vwfLayer0, text, left + tabsPadding, TAB_TOP); 1.330 + } 1.331 + tabsX = right; 1.332 +} 1.333 + 1.334 +void ljmenu_endTabs(void) { 1.335 + vwfRectfill(&vwfLayer0, 1.336 + tabsX, TAB_TOP, TAB_RIGHT, TAB_BOTTOM - 1, 1.337 + 4); 1.338 + vwfHline(&vwfLayer0, 1.339 + tabsX, TAB_BOTTOM - 1, TAB_RIGHT, 1.340 + 5); 1.341 +} 1.342 + 1.343 +#define PROPPANEL_TOP TAB_BOTTOM 1.344 +#define PROPPANEL_HT 12 1.345 +#define PROPPANEL_ROWS 7 1.346 +#define PROPPANEL_BOTTOM (PROPPANEL_TOP + PROPPANEL_HT * PROPPANEL_ROWS) 1.347 + 1.348 +void ljmenu_propPanelClear(unsigned int nRows) { 1.349 + if (nRows > PROPPANEL_ROWS) { 1.350 + nRows = PROPPANEL_ROWS; 1.351 + } 1.352 + int y = PROPPANEL_TOP + PROPPANEL_HT * nRows; 1.353 + vwfRectfill(&vwfLayer0, 1.354 + TAB_LEFT, PROPPANEL_TOP, TAB_RIGHT, y, 1.355 + 4); 1.356 + vwfRectfill(&vwfLayer0, 1.357 + TAB_LEFT, y, TAB_RIGHT, PROPPANEL_BOTTOM, 1.358 + 0); 1.359 +} 1.360 + 1.361 +void ljmenu_propPanelDrawRow(const char *name, const char *value, 1.362 + unsigned int y, unsigned int hilite) { 1.363 + if (y > PROPPANEL_ROWS) { 1.364 + return; 1.365 + } 1.366 + y = PROPPANEL_TOP + PROPPANEL_HT * y; 1.367 + unsigned int bgColor = hilite ? 12 : 4; 1.368 + 1.369 + vwfRectfill(&vwfLayer0, 1.370 + TAB_LEFT, y, TAB_RIGHT, y + PROPPANEL_HT, 1.371 + bgColor); 1.372 + if (hilite) { 1.373 + vwfRect(&vwfLayer0, 1.374 + TAB_LEFT, y, TAB_RIGHT, y + PROPPANEL_HT, 1.375 + bgColor + 1); 1.376 + } 1.377 + if (name) { 1.378 + vwfPuts(&vwfLayer0, name, TAB_LEFT + 8, y); 1.379 + } 1.380 + if (value) { 1.381 + int x = TAB_RIGHT - 8 - fontdraw_strWidth(value); 1.382 + vwfPuts(&vwfLayer0, value, x, y); 1.383 + } 1.384 +} 1.385 + 1.386 +static void roundrect(const VWFWindow *w, 1.387 + int l, int t, int r, int b, int c) { 1.388 + vwfRectfill(w, l, t + 2, r, b - 2, c); 1.389 + vwfHline(w, l + 2, t, r - 2, c); 1.390 + vwfHline(w, l + 1, t + 1, r - 1, c); 1.391 + vwfHline(w, l + 1, b - 2, r - 1, c); 1.392 + vwfHline(w, l + 2, b - 1, r - 2, c); 1.393 +} 1.394 + 1.395 +static void ljmenu_balloon(const char *text1, const char *text2, 1.396 + int l, int t, int r) { 1.397 + int b = t + (text2 ? 24 : 12); 1.398 + roundrect(&vwfLayer0, l, t, r, b, 4); 1.399 + vwfPuts(&vwfLayer0, text1, l + 4, t); 1.400 + if (text2) { 1.401 + vwfPuts(&vwfLayer0, text2, l + 4, t + 12); 1.402 + } 1.403 +} 1.404 + 1.405 +void ljmenu_propPanelDrawDesc(const char *text1, const char *text2) { 1.406 + ljmenu_balloon(text1, text2, TAB_LEFT, PROPPANEL_BOTTOM + 4, TAB_RIGHT); 1.407 +} 1.408 + 1.409 +void ljmenu_propPanelDrawHelp(const char *text1, const char *text2) { 1.410 + int y = text2 ? 176 - 24 : 176 - 12; 1.411 + ljmenu_balloon(text1, text2, TAB_LEFT, y, TAB_RIGHT); 1.412 +} 1.413 + 1.414 +#if 0 1.415 +static void ljmenu_pressA(void) { 1.416 + int phase = 0; 1.417 + while (!(REG_KEYINPUT & KEY_A)) { 1.418 + ++phase; 1.419 + vsync(); 1.420 + ljmenu_setHilitePalette(phase); 1.421 + } 1.422 + while (REG_KEYINPUT & KEY_A) { 1.423 + ++phase; 1.424 + vsync(); 1.425 + ljmenu_setHilitePalette(phase); 1.426 + } 1.427 +} 1.428 + 1.429 +void ljmenuTest(void) { 1.430 + ljmenu_init(); 1.431 + ljmenu_cls(); 1.432 + ljmenu_setTitle("LOCKJAW 0.43", "© 2008 Damian Yerrick"); 1.433 + ljmenu_drawButton(22, 18, 22 + 8, 18 + 3, "OK"); 1.434 + ljmenu_hiliteButton(22, 18, 22 + 8, 18 + 3, 1); 1.435 + ljmenu_drawButton(13, 18, 13 + 8, 18 + 3, "Cancel"); 1.436 + ljmenu_drawButton(2, 8, 30, 11, 1.437 + "coming soon: the new look of LOCKJAW"); 1.438 + ljmenu_pressA(); 1.439 + 1.440 + ljmenu_cls(); 1.441 + ljmenu_setTitle("LOCKJAW 0.43", "© 2008 Damian Yerrick"); 1.442 + ljmenu_beginTabs(4); 1.443 + ljmenu_addTab("Game", 1); 1.444 + ljmenu_addTab("Well", 0); 1.445 + ljmenu_addTab("Move", 0); 1.446 + ljmenu_addTab("Line", 0); 1.447 + ljmenu_addTab("Ctrl", 0); 1.448 + ljmenu_addTab("Drop", 0); 1.449 + ljmenu_addTab("Disp", 0); 1.450 + ljmenu_endTabs(); 1.451 + ljmenu_propPanelClear(7); 1.452 + ljmenu_propPanelDrawRow("Gimmick", "Marathon", 0, 1); 1.453 + ljmenu_propPanelDrawRow("Mr. Gimmick", "Halo", 1, 0); 1.454 + ljmenu_propPanelDrawDesc("Goal or other game mode", 1.455 + "Play until you <Ganon>DIE.</Ganon>"); 1.456 + ljmenu_propPanelDrawHelp("u d: move; l r: change; L R: page; Start: OK", 1.457 + NULL); 1.458 + ljmenu_pressA(); 1.459 +} 1.460 + 1.461 +#endif